xref: /haiku/src/servers/package/ResultWindow.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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