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