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 37 Package::Package(const BPath &path) 38 : 39 Group(), 40 fSize(0), 41 fIcon(NULL) 42 { 43 SetPath(path); 44 } 45 46 47 Package::~Package() 48 { 49 delete fIcon; 50 } 51 52 53 Package * 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 119 Package::GetSizeAsString(char* string, size_t stringSize) 120 { 121 string_for_size(fSize, string, stringSize); 122 } 123 124 125 Group::Group() 126 { 127 128 } 129 130 Group::~Group() 131 { 132 } 133 134 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 146 PackageCheckBox::~PackageCheckBox() 147 { 148 delete fPackage; 149 } 150 151 152 void 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 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 183 GroupView::GroupView(Group *group) 184 : 185 BStringView("group", group->GroupName()), 186 fGroup(group) 187 { 188 SetFont(be_bold_font); 189 } 190 191 192 GroupView::~GroupView() 193 { 194 delete fGroup; 195 } 196 197 198 // #pragma mark - 199 200 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 215 PackagesView::~PackagesView() 216 { 217 218 } 219 220 221 void 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 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 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 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 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