xref: /haiku/src/apps/installer/PackageViews.cpp (revision f1e5a6c914a9341f2b874f43b8f945db7c895d4c)
1 /*
2  * Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
3  * Copyright 2005, Jérôme DUVAL.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 #include "PackageViews.h"
8 
9 #include <stdio.h>
10 
11 #include <Catalog.h>
12 #include <ControlLook.h>
13 #include <Directory.h>
14 #include <Entry.h>
15 #include <fs_attr.h>
16 #include <GroupLayout.h>
17 #include <LayoutUtils.h>
18 #include <Locale.h>
19 #include <Messenger.h>
20 #include <package/PackageInfo.h>
21 #include <Path.h>
22 #include <ScrollBar.h>
23 #include <String.h>
24 #include <View.h>
25 #include <Window.h>
26 
27 #include "InstallerDefs.h"
28 #include "StringForSize.h"
29 
30 
31 #undef B_TRANSLATION_CONTEXT
32 #define B_TRANSLATION_CONTEXT "PackagesView"
33 
34 #define ICON_ATTRIBUTE "INSTALLER PACKAGE: ICON"
35 
36 
Package(const BPath & path)37 Package::Package(const BPath &path)
38 	:
39 	Group(),
40 	fSize(0),
41 	fIcon(NULL)
42 {
43 	SetPath(path);
44 }
45 
46 
~Package()47 Package::~Package()
48 {
49 	delete fIcon;
50 }
51 
52 
53 Package *
PackageFromEntry(BEntry & entry)54 Package::PackageFromEntry(BEntry &entry)
55 {
56 	BPath path;
57 	entry.GetPath(&path);
58 
59 	BPackageKit::BPackageInfo info;
60 	info.ReadFromPackageFile(path.Path());
61 
62 	if (info.InitCheck() != B_OK)
63 		return NULL;
64 
65 	Package *package = new Package(path);
66 	package->fName = info.Name();
67 	package->fDescription = info.Summary();
68 
69 	bool alwaysOn = false;
70 	bool onByDefault = true;
71 	off_t size = 0;
72 	entry.GetSize(&size);
73 	char group[64];
74 	memset(group, 0, 64);
75 
76 	BNode node(&entry);
77 	// FIXME enable these when the attributes on the packages are actually
78 	// populated by the buildsystem. For now, assume everything is
79 	// on-by-default and optional, and have no groups.
80 #if 0
81 	if (node.ReadAttr("INSTALLER PACKAGE: GROUP", B_STRING_TYPE, 0,
82 		group, 64) < 0) {
83 		goto err;
84 	}
85 	if (node.ReadAttr("INSTALLER PACKAGE: ON_BY_DEFAULT", B_BOOL_TYPE, 0,
86 		&onByDefault, sizeof(onByDefault)) < 0) {
87 		goto err;
88 	}
89 	if (node.ReadAttr("INSTALLER PACKAGE: ALWAYS_ON", B_BOOL_TYPE, 0,
90 		&alwaysOn, sizeof(alwaysOn)) < 0) {
91 		goto err;
92 	}
93 #endif
94 	package->SetGroupName(group);
95 	package->SetSize(size);
96 	package->SetAlwaysOn(alwaysOn);
97 	package->SetOnByDefault(onByDefault);
98 
99 	attr_info attributes;
100 	if (node.GetAttrInfo(ICON_ATTRIBUTE, &attributes) == B_OK) {
101 		char buffer[attributes.size];
102 		BMessage msg;
103 		if ((node.ReadAttr(ICON_ATTRIBUTE, attributes.type, 0, buffer,
104 				attributes.size) == attributes.size)
105 			&& (msg.Unflatten(buffer) == B_OK)) {
106 			package->SetIcon(new BBitmap(&msg));
107 		}
108 	}
109 	return package;
110 #if 0
111 err:
112 #endif
113 	delete package;
114 	return NULL;
115 }
116 
117 
118 void
GetSizeAsString(char * string,size_t stringSize)119 Package::GetSizeAsString(char* string, size_t stringSize)
120 {
121 	string_for_size(fSize, string, stringSize);
122 }
123 
124 
Group()125 Group::Group()
126 {
127 
128 }
129 
~Group()130 Group::~Group()
131 {
132 }
133 
134 
PackageCheckBox(Package * item)135 PackageCheckBox::PackageCheckBox(Package *item)
136 	:
137 	BCheckBox("pack_cb", item->Name(), NULL),
138 	fPackage(item)
139 {
140 	SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
141 	SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE);
142 	SetIcon(fPackage->Icon());
143 }
144 
145 
~PackageCheckBox()146 PackageCheckBox::~PackageCheckBox()
147 {
148 	delete fPackage;
149 }
150 
151 
152 void
Draw(BRect update)153 PackageCheckBox::Draw(BRect update)
154 {
155 	BCheckBox::Draw(update);
156 
157 	// Draw the label
158 	char string[15];
159 	fPackage->GetSizeAsString(string, sizeof(string));
160 	float width = StringWidth(string);
161 	BRect sizeRect = Bounds();
162 	sizeRect.left = sizeRect.right - width;
163 	be_control_look->DrawLabel(this, string, NULL, sizeRect, update,
164 		ui_color(B_DOCUMENT_BACKGROUND_COLOR), be_control_look->Flags(this));
165 }
166 
167 
168 void
MouseMoved(BPoint point,uint32 transit,const BMessage * dragMessage)169 PackageCheckBox::MouseMoved(BPoint point, uint32 transit,
170 	const BMessage* dragMessage)
171 {
172 	if (transit == B_ENTERED_VIEW) {
173 		BMessage msg(MSG_STATUS_MESSAGE);
174 		msg.AddString("status", fPackage->Description());
175 		BMessenger(NULL, Window()).SendMessage(&msg);
176 	} else if (transit == B_EXITED_VIEW) {
177 		BMessage msg(MSG_STATUS_MESSAGE);
178 		BMessenger(NULL, Window()).SendMessage(&msg);
179 	}
180 }
181 
182 
GroupView(Group * group)183 GroupView::GroupView(Group *group)
184 	:
185 	BStringView("group", group->GroupName()),
186 	fGroup(group)
187 {
188 	SetFont(be_bold_font);
189 }
190 
191 
~GroupView()192 GroupView::~GroupView()
193 {
194 	delete fGroup;
195 }
196 
197 
198 // #pragma mark -
199 
200 
PackagesView(const char * name)201 PackagesView::PackagesView(const char* name)
202 	:
203 	BView(name, B_WILL_DRAW)
204 {
205 	BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
206 	layout->SetSpacing(0);
207 	layout->SetInsets(B_USE_SMALL_SPACING, 0);
208 	SetLayout(layout);
209 
210 	SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR);
211 	SetExplicitMinSize(BSize(B_SIZE_UNSET, 80));
212 }
213 
214 
~PackagesView()215 PackagesView::~PackagesView()
216 {
217 
218 }
219 
220 
221 void
Clean()222 PackagesView::Clean()
223 {
224 	BView* view;
225 	while ((view = ChildAt(0))) {
226 		if (dynamic_cast<GroupView*>(view)
227 			|| dynamic_cast<PackageCheckBox*>(view)) {
228 			RemoveChild(view);
229 			delete view;
230 		}
231 	}
232 	ScrollTo(0, 0);
233 
234 	BView* parent = Parent();
235 	BRect r = parent->Bounds();
236 	parent->FrameResized(r.Width(), r.Height());
237 }
238 
239 
240 void
AddPackages(BList & packages,BMessage * msg)241 PackagesView::AddPackages(BList& packages, BMessage* msg)
242 {
243 	int32 count = packages.CountItems();
244 	BString lastGroup = "";
245 	for (int32 i = 0; i < count; i++) {
246 		void* item = packages.ItemAt(i);
247 		Package* package = static_cast<Package*>(item);
248 		if (lastGroup != BString(package->GroupName())) {
249 			lastGroup = package->GroupName();
250 			Group* group = new Group();
251 			group->SetGroupName(package->GroupName());
252 			GroupView *view = new GroupView(group);
253 			AddChild(view);
254 		}
255 		PackageCheckBox* checkBox = new PackageCheckBox(package);
256 		checkBox->SetValue(package->OnByDefault()
257 			? B_CONTROL_ON : B_CONTROL_OFF);
258 		checkBox->SetEnabled(!package->AlwaysOn());
259 		checkBox->SetMessage(new BMessage(*msg));
260 		AddChild(checkBox);
261 	}
262 	Invalidate();
263 
264 	// Force scrollbars to update
265 	BView* parent = Parent();
266 	BRect r = parent->Bounds();
267 	parent->FrameResized(r.Width(), r.Height());
268 }
269 
270 
271 void
GetTotalSizeAsString(char * string,size_t stringSize)272 PackagesView::GetTotalSizeAsString(char* string, size_t stringSize)
273 {
274 	int32 count = CountChildren();
275 	int32 size = 0;
276 	for (int32 i = 0; i < count; i++) {
277 		PackageCheckBox* cb = dynamic_cast<PackageCheckBox*>(ChildAt(i));
278 		if (cb && cb->Value())
279 			size += cb->GetPackage()->Size();
280 	}
281 	string_for_size(size, string, stringSize);
282 }
283 
284 
285 void
GetPackagesToInstall(BList * list,int32 * size)286 PackagesView::GetPackagesToInstall(BList* list, int32* size)
287 {
288 	int32 count = CountChildren();
289 	*size = 0;
290 	for (int32 i = 0; i < count; i++) {
291 		PackageCheckBox* cb = dynamic_cast<PackageCheckBox*>(ChildAt(i));
292 		if (cb && cb->Value()) {
293 			list->AddItem(cb->GetPackage());
294 			*size += cb->GetPackage()->Size();
295 		}
296 	}
297 }
298 
299 
300 void
Draw(BRect updateRect)301 PackagesView::Draw(BRect updateRect)
302 {
303 	if (CountChildren() > 0)
304 		return;
305 
306 	be_control_look->DrawLabel(this,
307 		B_TRANSLATE("No optional packages available."),
308 		Bounds(), updateRect, ViewColor(), BControlLook::B_DISABLED,
309 		BAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE));
310 }
311