1 /* 2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "ResultWindow.h" 8 9 #include <Button.h> 10 #include <GroupView.h> 11 #include <LayoutBuilder.h> 12 #include <ScrollView.h> 13 #include <StringView.h> 14 #include <package/solver/SolverPackage.h> 15 #include <package/solver/SolverRepository.h> 16 17 #include <AutoDeleter.h> 18 #include <AutoLocker.h> 19 #include <ViewPort.h> 20 21 22 using namespace BPackageKit; 23 24 25 static const uint32 kApplyMessage = 'rtry'; 26 27 28 ResultWindow::ResultWindow() 29 : 30 BWindow(BRect(0, 0, 400, 300), "Package changes", B_TITLED_WINDOW_LOOK, 31 B_NORMAL_WINDOW_FEEL, 32 B_ASYNCHRONOUS_CONTROLS | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS, 33 B_ALL_WORKSPACES), 34 fDoneSemaphore(-1), 35 fClientWaiting(false), 36 fAccepted(false), 37 fContainerView(NULL), 38 fCancelButton(NULL), 39 fApplyButton(NULL) 40 41 { 42 fDoneSemaphore = create_sem(0, "package changes"); 43 if (fDoneSemaphore < 0) 44 throw std::bad_alloc(); 45 46 BStringView* topTextView = NULL; 47 BViewPort* viewPort = NULL; 48 49 BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) 50 .SetInsets(B_USE_SMALL_INSETS) 51 .Add(topTextView = new BStringView(NULL, 52 "The following additional package changes have to be made:")) 53 .Add(new BScrollView(NULL, viewPort = new BViewPort(), 0, false, true)) 54 .AddGroup(B_HORIZONTAL) 55 .Add(fCancelButton = new BButton("Cancel", new BMessage(B_CANCEL))) 56 .AddGlue() 57 .Add(fApplyButton = new BButton("Apply changes", 58 new BMessage(kApplyMessage))) 59 .End(); 60 61 topTextView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 62 63 viewPort->SetChildView(fContainerView = new BGroupView(B_VERTICAL, 0)); 64 65 // set small scroll step (large step will be set by the view port) 66 font_height fontHeight; 67 topTextView->GetFontHeight(&fontHeight); 68 float smallStep = ceilf(fontHeight.ascent + fontHeight.descent); 69 viewPort->ScrollBar(B_VERTICAL)->SetSteps(smallStep, smallStep); 70 } 71 72 73 ResultWindow::~ResultWindow() 74 { 75 if (fDoneSemaphore >= 0) 76 delete_sem(fDoneSemaphore); 77 } 78 79 80 bool 81 ResultWindow::AddLocationChanges(const char* location, 82 const PackageList& packagesToInstall, 83 const PackageSet& packagesAlreadyAdded, 84 const PackageList& packagesToUninstall, 85 const PackageSet& packagesAlreadyRemoved) 86 { 87 BGroupView* locationGroup = new BGroupView(B_VERTICAL); 88 ObjectDeleter<BGroupView> locationGroupDeleter(locationGroup); 89 90 locationGroup->GroupLayout()->SetInsets(B_USE_SMALL_INSETS); 91 92 float backgroundTint = B_NO_TINT; 93 if ((fContainerView->CountChildren() & 1) != 0) 94 backgroundTint = 1.04; 95 locationGroup->SetViewUIColor(B_LIST_BACKGROUND_COLOR, backgroundTint); 96 97 BStringView* locationView = new BStringView(NULL, 98 BString().SetToFormat("in %s:", location)); 99 locationGroup->AddChild(locationView); 100 locationView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 101 locationView->AdoptParentColors(); 102 BFont locationFont; 103 locationView->GetFont(&locationFont); 104 locationFont.SetFace(B_BOLD_FACE); 105 locationView->SetFont(&locationFont); 106 107 BGroupLayout* packagesGroup = new BGroupLayout(B_VERTICAL); 108 locationGroup->GroupLayout()->AddItem(packagesGroup); 109 packagesGroup->SetInsets(20, 0, 0, 0); 110 111 bool packagesAdded = _AddPackages(packagesGroup, packagesToInstall, 112 packagesAlreadyAdded, true); 113 packagesAdded |= _AddPackages(packagesGroup, packagesToUninstall, 114 packagesAlreadyRemoved, false); 115 116 if (!packagesAdded) 117 return false; 118 119 fContainerView->AddChild(locationGroup); 120 locationGroupDeleter.Detach(); 121 122 return true; 123 } 124 125 126 bool 127 ResultWindow::Go() 128 { 129 AutoLocker<ResultWindow> locker(this); 130 131 CenterOnScreen(); 132 Show(); 133 134 fAccepted = false; 135 fClientWaiting = true; 136 137 locker.Unlock(); 138 139 while (acquire_sem(fDoneSemaphore) == B_INTERRUPTED) { 140 } 141 142 locker.Lock(); 143 bool result = false; 144 if (locker.IsLocked()) { 145 result = fAccepted; 146 Quit(); 147 locker.Detach(); 148 } else 149 PostMessage(B_QUIT_REQUESTED); 150 151 return result; 152 } 153 154 155 bool 156 ResultWindow::QuitRequested() 157 { 158 if (fClientWaiting) { 159 Hide(); 160 fClientWaiting = false; 161 release_sem(fDoneSemaphore); 162 return false; 163 } 164 165 return true; 166 } 167 168 169 void 170 ResultWindow::MessageReceived(BMessage* message) 171 { 172 switch (message->what) { 173 case B_CANCEL: 174 case kApplyMessage: 175 Hide(); 176 fAccepted = message->what == kApplyMessage; 177 fClientWaiting = false; 178 release_sem(fDoneSemaphore); 179 break; 180 default: 181 BWindow::MessageReceived(message); 182 break; 183 } 184 } 185 186 187 bool 188 ResultWindow::_AddPackages(BGroupLayout* packagesGroup, 189 const PackageList& packages, const PackageSet& ignorePackages, bool install) 190 { 191 bool packagesAdded = false; 192 193 for (int32 i = 0; BSolverPackage* package = packages.ItemAt(i); 194 i++) { 195 if (ignorePackages.find(package) != ignorePackages.end()) 196 continue; 197 198 BString text; 199 if (install) { 200 text.SetToFormat("install package %s from repository %s\n", 201 package->Info().FileName().String(), 202 package->Repository()->Name().String()); 203 } else { 204 text.SetToFormat("uninstall package %s\n", 205 package->VersionedName().String()); 206 } 207 208 BStringView* packageView = new BStringView(NULL, text); 209 packagesGroup->AddView(packageView); 210 packageView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 211 packageView->AdoptParentColors(); 212 213 packagesAdded = true; 214 } 215 216 return packagesAdded; 217 } 218