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