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