xref: /haiku/src/apps/installer/PackageViews.cpp (revision 0562493379cd52eb7103531f895f10bb8e77c085)
1 /*
2  * Copyright 2005, Jérôme DUVAL. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <fs_attr.h>
7 #include <Directory.h>
8 #include <Entry.h>
9 #include <Messenger.h>
10 #include <ScrollBar.h>
11 #include <String.h>
12 #include <stdio.h>
13 #include <View.h>
14 #include "PackageViews.h"
15 #include "InstallerWindow.h"
16 
17 #define ICON_ATTRIBUTE "INSTALLER PACKAGE: ICON"
18 
19 void SizeAsString(off_t size, char *string);
20 
21 void
22 SizeAsString(off_t size, char *string)
23 {
24 	double kb = size / 1024.0;
25 	if (kb < 1.0) {
26 		sprintf(string, "%Ld B", size);
27 		return;
28 	}
29 	float mb = kb / 1024.0;
30 	if (mb < 1.0) {
31 		sprintf(string, "%3.1f KB", kb);
32 		return;
33 	}
34 	float gb = mb / 1024.0;
35 	if (gb < 1.0) {
36 		sprintf(string, "%3.1f MB", mb);
37 		return;
38 	}
39 	float tb = gb / 1024.0;
40 	if (tb < 1.0) {
41 		sprintf(string, "%3.1f GB", gb);
42 		return;
43 	}
44 	sprintf(string, "%.1f TB", tb);
45 }
46 
47 
48 Package::Package(const char *folder)
49 	: Group(),
50 	fSize(0),
51 	fIcon(NULL)
52 {
53 	SetFolder(folder);
54 }
55 
56 
57 Package::~Package()
58 {
59 	delete fIcon;
60 }
61 
62 
63 Package *
64 Package::PackageFromEntry(BEntry &entry)
65 {
66 	char folder[B_FILE_NAME_LENGTH];
67 	entry.GetName(folder);
68 	BDirectory directory(&entry);
69 	if (directory.InitCheck() != B_OK)
70 		return NULL;
71 	Package *package = new Package(folder);
72 	bool alwaysOn;
73 	bool onByDefault;
74 	int32 size;
75 	char group[64];
76 	memset(group, 0, 64);
77 	if (directory.ReadAttr("INSTALLER PACKAGE: NAME", B_STRING_TYPE, 0, package->fName, 64) < 0)
78 		goto err;
79 	if (directory.ReadAttr("INSTALLER PACKAGE: GROUP", B_STRING_TYPE, 0, group, 64) < 0)
80 		goto err;
81 	if (directory.ReadAttr("INSTALLER PACKAGE: DESCRIPTION", B_STRING_TYPE, 0, package->fDescription, 64) < 0)
82 		goto err;
83 	if (directory.ReadAttr("INSTALLER PACKAGE: ON_BY_DEFAULT", B_BOOL_TYPE, 0, &onByDefault, sizeof(onByDefault)) < 0)
84 		goto err;
85 	if (directory.ReadAttr("INSTALLER PACKAGE: ALWAYS_ON", B_BOOL_TYPE, 0, &alwaysOn, sizeof(alwaysOn)) < 0)
86 		goto err;
87 	if (directory.ReadAttr("INSTALLER PACKAGE: SIZE", B_INT32_TYPE, 0, &size, sizeof(size)) < 0)
88 		goto err;
89 	package->SetGroupName(group);
90 	package->SetSize(size);
91 	package->SetAlwaysOn(alwaysOn);
92 	package->SetOnByDefault(onByDefault);
93 
94 	attr_info info;
95 	if (directory.GetAttrInfo(ICON_ATTRIBUTE, &info) == B_OK) {
96 		char buffer[info.size];
97 		BMessage msg;
98 		if ((directory.ReadAttr(ICON_ATTRIBUTE, info.type, 0, buffer, info.size) == info.size)
99 			&& (msg.Unflatten(buffer) == B_OK)) {
100 			package->SetIcon(new BBitmap(&msg));
101 		}
102 	}
103 	return package;
104 err:
105 	delete package;
106 	return NULL;
107 }
108 
109 
110 void
111 Package::GetSizeAsString(char *string)
112 {
113 	SizeAsString(fSize, string);
114 }
115 
116 
117 Group::Group()
118 {
119 
120 }
121 
122 Group::~Group()
123 {
124 }
125 
126 
127 PackageCheckBox::PackageCheckBox(BRect rect, Package *item)
128 	: BCheckBox(rect.OffsetBySelf(7, 0), "pack_cb", item->Name(), NULL),
129 	fPackage(item)
130 {
131 }
132 
133 
134 PackageCheckBox::~PackageCheckBox()
135 {
136 	delete fPackage;
137 }
138 
139 
140 void
141 PackageCheckBox::Draw(BRect update)
142 {
143 	BCheckBox::Draw(update);
144 	char string[15];
145 	fPackage->GetSizeAsString(string);
146 	float width = StringWidth(string);
147 	DrawString(string, BPoint(Bounds().right - width - 8, 11));
148 
149 	const BBitmap *icon = fPackage->Icon();
150 	if (icon)
151 		DrawBitmap(icon, BPoint(Bounds().right - 92, 0));
152 }
153 
154 
155 void
156 PackageCheckBox::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
157 {
158 	printf("%s called\n", __PRETTY_FUNCTION__);
159 	if (transit == B_ENTERED_VIEW) {
160 		BMessage msg(STATUS_MESSAGE);
161 		msg.AddString("status", fPackage->Description());
162 		BMessenger(NULL, Window()).SendMessage(&msg);
163 	} else if (transit == B_EXITED_VIEW) {
164 		BMessage msg(STATUS_MESSAGE);
165 		BMessenger(NULL, Window()).SendMessage(&msg);
166 	}
167 }
168 
169 
170 GroupView::GroupView(BRect rect, Group *group)
171 	: BStringView(rect, "group", group->GroupName()),
172 	fGroup(group)
173 {
174 	SetFont(be_bold_font);
175 }
176 
177 
178 GroupView::~GroupView()
179 {
180 	delete fGroup;
181 }
182 
183 
184 PackagesView::PackagesView(BRect rect, const char* name)
185 	: BView(rect, name, B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS)
186 {
187 }
188 
189 
190 PackagesView::~PackagesView()
191 {
192 
193 }
194 
195 
196 void
197 PackagesView::Clean()
198 {
199 	BView *view;
200 	while ((view = ChildAt(0))) {
201 		if (dynamic_cast<GroupView*>(view) || dynamic_cast<PackageCheckBox*>(view)) {
202 			RemoveChild(view);
203 			delete view;
204 		}
205 	}
206 	ScrollTo(0, 0);
207 }
208 
209 
210 void
211 PackagesView::AddPackages(BList &packages, BMessage *msg)
212 {
213 	int32 count = packages.CountItems();
214 	BRect rect = Bounds();
215 	BRect bounds = rect;
216 	rect.left = 1;
217 	rect.bottom = 15;
218 	rect.top = 0;
219 	BString lastGroup = "";
220 	for (int32 i = 0; i < count; i++) {
221 		void *item = packages.ItemAt(i);
222 		Package *package = static_cast<Package *>(item);
223 		if (lastGroup != BString(package->GroupName())) {
224 			rect.OffsetBy(0, 1);
225 			lastGroup = package->GroupName();
226 			Group *group = new Group();
227 			group->SetGroupName(package->GroupName());
228 			GroupView *view = new GroupView(rect, group);
229 			AddChild(view);
230 			rect.OffsetBy(0, 17);
231 		}
232 		PackageCheckBox *checkBox = new PackageCheckBox(rect, package);
233 		checkBox->SetValue(package->OnByDefault() ? B_CONTROL_ON : B_CONTROL_OFF);
234 		checkBox->SetEnabled(!package->AlwaysOn());
235 		checkBox->SetMessage(new BMessage(*msg));
236 		AddChild(checkBox);
237 		rect.OffsetBy(0, 20);
238 	}
239 	ResizeTo(bounds.Width(), rect.top);
240 
241 	BScrollBar *vertScroller = ScrollBar(B_VERTICAL);
242 
243 	if (vertScroller->Bounds().Height() > rect.top) {
244 		vertScroller->SetRange(0.0f, 0.0f);
245 		vertScroller->SetValue(0.0f);
246 	} else {
247 		vertScroller->SetRange(0.0f, rect.top - vertScroller->Bounds().Height());
248 		vertScroller->SetProportion(vertScroller->Bounds().Height() / rect.top);
249 	}
250 
251 	vertScroller->SetSteps(15, vertScroller->Bounds().Height());
252 
253 	Invalidate();
254 }
255 
256 
257 void
258 PackagesView::GetTotalSizeAsString(char *string)
259 {
260 	int32 count = CountChildren();
261 	int32 size = 0;
262 	for (int32 i = 0; i < count; i++) {
263 		PackageCheckBox *cb = dynamic_cast<PackageCheckBox*>(ChildAt(i));
264 		if (cb && cb->Value())
265 			size += cb->GetPackage()->Size();
266 	}
267 	SizeAsString(size, string);
268 }
269 
270 
271 void
272 PackagesView::GetPackagesToInstall(BList *list, int32 *size)
273 {
274 	int32 count = CountChildren();
275 	*size = 0;
276 	for (int32 i = 0; i < count; i++) {
277 		PackageCheckBox *cb = dynamic_cast<PackageCheckBox*>(ChildAt(i));
278 		if (cb && cb->Value()) {
279 			list->AddItem(cb->GetPackage());
280 			*size += cb->GetPackage()->Size();
281 		}
282 	}
283 }
284 
285