ADDING the InstalledPackages application originally created by Łukasz Zemczak

for Summer of Code 2007. It probably still needs some work but it is better put
into SVN than sitting on my machine. I figure it might one day be morphed
into a simple Haiku package manager (though maybe we don't want that...)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27395 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ryan Leavengood 2008-09-10 05:36:45 +00:00
parent a2b5ecab7a
commit e2e25120bc
7 changed files with 587 additions and 0 deletions

View File

@ -19,6 +19,7 @@ SubInclude HAIKU_TOP src apps expander ;
SubInclude HAIKU_TOP src apps fontdemo ;
SubInclude HAIKU_TOP src apps glteapot ;
SubInclude HAIKU_TOP src apps icon-o-matic ;
SubInclude HAIKU_TOP src apps installedpackages ;
SubInclude HAIKU_TOP src apps installer ;
SubInclude HAIKU_TOP src apps launchbox ;
SubInclude HAIKU_TOP src apps login ;

View File

@ -0,0 +1,17 @@
SubDir HAIKU_TOP src apps installedpackages ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders shared interface ;
SubDirHdrs $(HAIKU_TOP) src apps packageinstaller ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits interface ] ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps packageinstaller ] ;
Application InstalledPackages :
InstalledPackageInfo.cpp
main.cpp
UninstallWindow.cpp
UninstallView.cpp
: be tracker
;

View File

@ -0,0 +1,368 @@
/*
* Copyright (c) 2007, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
*/
#include "UninstallView.h"
#include <Alert.h>
#include <String.h>
#include <Directory.h>
#include <File.h>
#include <Entry.h>
#include <Button.h>
#include <Box.h>
#include <StringView.h>
#include <NodeMonitor.h>
#include <FindDirectory.h>
#include <stdio.h>
enum {
P_MSG_REMOVE = 'umrm',
P_MSG_SELECT
};
// Reserved
#define T(x) x
// TODO list:
// - B_ENTRY_MOVED
// - Right now the installed package info naming convention is the same
// as at SoftwareValet. Maybe there would be a better one?
// - Add a status window (reuse the one from PackageInstall)
class UninstallView::InfoItem : public BStringItem {
public:
InfoItem(const char *name, const char *version, node_ref ref)
: BStringItem(name),
fVersion(version),
fNodeRef(ref)
{
}
const char * GetName() { return BStringItem::Text(); }
const char * GetVersion() { return fVersion.String(); };
node_ref GetNodeRef() { return fNodeRef; };
private:
BString fVersion;
node_ref fNodeRef;
};
UninstallView::UninstallView(BRect frame)
: BView(frame, "uninstall_view", B_FOLLOW_NONE, 0)
{
_InitView();
}
UninstallView::~UninstallView()
{
_ClearAppList();
// Stop all node watching
stop_watching(this);
}
void
UninstallView::AttachedToWindow()
{
fAppList->SetTarget(this);
fButton->SetTarget(this);
_ReloadAppList();
// We loaded the list, but now let's set up a node watcher for the packages
// directory, so that we can update the list of installed packages in real
// time
_CachePathToPackages();
node_ref ref;
fWatcherRunning = false;
BDirectory dir(fToPackages.Path());
if (dir.InitCheck() != B_OK) {
// The packages/ directory obviously does not exist.
// Since this is the case, we need to watch for it to appear first
BPath path;
fToPackages.GetParent(&path);
if (dir.SetTo(path.Path()) != B_OK)
return;
}
else
fWatcherRunning = true;
dir.GetNodeRef(&ref);
if (watch_node(&ref, B_WATCH_DIRECTORY, this) != B_OK) {
fWatcherRunning = false;
return;
}
}
void
UninstallView::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case B_NODE_MONITOR:
{
int32 opcode;
if (msg->FindInt32("opcode", &opcode) != B_OK)
break;
fprintf(stderr, "Got an opcoded node monitor message\n");
if (opcode == B_ENTRY_CREATED) {
fprintf(stderr, "Created?...\n");
BString filename, name, version;
node_ref ref;
if (msg->FindString("name", &filename) != B_OK ||
msg->FindInt32("device", &ref.device) != B_OK ||
msg->FindInt64("node", &ref.node) != B_OK)
break;
// TODO: This obviously is a hack
// The node watcher informs the view a bit to early, and because
// of this the data of the node is not ready at this moment.
// For this reason, we must give the filesystem some time before
// continuing.
usleep(10000);
if (fWatcherRunning) {
name = info_get_package_name(filename.String());
version = info_get_package_version(filename.String());
fAppList->AddItem(new InfoItem(name.String(), version.String(), ref));
}
else {
// This most likely means we were waiting for the packages/ dir
// to appear
if (filename == "packages") {
if (watch_node(&ref, B_WATCH_DIRECTORY, this) == B_OK)
fWatcherRunning = true;
}
}
}
else if (opcode == B_ENTRY_REMOVED) {
node_ref ref;
if (msg->FindInt32("device", &ref.device) != B_OK ||
msg->FindInt64("node", &ref.node) != B_OK)
break;
int32 i, count = fAppList->CountItems();
InfoItem *iter;
for (i = 0;i < count;i++) {
iter = static_cast<InfoItem *>(fAppList->ItemAt(i));
if (iter->GetNodeRef() == ref) {
if (i == fAppList->CurrentSelection())
fDescription->SetText(T("No package selected"));
fAppList->RemoveItem(i);
delete iter;
}
}
}
else if (opcode == B_ENTRY_MOVED) {
ino_t from, to;
if (msg->FindInt64("from directory", &from) != B_OK ||
msg->FindInt64("to directory", &to) != B_OK)
break;
BDirectory packagesDir(fToPackages.Path());
node_ref ref;
packagesDir.GetNodeRef(&ref);
if (ref.node == to) {
// Package added
// TODO
}
else if (ref.node == from) {
// Package removed
// TODO
}
}
break;
}
case P_MSG_SELECT:
{
int32 index = fAppList->CurrentSelection();
if (index < 0)
break;
fprintf(stderr, "Another debug message...\n");
InfoItem *item = dynamic_cast<InfoItem *>(fAppList->ItemAt(index));
if (!item)
break;
fprintf(stderr, "Uh: %s and %s\n", item->GetName(), item->GetVersion());
if (fCurrentSelection.SetTo(item->GetName(), item->GetVersion()) != B_OK)
break;
fprintf(stderr, " ...how much longer?\n");
fDescription->SetText(fCurrentSelection.GetDescription());
break;
}
case P_MSG_REMOVE:
{
if (fCurrentSelection.InitCheck() != B_OK)
break;
int32 index = fAppList->CurrentSelection();
if (index < 0)
break;
BAlert *notify;
if (fCurrentSelection.Uninstall() == B_OK) {
BListItem *item = static_cast<BListItem *>(fAppList->ItemAt(index));
fAppList->RemoveItem(index);
delete item;
fDescription->SetText(T("No package selected"));
notify = new BAlert("removal_success",
T("The package you selected has been successfully removed "
"from your system."), T("OK"));
}
else
notify = new BAlert("removal_failed",
T("The selected package was not removed from your system. The "
"given installed package information file might have been "
"corrupted."), T("OK"), NULL,
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
notify->Go();
}
default:
BView::MessageReceived(msg);
break;
}
}
void
UninstallView::_InitView()
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BRect rect = Bounds().InsetBySelf(10.0f, 10.0f);
rect.bottom = 125.0f;
rect.right -= B_V_SCROLL_BAR_WIDTH;
fAppList = new BListView(rect, "pkg_list", B_SINGLE_SELECTION_LIST,
B_FOLLOW_NONE);
fAppList->SetSelectionMessage(new BMessage(P_MSG_SELECT));
BScrollView *scroll = new BScrollView("list_scroll", fAppList, B_FOLLOW_NONE,
0, false, true);
AddChild(scroll);
rect.top = rect.bottom + 8.0f;
rect.bottom += 120.0f;
rect.right += B_V_SCROLL_BAR_WIDTH;
BBox *box = new BBox(rect, "desc_box");
BStringView *descLabel = new BStringView(BRect(3, 3, 10, 10), "desc_label",
T("Package description:"));
descLabel->ResizeToPreferred();
box->AddChild(descLabel);
BRect inside = box->Bounds().InsetBySelf(3.0f, 3.0f);
inside.top = descLabel->Frame().bottom + 10.0f;
inside.right -= B_V_SCROLL_BAR_WIDTH;
fDescription = new BTextView(inside, "description",
BRect(0, 0, inside.Width(), inside.Height()), B_FOLLOW_NONE, B_WILL_DRAW);
fDescription->MakeSelectable(true);
fDescription->MakeEditable(false);
fDescription->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fDescription->SetText(T("No package selected."));
fDescScroll = new BScrollView("desc_scroll", fDescription, B_FOLLOW_NONE,
0, false, true, B_NO_BORDER);
box->AddChild(fDescScroll);
AddChild(box);
fButton = new BButton(BRect(0, 0, 1, 1), "removal", T("Remove"),
new BMessage(P_MSG_REMOVE));
fButton->ResizeToPreferred();
rect.top = rect.bottom + 5.0f;
rect.left = Bounds().Width() - 5.0f - fButton->Bounds().Width();
fButton->MoveTo(rect.LeftTop());
AddChild(fButton);
ResizeTo(Bounds().Width(), fButton->Frame().bottom + 10.0f);
}
status_t
UninstallView::_ReloadAppList()
{
_ClearAppList();
if (fToPackages.InitCheck() != B_OK)
_CachePathToPackages();
BDirectory dir(fToPackages.Path());
status_t ret = dir.InitCheck();
if (ret != B_OK)
return ret;
fprintf(stderr, "Ichi! %s\n", fToPackages.Path());
BEntry iter;
node_ref ref;
char filename[B_FILE_NAME_LENGTH];
BString name, version;
while (1) {
ret = dir.GetNextEntry(&iter);
if (ret != B_OK)
break;
fprintf(stderr, "Found one!\n");
iter.GetName(filename);
iter.GetNodeRef(&ref);
name = info_get_package_name(filename);
version = info_get_package_version(filename);
fAppList->AddItem(new InfoItem(name.String(), version.String(), ref));
}
if (ret != B_ENTRY_NOT_FOUND)
return ret;
return B_OK;
}
void
UninstallView::_ClearAppList()
{
int32 i, count = fAppList->CountItems();
BListItem *iter = 0;
for (i = 0;i < count;i++) {
iter = static_cast<BListItem *>(fAppList->ItemAt(0));
fAppList->RemoveItem((int32)0);
delete iter;
}
}
void
UninstallView::_CachePathToPackages()
{
if (find_directory(B_USER_CONFIG_DIRECTORY, &fToPackages) != B_OK)
return;
if (fToPackages.Append(kPackagesDir) != B_OK)
return;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2007, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
*/
#ifndef UNINSTALLVIEW_H
#define UNINSTALLVIEW_H
#include "InstalledPackageInfo.h"
#include <View.h>
#include <Layout.h>
#include <ListView.h>
#include <ScrollView.h>
#include <Button.h>
#include <TextView.h>
#include <Path.h>
class UninstallView : public BView {
public:
UninstallView(BRect frame);
~UninstallView();
void AttachedToWindow();
void MessageReceived(BMessage *msg);
private:
class InfoItem;
void _InitView();
status_t _ReloadAppList();
void _ClearAppList();
void _CachePathToPackages();
BPath fToPackages;
BListView *fAppList;
BTextView *fDescription;
BButton *fButton;
BScrollView *fDescScroll;
InstalledPackageInfo fCurrentSelection;
bool fWatcherRunning;
};
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2007, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
*/
#include "UninstallWindow.h"
#include <Application.h>
// Macro reserved for later localization
#define T(x) x
UninstallWindow::UninstallWindow()
: BWindow(BRect(100, 100, 600, 300), T("Installed packages"),
B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
{
fBackground = new UninstallView(Bounds());
AddChild(fBackground);
ResizeTo(Bounds().Width(), fBackground->Bounds().Height());
}
UninstallWindow::~UninstallWindow()
{
RemoveChild(fBackground);
delete fBackground;
}
bool
UninstallWindow::QuitRequested()
{
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2007, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
*/
#ifndef UNINSTALLWINDOW_H
#define UNINSTALLWINDOW_H
#include "UninstallView.h"
#include <Window.h>
#include <Entry.h>
class UninstallWindow : public BWindow {
public:
UninstallWindow();
~UninstallWindow();
bool QuitRequested();
private:
UninstallView *fBackground;
};
#endif

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2007, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
*/
#include "UninstallWindow.h"
#include <Application.h>
#include <List.h>
#include <Alert.h>
#include <TextView.h>
#include <Entry.h>
#include <Autolock.h>
#include <stdio.h>
class UninstallApplication : public BApplication {
public:
UninstallApplication();
~UninstallApplication();
void MessageReceived(BMessage *msg);
void AboutRequested();
private:
UninstallWindow *fWindow;
};
UninstallApplication::UninstallApplication()
: BApplication("application/x-vnd.Haiku-InstalledPackages")
{
fWindow = new UninstallWindow();
fWindow->Show();
}
UninstallApplication::~UninstallApplication()
{
}
void
UninstallApplication::MessageReceived(BMessage *msg)
{
switch (msg->what) {
default:
BApplication::MessageReceived(msg);
}
}
void
UninstallApplication::AboutRequested()
{
BAlert *about = new BAlert("about",
"InstalledPackages\n"
"BeOS legacy .pkg package removing application for Haiku.\n\n"
"Copyright 2007,\nŁukasz 'Sil2100' Zemczak\n\n"
"Copyright (c) 2007 Haiku, Inc. \n",
"Close");
BTextView *view = about->TextView();
BFont font;
view->SetStylable(true);
view->GetFont(&font);
font.SetFace(B_BOLD_FACE);
font.SetSize(font.Size() * 1.5);
view->SetFontAndColor(0, 15, &font);
about->Go();
}
int
main(void)
{
UninstallApplication app;
app.Run();
return 0;
}