144f919daSRyan Leavengood/*
2a1b7cb62SStephan Aßmus * Copyright 2007-2014, Haiku, Inc.
344f919daSRyan Leavengood * Distributed under the terms of the MIT license.
444f919daSRyan Leavengood *
544f919daSRyan Leavengood * Author:
644f919daSRyan Leavengood *		��ukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
7735727daSStephan Aßmus *		Stephan A��mus <superstippi@gmx.de>
844f919daSRyan Leavengood */
944f919daSRyan Leavengood
10f51cdb44SStephan Aßmus
1144f919daSRyan Leavengood#include "InstalledPackageInfo.h"
1244f919daSRyan Leavengood#include "PackageImageViewer.h"
1344f919daSRyan Leavengood#include "PackageTextViewer.h"
1444f919daSRyan Leavengood#include "PackageView.h"
1544f919daSRyan Leavengood
1644f919daSRyan Leavengood#include <Alert.h>
17a1b7cb62SStephan Aßmus#include <Box.h>
1844f919daSRyan Leavengood#include <Button.h>
19091440e0SStephan Aßmus#include <Catalog.h>
2044f919daSRyan Leavengood#include <Directory.h>
21a1b7cb62SStephan Aßmus#include <FilePanel.h>
2244f919daSRyan Leavengood#include <FindDirectory.h>
23091440e0SStephan Aßmus#include <Locale.h>
24735727daSStephan Aßmus#include <LayoutBuilder.h>
25a1b7cb62SStephan Aßmus#include <MenuField.h>
2644f919daSRyan Leavengood#include <MenuItem.h>
2744f919daSRyan Leavengood#include <Path.h>
2844f919daSRyan Leavengood#include <PopUpMenu.h>
2944f919daSRyan Leavengood#include <ScrollView.h>
300cec9e76SAugustin Cavalier#include <StringForSize.h>
3144f919daSRyan Leavengood#include <TextView.h>
3244f919daSRyan Leavengood#include <Volume.h>
3344f919daSRyan Leavengood#include <VolumeRoster.h>
3444f919daSRyan Leavengood#include <Window.h>
3544f919daSRyan Leavengood
3644f919daSRyan Leavengood#include <GroupLayout.h>
3744f919daSRyan Leavengood#include <GroupLayoutBuilder.h>
3844f919daSRyan Leavengood#include <GroupView.h>
3944f919daSRyan Leavengood
4044f919daSRyan Leavengood#include <fs_info.h>
4144f919daSRyan Leavengood#include <stdio.h> // For debugging
4244f919daSRyan Leavengood
43091440e0SStephan Aßmus
44546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
45546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "PackageView"
4644f919daSRyan Leavengood
4744f919daSRyan Leavengoodconst float kMaxDescHeight = 125.0f;
4844f919daSRyan Leavengoodconst uint32 kSeparatorIndex = 3;
4944f919daSRyan Leavengood
5044f919daSRyan Leavengood
5144f919daSRyan Leavengood// #pragma mark -
5244f919daSRyan Leavengood
5344f919daSRyan Leavengood
54735727daSStephan AßmusPackageView::PackageView(const entry_ref* ref)
55091440e0SStephan Aßmus	:
56735727daSStephan Aßmus	BView("package_view", 0),
57091440e0SStephan Aßmus	fOpenPanel(new BFilePanel(B_OPEN_PANEL, NULL, NULL, B_DIRECTORY_NODE,
58091440e0SStephan Aßmus		false)),
59792a46dbSStephan Aßmus	fExpectingOpenPanelResult(false),
609ff2343bSJérôme Duval	fInfo(ref),
619ff2343bSJérôme Duval	fInstallProcess(this)
6244f919daSRyan Leavengood{
6344f919daSRyan Leavengood	_InitView();
6444f919daSRyan Leavengood
6544f919daSRyan Leavengood	// Check whether the package has been successfuly parsed
6644f919daSRyan Leavengood	status_t ret = fInfo.InitCheck();
67fc11b80cSAxel Dörfler	if (ret == B_OK)
6844f919daSRyan Leavengood		_InitProfiles();
6944f919daSRyan Leavengood}
7044f919daSRyan Leavengood
7144f919daSRyan Leavengood
7244f919daSRyan LeavengoodPackageView::~PackageView()
7344f919daSRyan Leavengood{
7444f919daSRyan Leavengood	delete fOpenPanel;
7544f919daSRyan Leavengood}
7644f919daSRyan Leavengood
7744f919daSRyan Leavengood
7844f919daSRyan Leavengoodvoid
7944f919daSRyan LeavengoodPackageView::AttachedToWindow()
8044f919daSRyan Leavengood{
81b97c244eSJérôme Duval	status_t ret = fInfo.InitCheck();
82b97c244eSJérôme Duval	if (ret != B_OK && ret != B_NO_INIT) {
83735727daSStephan Aßmus		BAlert* warning = new BAlert("parsing_failed",
84eef95624SMatt Madia				B_TRANSLATE("The package file is not readable.\nOne of the "
85eef95624SMatt Madia				"possible reasons for this might be that the requested file "
86eef95624SMatt Madia				"is not a valid BeOS .pkg package."), B_TRANSLATE("OK"),
87eef95624SMatt Madia				NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
88aed35104SHumdinger		warning->SetFlags(warning->Flags() | B_CLOSE_ON_ESCAPE);
89b97c244eSJérôme Duval		warning->Go();
90b97c244eSJérôme Duval
91b97c244eSJérôme Duval		Window()->PostMessage(B_QUIT_REQUESTED);
92b97c244eSJérôme Duval		return;
93b97c244eSJérôme Duval	}
94b97c244eSJérôme Duval
9544f919daSRyan Leavengood	// Set the window title
96735727daSStephan Aßmus	BWindow* parent = Window();
9744f919daSRyan Leavengood	BString title;
9844f919daSRyan Leavengood	BString name = fInfo.GetName();
9944f919daSRyan Leavengood	if (name.CountChars() == 0) {
100eef95624SMatt Madia		title = B_TRANSLATE("Package installer");
101735727daSStephan Aßmus	} else {
102236dd276SStephan Aßmus		title = B_TRANSLATE("Install %name%");
103236dd276SStephan Aßmus		title.ReplaceAll("%name%", name);
10444f919daSRyan Leavengood	}
10544f919daSRyan Leavengood	parent->SetTitle(title.String());
106e75f469dSStephan Aßmus	fBeginButton->SetTarget(this);
10744f919daSRyan Leavengood
10844f919daSRyan Leavengood	fOpenPanel->SetTarget(BMessenger(this));
10944f919daSRyan Leavengood	fInstallTypes->SetTargetForItems(this);
11044f919daSRyan Leavengood
111193a4de1SStephan Aßmus	if (ret != B_OK)
112193a4de1SStephan Aßmus		return;
113fc11b80cSAxel Dörfler
114193a4de1SStephan Aßmus	// If the package is valid, we can set up the default group and all
115193a4de1SStephan Aßmus	// other things. If not, then the application will close just after
116193a4de1SStephan Aßmus	// attaching the view to the window
117735727daSStephan Aßmus	_InstallTypeChanged(0);
118193a4de1SStephan Aßmus
119193a4de1SStephan Aßmus	fStatusWindow = new PackageStatus(B_TRANSLATE("Installation progress"),
120193a4de1SStephan Aßmus		NULL, NULL, this);
121193a4de1SStephan Aßmus
122193a4de1SStephan Aßmus	// Show the splash screen, if present
123193a4de1SStephan Aßmus	BMallocIO* image = fInfo.GetSplashScreen();
124193a4de1SStephan Aßmus	if (image != NULL) {
125193a4de1SStephan Aßmus		PackageImageViewer* imageViewer = new PackageImageViewer(image);
126193a4de1SStephan Aßmus		imageViewer->Go();
127193a4de1SStephan Aßmus	}
128193a4de1SStephan Aßmus
129193a4de1SStephan Aßmus	// Show the disclaimer/info text popup, if present
130193a4de1SStephan Aßmus	BString disclaimer = fInfo.GetDisclaimer();
131193a4de1SStephan Aßmus	if (disclaimer.Length() != 0) {
132193a4de1SStephan Aßmus		PackageTextViewer* text = new PackageTextViewer(
133193a4de1SStephan Aßmus			disclaimer.String());
134193a4de1SStephan Aßmus		int32 selection = text->Go();
135193a4de1SStephan Aßmus		// The user didn't accept our disclaimer, this means we cannot
136193a4de1SStephan Aßmus		// continue.
137193a4de1SStephan Aßmus		if (selection == 0)
138193a4de1SStephan Aßmus			parent->Quit();
139bf86f099SJérôme Duval	}
14044f919daSRyan Leavengood}
14144f919daSRyan Leavengood
14244f919daSRyan Leavengood
14344f919daSRyan Leavengoodvoid
144193a4de1SStephan AßmusPackageView::MessageReceived(BMessage* message)
14544f919daSRyan Leavengood{
146193a4de1SStephan Aßmus	switch (message->what) {
14744f919daSRyan Leavengood		case P_MSG_INSTALL:
14844f919daSRyan Leavengood		{
149e75f469dSStephan Aßmus			fBeginButton->SetEnabled(false);
1509ff2343bSJérôme Duval			fInstallTypes->SetEnabled(false);
1519ff2343bSJérôme Duval			fDestination->SetEnabled(false);
15244f919daSRyan Leavengood			fStatusWindow->Show();
153fc11b80cSAxel Dörfler
1549ff2343bSJérôme Duval			fInstallProcess.Start();
15544f919daSRyan Leavengood			break;
15644f919daSRyan Leavengood		}
1571d5c1fc3SJohn Scipione
15844f919daSRyan Leavengood		case P_MSG_PATH_CHANGED:
15944f919daSRyan Leavengood		{
16044f919daSRyan Leavengood			BString path;
161735727daSStephan Aßmus			if (message->FindString("path", &path) == B_OK)
16244f919daSRyan Leavengood				fCurrentPath.SetTo(path.String());
16344f919daSRyan Leavengood			break;
16444f919daSRyan Leavengood		}
1651d5c1fc3SJohn Scipione
16644f919daSRyan Leavengood		case P_MSG_OPEN_PANEL:
167792a46dbSStephan Aßmus			fExpectingOpenPanelResult = true;
16844f919daSRyan Leavengood			fOpenPanel->Show();
16944f919daSRyan Leavengood			break;
1701d5c1fc3SJohn Scipione
171735727daSStephan Aßmus		case P_MSG_INSTALL_TYPE_CHANGED:
17244f919daSRyan Leavengood		{
17344f919daSRyan Leavengood			int32 index;
174735727daSStephan Aßmus			if (message->FindInt32("index", &index) == B_OK)
175735727daSStephan Aßmus				_InstallTypeChanged(index);
17644f919daSRyan Leavengood			break;
17744f919daSRyan Leavengood		}
1781d5c1fc3SJohn Scipione
1799ff2343bSJérôme Duval		case P_MSG_I_FINISHED:
1809ff2343bSJérôme Duval		{
181735727daSStephan Aßmus			BAlert* notify = new BAlert("installation_success",
182eef95624SMatt Madia				B_TRANSLATE("The package you requested has been successfully "
183eef95624SMatt Madia					"installed on your system."),
184eef95624SMatt Madia				B_TRANSLATE("OK"));
185aed35104SHumdinger			notify->SetFlags(notify->Flags() | B_CLOSE_ON_ESCAPE);
1869ff2343bSJérôme Duval
1879ff2343bSJérôme Duval			notify->Go();
1889ff2343bSJérôme Duval			fStatusWindow->Hide();
189e75f469dSStephan Aßmus			fBeginButton->SetEnabled(true);
1909ff2343bSJérôme Duval			fInstallTypes->SetEnabled(true);
1919ff2343bSJérôme Duval			fDestination->SetEnabled(true);
1929ff2343bSJérôme Duval			fInstallProcess.Stop();
1939ff2343bSJérôme Duval
1949ff2343bSJérôme Duval			BWindow *parent = Window();
1959ff2343bSJérôme Duval			if (parent && parent->Lock())
1969ff2343bSJérôme Duval				parent->Quit();
1979ff2343bSJérôme Duval			break;
1989ff2343bSJérôme Duval		}
1991d5c1fc3SJohn Scipione
2009ff2343bSJérôme Duval		case P_MSG_I_ABORT:
2019ff2343bSJérôme Duval		{
202735727daSStephan Aßmus			BAlert* notify = new BAlert("installation_aborted",
203eef95624SMatt Madia				B_TRANSLATE(
204eef95624SMatt Madia					"The installation of the package has been aborted."),
205eef95624SMatt Madia				B_TRANSLATE("OK"));
206aed35104SHumdinger			notify->SetFlags(notify->Flags() | B_CLOSE_ON_ESCAPE);
2079ff2343bSJérôme Duval			notify->Go();
2089ff2343bSJérôme Duval			fStatusWindow->Hide();
209e75f469dSStephan Aßmus			fBeginButton->SetEnabled(true);
2109ff2343bSJérôme Duval			fInstallTypes->SetEnabled(true);
2119ff2343bSJérôme Duval			fDestination->SetEnabled(true);
2129ff2343bSJérôme Duval			fInstallProcess.Stop();
2139ff2343bSJérôme Duval			break;
2149ff2343bSJérôme Duval		}
2151d5c1fc3SJohn Scipione
2169ff2343bSJérôme Duval		case P_MSG_I_ERROR:
2179ff2343bSJérôme Duval		{
218091440e0SStephan Aßmus			// TODO: Review this
219735727daSStephan Aßmus			BAlert* notify = new BAlert("installation_failed",
220eef95624SMatt Madia				B_TRANSLATE("The requested package failed to install on your "
221eef95624SMatt Madia					"system. This might be a problem with the target package "
222eef95624SMatt Madia					"file. Please consult this issue with the package "
223eef95624SMatt Madia					"distributor."),
224eef95624SMatt Madia				B_TRANSLATE("OK"),
225eef95624SMatt Madia				NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
226eef95624SMatt Madia			fprintf(stderr,
227eef95624SMatt Madia				B_TRANSLATE("Error while installing the package\n"));
228aed35104SHumdinger			notify->SetFlags(notify->Flags() | B_CLOSE_ON_ESCAPE);
2299ff2343bSJérôme Duval			notify->Go();
2309ff2343bSJérôme Duval			fStatusWindow->Hide();
231e75f469dSStephan Aßmus			fBeginButton->SetEnabled(true);
2329ff2343bSJérôme Duval			fInstallTypes->SetEnabled(true);
2339ff2343bSJérôme Duval			fDestination->SetEnabled(true);
2349ff2343bSJérôme Duval			fInstallProcess.Stop();
2359ff2343bSJérôme Duval			break;
2369ff2343bSJérôme Duval		}
2371d5c1fc3SJohn Scipione
2389ff2343bSJérôme Duval		case P_MSG_STOP:
2399ff2343bSJérôme Duval		{
2409ff2343bSJérôme Duval			// This message is sent to us by the PackageStatus window, informing
2419ff2343bSJérôme Duval			// user interruptions.
2429ff2343bSJérôme Duval			// We actually use this message only when a post installation script
2439ff2343bSJérôme Duval			// is running and we want to kill it while it's still running
2449ff2343bSJérôme Duval			fStatusWindow->Hide();
245e75f469dSStephan Aßmus			fBeginButton->SetEnabled(true);
2469ff2343bSJérôme Duval			fInstallTypes->SetEnabled(true);
2479ff2343bSJérôme Duval			fDestination->SetEnabled(true);
2489ff2343bSJérôme Duval			fInstallProcess.Stop();
2499ff2343bSJérôme Duval			break;
2509ff2343bSJérôme Duval		}
2511d5c1fc3SJohn Scipione
25244f919daSRyan Leavengood		case B_REFS_RECEIVED:
25344f919daSRyan Leavengood		{
254792a46dbSStephan Aßmus			if (!_ValidateFilePanelMessage(message))
255792a46dbSStephan Aßmus				break;
256792a46dbSStephan Aßmus
25744f919daSRyan Leavengood			entry_ref ref;
258193a4de1SStephan Aßmus			if (message->FindRef("refs", &ref) == B_OK) {
25944f919daSRyan Leavengood				BPath path(&ref);
260735727daSStephan Aßmus				if (path.InitCheck() != B_OK)
261735727daSStephan Aßmus					break;
26244f919daSRyan Leavengood
26344f919daSRyan Leavengood				dev_t device = dev_for_path(path.Path());
26444f919daSRyan Leavengood				BVolume volume(device);
26544f919daSRyan Leavengood				if (volume.InitCheck() != B_OK)
26644f919daSRyan Leavengood					break;
26744f919daSRyan Leavengood
268735727daSStephan Aßmus				BMenuItem* item = fDestField->MenuItem();
26944f919daSRyan Leavengood
270735727daSStephan Aßmus				BString name = _NamePlusSizeString(path.Path(),
271735727daSStephan Aßmus					volume.FreeBytes(), B_TRANSLATE("%name% (%size% free)"));
27244f919daSRyan Leavengood
27344f919daSRyan Leavengood				item->SetLabel(name.String());
27444f919daSRyan Leavengood				fCurrentPath.SetTo(path.Path());
27544f919daSRyan Leavengood			}
27644f919daSRyan Leavengood			break;
27744f919daSRyan Leavengood		}
2781d5c1fc3SJohn Scipione
2791e35b8fcSStephan Aßmus		case B_CANCEL:
2801e35b8fcSStephan Aßmus		{
281792a46dbSStephan Aßmus			if (!_ValidateFilePanelMessage(message))
282792a46dbSStephan Aßmus				break;
283792a46dbSStephan Aßmus
2841d5c1fc3SJohn Scipione			// file panel aborted, select first suitable item
28551f34888SStephan Aßmus			for (int32 i = 0; i < fDestination->CountItems(); i++) {
28651f34888SStephan Aßmus				BMenuItem* item = fDestination->ItemAt(i);
28751f34888SStephan Aßmus				BMessage* message = item->Message();
28851f34888SStephan Aßmus				if (message == NULL)
28951f34888SStephan Aßmus					continue;
29051f34888SStephan Aßmus				BString path;
29151f34888SStephan Aßmus				if (message->FindString("path", &path) == B_OK) {
29251f34888SStephan Aßmus					fCurrentPath.SetTo(path.String());
29351f34888SStephan Aßmus					item->SetMarked(true);
29451f34888SStephan Aßmus					break;
29551f34888SStephan Aßmus				}
2961e35b8fcSStephan Aßmus			}
2971e35b8fcSStephan Aßmus			break;
2981e35b8fcSStephan Aßmus		}
2991d5c1fc3SJohn Scipione
30044f919daSRyan Leavengood		case B_SIMPLE_DATA:
301193a4de1SStephan Aßmus			if (message->WasDropped()) {
30244f919daSRyan Leavengood				uint32 type;
30344f919daSRyan Leavengood				int32 count;
304193a4de1SStephan Aßmus				status_t ret = message->GetInfo("refs", &type, &count);
3051d5c1fc3SJohn Scipione				// check whether the message means someone dropped a file
30644f919daSRyan Leavengood				// to our view
30744f919daSRyan Leavengood				if (ret == B_OK && type == B_REF_TYPE) {
3081d5c1fc3SJohn Scipione					// if it is, send it along with the refs to the application
309193a4de1SStephan Aßmus					message->what = B_REFS_RECEIVED;
310193a4de1SStephan Aßmus					be_app->PostMessage(message);
31144f919daSRyan Leavengood				}
31244f919daSRyan Leavengood			}
3131d5c1fc3SJohn Scipione			// fall-through
31444f919daSRyan Leavengood		default:
315193a4de1SStephan Aßmus			BView::MessageReceived(message);
31644f919daSRyan Leavengood			break;
31744f919daSRyan Leavengood	}
31844f919daSRyan Leavengood}
31944f919daSRyan Leavengood
32044f919daSRyan Leavengood
3219ff2343bSJérôme Duvalint32
322193a4de1SStephan AßmusPackageView::ItemExists(PackageItem& item, BPath& path, int32& policy)
32344f919daSRyan Leavengood{
3249ff2343bSJérôme Duval	int32 choice = P_EXISTS_NONE;
32544f919daSRyan Leavengood
3269ff2343bSJérôme Duval	switch (policy) {
3279ff2343bSJérôme Duval		case P_EXISTS_OVERWRITE:
3289ff2343bSJérôme Duval			choice = P_EXISTS_OVERWRITE;
3299ff2343bSJérôme Duval			break;
33044f919daSRyan Leavengood
3319ff2343bSJérôme Duval		case P_EXISTS_SKIP:
3329ff2343bSJérôme Duval			choice = P_EXISTS_SKIP;
3339ff2343bSJérôme Duval			break;
334fc11b80cSAxel Dörfler
3359ff2343bSJérôme Duval		case P_EXISTS_ASK:
3369ff2343bSJérôme Duval		case P_EXISTS_NONE:
3379ff2343bSJérôme Duval		{
338091440e0SStephan Aßmus			const char* formatString;
3392824c5d3SAdrien Destugues			switch (item.ItemKind()) {
340091440e0SStephan Aßmus				case P_KIND_SCRIPT:
341eef95624SMatt Madia					formatString = B_TRANSLATE("The script named \'%s\' "
342f98e331cSNiels Sascha Reedijk						"already exists in the given path.\nReplace the script "
343eef95624SMatt Madia						"with the one from this package or skip it?");
344091440e0SStephan Aßmus					break;
345091440e0SStephan Aßmus				case P_KIND_FILE:
346eef95624SMatt Madia					formatString = B_TRANSLATE("The file named \'%s\' already "
347f98e331cSNiels Sascha Reedijk						"exists in the given path.\nReplace the file with the "
348eef95624SMatt Madia						"one from this package or skip it?");
349091440e0SStephan Aßmus					break;
350091440e0SStephan Aßmus				case P_KIND_DIRECTORY:
351eef95624SMatt Madia					formatString = B_TRANSLATE("The directory named \'%s\' "
352f98e331cSNiels Sascha Reedijk						"already exists in the given path.\nReplace the "
353eef95624SMatt Madia						"directory with one from this package or skip it?");
3542824c5d3SAdrien Destugues					break;
355091440e0SStephan Aßmus				case P_KIND_SYM_LINK:
356eef95624SMatt Madia					formatString = B_TRANSLATE("The symbolic link named \'%s\' "
3572824c5d3SAdrien Destugues						"already exists in the given path.\nReplace the link "
358eef95624SMatt Madia						"with the one from this package or skip it?");
359091440e0SStephan Aßmus					break;
360091440e0SStephan Aßmus				default:
361eef95624SMatt Madia					formatString = B_TRANSLATE("The item named \'%s\' already "
362f98e331cSNiels Sascha Reedijk						"exists in the given path.\nReplace the item with the "
363eef95624SMatt Madia						"one from this package or skip it?");
364091440e0SStephan Aßmus					break;
365091440e0SStephan Aßmus			}
366091440e0SStephan Aßmus			char buffer[512];
367091440e0SStephan Aßmus			snprintf(buffer, sizeof(buffer), formatString, path.Leaf());
368eef95624SMatt Madia
369091440e0SStephan Aßmus			BString alertString = buffer;
370eef95624SMatt Madia
371735727daSStephan Aßmus			BAlert* alert = new BAlert("file_exists", alertString.String(),
372eef95624SMatt Madia				B_TRANSLATE("Replace"),
373eef95624SMatt Madia				B_TRANSLATE("Skip"),
374eef95624SMatt Madia				B_TRANSLATE("Abort"));
375aed35104SHumdinger			alert->SetShortcut(2, B_ESCAPE);
3762824c5d3SAdrien Destugues
3779ff2343bSJérôme Duval			choice = alert->Go();
3789ff2343bSJérôme Duval			switch (choice) {
3799ff2343bSJérôme Duval				case 0:
3809ff2343bSJérôme Duval					choice = P_EXISTS_OVERWRITE;
3819ff2343bSJérôme Duval					break;
3829ff2343bSJérôme Duval				case 1:
3839ff2343bSJérôme Duval					choice = P_EXISTS_SKIP;
3849ff2343bSJérôme Duval					break;
3859ff2343bSJérôme Duval				default:
3869ff2343bSJérôme Duval					return P_EXISTS_ABORT;
3879ff2343bSJérôme Duval			}
38844f919daSRyan Leavengood
3899ff2343bSJérôme Duval			if (policy == P_EXISTS_NONE) {
3909ff2343bSJérôme Duval				// TODO: Maybe add 'No, but ask again' type of choice as well?
391eef95624SMatt Madia				alertString = B_TRANSLATE("Do you want to remember this "
392eef95624SMatt Madia					"decision for the rest of this installation?\n");
3934a31ed96SDarkWyrm
3944a31ed96SDarkWyrm				BString actionString;
3954a31ed96SDarkWyrm				if (choice == P_EXISTS_OVERWRITE) {
396193a4de1SStephan Aßmus					alertString << B_TRANSLATE(
397193a4de1SStephan Aßmus						"All existing files will be replaced?");
3983c018b5fSJoachim Seemer					actionString = B_TRANSLATE("Replace all");
3994a31ed96SDarkWyrm				} else {
400193a4de1SStephan Aßmus					alertString << B_TRANSLATE(
401193a4de1SStephan Aßmus						"All existing files will be skipped?");
4023c018b5fSJoachim Seemer					actionString = B_TRANSLATE("Skip all");
4034a31ed96SDarkWyrm				}
404091440e0SStephan Aßmus				alert = new BAlert("policy_decision", alertString.String(),
4054a31ed96SDarkWyrm					actionString.String(), B_TRANSLATE("Ask again"));
40644f919daSRyan Leavengood
4079ff2343bSJérôme Duval				int32 decision = alert->Go();
4089ff2343bSJérôme Duval				if (decision == 0)
4099ff2343bSJérôme Duval					policy = choice;
4109ff2343bSJérôme Duval				else
4119ff2343bSJérôme Duval					policy = P_EXISTS_ASK;
4129ff2343bSJérôme Duval			}
4139ff2343bSJérôme Duval			break;
4149ff2343bSJérôme Duval		}
4159ff2343bSJérôme Duval	}
41644f919daSRyan Leavengood
4179ff2343bSJérôme Duval	return choice;
41844f919daSRyan Leavengood}
41944f919daSRyan Leavengood
42044f919daSRyan Leavengood
421735727daSStephan Aßmus// #pragma mark -
422fc11b80cSAxel Dörfler
42344f919daSRyan Leavengood
424735727daSStephan Aßmusclass DescriptionTextView : public BTextView {
425735727daSStephan Aßmuspublic:
426735727daSStephan Aßmus	DescriptionTextView(const char* name, float minHeight)
427735727daSStephan Aßmus		:
428735727daSStephan Aßmus		BTextView(name)
429735727daSStephan Aßmus	{
430735727daSStephan Aßmus		SetExplicitMinSize(BSize(B_SIZE_UNSET, minHeight));
431735727daSStephan Aßmus	}
43244f919daSRyan Leavengood
433735727daSStephan Aßmus	virtual void AttachedToWindow()
434735727daSStephan Aßmus	{
435735727daSStephan Aßmus		BTextView::AttachedToWindow();
436735727daSStephan Aßmus		_UpdateScrollBarVisibility();
437735727daSStephan Aßmus	}
43844f919daSRyan Leavengood
439735727daSStephan Aßmus	virtual void FrameResized(float width, float height)
440735727daSStephan Aßmus	{
441735727daSStephan Aßmus		BTextView::FrameResized(width, height);
442735727daSStephan Aßmus		_UpdateScrollBarVisibility();
443735727daSStephan Aßmus	}
44444f919daSRyan Leavengood
445735727daSStephan Aßmus	virtual void Draw(BRect updateRect)
446735727daSStephan Aßmus	{
447735727daSStephan Aßmus		BTextView::Draw(updateRect);
448735727daSStephan Aßmus		_UpdateScrollBarVisibility();
449735727daSStephan Aßmus	}
450fc11b80cSAxel Dörfler
451735727daSStephan Aßmusprivate:
452735727daSStephan Aßmus	void _UpdateScrollBarVisibility()
453735727daSStephan Aßmus	{
454735727daSStephan Aßmus		BScrollBar* verticalBar = ScrollBar(B_VERTICAL);
455735727daSStephan Aßmus		if (verticalBar != NULL) {
456735727daSStephan Aßmus			float min;
457735727daSStephan Aßmus			float max;
458735727daSStephan Aßmus			verticalBar->GetRange(&min, &max);
459735727daSStephan Aßmus			if (min == max) {
460735727daSStephan Aßmus				if (!verticalBar->IsHidden(verticalBar))
461735727daSStephan Aßmus					verticalBar->Hide();
462735727daSStephan Aßmus			} else {
463735727daSStephan Aßmus				if (verticalBar->IsHidden(verticalBar))
464735727daSStephan Aßmus					verticalBar->Show();
465735727daSStephan Aßmus			}
466735727daSStephan Aßmus		}
467735727daSStephan Aßmus	}
468735727daSStephan Aßmus};
46944f919daSRyan Leavengood
47044f919daSRyan Leavengood
47144f919daSRyan Leavengoodvoid
47244f919daSRyan LeavengoodPackageView::_InitView()
47344f919daSRyan Leavengood{
474fa19dd44Slooncraz	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
475fc11b80cSAxel Dörfler
476735727daSStephan Aßmus	float fontHeight = be_plain_font->Size();
477fa19dd44Slooncraz	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
478fc11b80cSAxel Dörfler
479735727daSStephan Aßmus	BTextView* packageDescriptionView = new DescriptionTextView(
480735727daSStephan Aßmus		"package description", fontHeight * 13);
481fa19dd44Slooncraz	packageDescriptionView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
482735727daSStephan Aßmus	packageDescriptionView->SetText(fInfo.GetDescription());
483735727daSStephan Aßmus	packageDescriptionView->MakeEditable(false);
484735727daSStephan Aßmus	packageDescriptionView->MakeSelectable(false);
485fa19dd44Slooncraz	packageDescriptionView->SetFontAndColor(be_plain_font, B_FONT_ALL,
486fa19dd44Slooncraz		&textColor);
48744f919daSRyan Leavengood
488735727daSStephan Aßmus	BScrollView* descriptionScrollView = new BScrollView(
489735727daSStephan Aßmus		"package description scroll view", packageDescriptionView,
490735727daSStephan Aßmus		0, false, true, B_NO_BORDER);
491fc11b80cSAxel Dörfler
492735727daSStephan Aßmus	// Install type menu field
493735727daSStephan Aßmus	fInstallTypes = new BPopUpMenu(B_TRANSLATE("none"));
494735727daSStephan Aßmus	BMenuField* installType = new BMenuField("install_type",
495735727daSStephan Aßmus		B_TRANSLATE("Installation type:"), fInstallTypes);
496735727daSStephan Aßmus
497735727daSStephan Aßmus	// Install type description text view
498735727daSStephan Aßmus	fInstallTypeDescriptionView = new DescriptionTextView(
499ab29480fSStephan Aßmus		"install type description", fontHeight * 4);
500735727daSStephan Aßmus	fInstallTypeDescriptionView->MakeEditable(false);
501735727daSStephan Aßmus	fInstallTypeDescriptionView->MakeSelectable(false);
5025da00053SStephan Aßmus	fInstallTypeDescriptionView->SetInsets(8, 0, 0, 0);
5035da00053SStephan Aßmus		// Left inset needs to match BMenuField text offset
504735727daSStephan Aßmus	fInstallTypeDescriptionView->SetText(
505735727daSStephan Aßmus		B_TRANSLATE("No installation type selected"));
506fa19dd44Slooncraz	fInstallTypeDescriptionView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
5075da00053SStephan Aßmus	BFont font(be_plain_font);
5085da00053SStephan Aßmus	font.SetSize(ceilf(font.Size() * 0.85));
509fa19dd44Slooncraz	fInstallTypeDescriptionView->SetFontAndColor(&font, B_FONT_ALL,
510fa19dd44Slooncraz		&textColor);
511735727daSStephan Aßmus
512735727daSStephan Aßmus	BScrollView* installTypeScrollView = new BScrollView(
513735727daSStephan Aßmus		"install type description scroll view", fInstallTypeDescriptionView,
514735727daSStephan Aßmus		 0, false, true, B_NO_BORDER);
515735727daSStephan Aßmus
516735727daSStephan Aßmus	// Destination menu field
5173c018b5fSJoachim Seemer	fDestination = new BPopUpMenu(B_TRANSLATE("none"));
518735727daSStephan Aßmus	fDestField = new BMenuField("install_to", B_TRANSLATE("Install to:"),
519735727daSStephan Aßmus		fDestination);
520735727daSStephan Aßmus
521e75f469dSStephan Aßmus	fBeginButton = new BButton("begin_button", B_TRANSLATE("Begin"),
522735727daSStephan Aßmus		new BMessage(P_MSG_INSTALL));
523735727daSStephan Aßmus
5245da00053SStephan Aßmus	BLayoutItem* typeLabelItem = installType->CreateLabelLayoutItem();
5255da00053SStephan Aßmus	BLayoutItem* typeMenuItem = installType->CreateMenuBarLayoutItem();
5265da00053SStephan Aßmus
527e75f469dSStephan Aßmus	BLayoutItem* destFieldLabelItem = fDestField->CreateLabelLayoutItem();
528e75f469dSStephan Aßmus	BLayoutItem* destFieldMenuItem = fDestField->CreateMenuBarLayoutItem();
529e75f469dSStephan Aßmus
5305da00053SStephan Aßmus	float forcedMinWidth = be_plain_font->StringWidth("XXX") * 5;
5315da00053SStephan Aßmus	destFieldMenuItem->SetExplicitMinSize(BSize(forcedMinWidth, B_SIZE_UNSET));
5325da00053SStephan Aßmus	typeMenuItem->SetExplicitMinSize(BSize(forcedMinWidth, B_SIZE_UNSET));
5335da00053SStephan Aßmus
534e75f469dSStephan Aßmus	BAlignment labelAlignment(B_ALIGN_RIGHT, B_ALIGN_VERTICAL_UNSET);
535e75f469dSStephan Aßmus	typeLabelItem->SetExplicitAlignment(labelAlignment);
536e75f469dSStephan Aßmus	destFieldLabelItem->SetExplicitAlignment(labelAlignment);
537e75f469dSStephan Aßmus
538735727daSStephan Aßmus	// Build the layout
539735727daSStephan Aßmus	BLayoutBuilder::Group<>(this, B_VERTICAL)
540735727daSStephan Aßmus		.Add(descriptionScrollView)
541e75f469dSStephan Aßmus		.AddGrid(B_USE_SMALL_SPACING, B_USE_DEFAULT_SPACING)
5425da00053SStephan Aßmus			.Add(typeLabelItem, 0, 0)
5435da00053SStephan Aßmus			.Add(typeMenuItem, 1, 0)
544e75f469dSStephan Aßmus			.Add(installTypeScrollView, 1, 1)
5455da00053SStephan Aßmus			.Add(destFieldLabelItem, 0, 2)
5465da00053SStephan Aßmus			.Add(destFieldMenuItem, 1, 2)
547e75f469dSStephan Aßmus		.End()
548e75f469dSStephan Aßmus		.AddGroup(B_HORIZONTAL)
549e75f469dSStephan Aßmus			.AddGlue()
550e75f469dSStephan Aßmus			.Add(fBeginButton)
551735727daSStephan Aßmus		.End()
552735727daSStephan Aßmus		.SetInsets(B_USE_DEFAULT_SPACING)
553735727daSStephan Aßmus	;
554fc11b80cSAxel Dörfler
555e75f469dSStephan Aßmus	fBeginButton->MakeDefault(true);
55644f919daSRyan Leavengood}
55744f919daSRyan Leavengood
55844f919daSRyan Leavengood
55944f919daSRyan Leavengoodvoid
56044f919daSRyan LeavengoodPackageView::_InitProfiles()
56144f919daSRyan Leavengood{
562193a4de1SStephan Aßmus	int count = fInfo.GetProfileCount();
563193a4de1SStephan Aßmus
564193a4de1SStephan Aßmus	if (count > 0) {
565193a4de1SStephan Aßmus		// Add the default item
566193a4de1SStephan Aßmus		pkg_profile* profile = fInfo.GetProfile(0);
567193a4de1SStephan Aßmus		BMenuItem* item = _AddInstallTypeMenuItem(profile->name,
568193a4de1SStephan Aßmus			profile->space_needed, 0);
56944f919daSRyan Leavengood		item->SetMarked(true);
57044f919daSRyan Leavengood		fCurrentType = 0;
57144f919daSRyan Leavengood	}
57244f919daSRyan Leavengood
573193a4de1SStephan Aßmus	for (int i = 1; i < count; i++) {
574193a4de1SStephan Aßmus		pkg_profile* profile = fInfo.GetProfile(i);
575fc11b80cSAxel Dörfler
576a16a1437SStephan Aßmus		if (profile != NULL)
577193a4de1SStephan Aßmus			_AddInstallTypeMenuItem(profile->name, profile->space_needed, i);
578a16a1437SStephan Aßmus		else
57944f919daSRyan Leavengood			fInstallTypes->AddSeparatorItem();
58044f919daSRyan Leavengood	}
58144f919daSRyan Leavengood}
58244f919daSRyan Leavengood
58344f919daSRyan Leavengood
58444f919daSRyan Leavengoodstatus_t
585735727daSStephan AßmusPackageView::_InstallTypeChanged(int32 index)
58644f919daSRyan Leavengood{
58744f919daSRyan Leavengood	if (index < 0)
58844f919daSRyan Leavengood		return B_ERROR;
58944f919daSRyan Leavengood
59044f919daSRyan Leavengood	// Clear the choice list
591193a4de1SStephan Aßmus	for (int32 i = fDestination->CountItems() - 1; i >= 0; i--) {
592193a4de1SStephan Aßmus		BMenuItem* item = fDestination->RemoveItem(i);
593193a4de1SStephan Aßmus		delete item;
59444f919daSRyan Leavengood	}
59544f919daSRyan Leavengood
59644f919daSRyan Leavengood	fCurrentType = index;
597193a4de1SStephan Aßmus	pkg_profile* profile = fInfo.GetProfile(index);
5981d5c1fc3SJohn Scipione
599193a4de1SStephan Aßmus	if (profile == NULL)
600193a4de1SStephan Aßmus		return B_ERROR;
601193a4de1SStephan Aßmus
6025da00053SStephan Aßmus	BString typeDescription = profile->description;
6035da00053SStephan Aßmus	if (typeDescription.IsEmpty())
6045da00053SStephan Aßmus		typeDescription = profile->name;
6051d5c1fc3SJohn Scipione
6065da00053SStephan Aßmus	fInstallTypeDescriptionView->SetText(typeDescription.String());
6071d5c1fc3SJohn Scipione
608193a4de1SStephan Aßmus	BPath path;
609193a4de1SStephan Aßmus	BVolume volume;
610193a4de1SStephan Aßmus
611193a4de1SStephan Aßmus	if (profile->path_type == P_INSTALL_PATH) {
612193a4de1SStephan Aßmus		BMenuItem* item = NULL;
6134407020bSStephan Aßmus		if (find_directory(B_SYSTEM_NONPACKAGED_DIRECTORY, &path) == B_OK) {
614193a4de1SStephan Aßmus			dev_t device = dev_for_path(path.Path());
6154407020bSStephan Aßmus			if (volume.SetTo(device) == B_OK && !volume.IsReadOnly()
6164407020bSStephan Aßmus				&& path.Append("apps") == B_OK) {
617193a4de1SStephan Aßmus				item = _AddDestinationMenuItem(path.Path(), volume.FreeBytes(),
618193a4de1SStephan Aßmus					path.Path());
61944f919daSRyan Leavengood			}
620193a4de1SStephan Aßmus		}
621193a4de1SStephan Aßmus
622193a4de1SStephan Aßmus		if (item != NULL) {
623193a4de1SStephan Aßmus			item->SetMarked(true);
624193a4de1SStephan Aßmus			fCurrentPath.SetTo(path.Path());
6254407020bSStephan Aßmus			fDestination->AddSeparatorItem();
626193a4de1SStephan Aßmus		}
627193a4de1SStephan Aßmus
628193a4de1SStephan Aßmus		_AddMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS),
629193a4de1SStephan Aßmus			new BMessage(P_MSG_OPEN_PANEL), fDestination);
630193a4de1SStephan Aßmus
631193a4de1SStephan Aßmus		fDestField->SetEnabled(true);
632193a4de1SStephan Aßmus	} else if (profile->path_type == P_USER_PATH) {
633193a4de1SStephan Aßmus		bool defaultPathSet = false;
634193a4de1SStephan Aßmus		BVolumeRoster roster;
635193a4de1SStephan Aßmus
636193a4de1SStephan Aßmus		while (roster.GetNextVolume(&volume) != B_BAD_VALUE) {
637193a4de1SStephan Aßmus			BDirectory mountPoint;
638193a4de1SStephan Aßmus			if (volume.IsReadOnly() || !volume.IsPersistent()
639193a4de1SStephan Aßmus				|| volume.GetRootDirectory(&mountPoint) != B_OK) {
640193a4de1SStephan Aßmus				continue;
641193a4de1SStephan Aßmus			}
642193a4de1SStephan Aßmus
643193a4de1SStephan Aßmus			if (path.SetTo(&mountPoint, NULL) != B_OK)
644193a4de1SStephan Aßmus				continue;
645193a4de1SStephan Aßmus
646193a4de1SStephan Aßmus			char volumeName[B_FILE_NAME_LENGTH];
647193a4de1SStephan Aßmus			volume.GetName(volumeName);
648193a4de1SStephan Aßmus
649193a4de1SStephan Aßmus			BMenuItem* item = _AddDestinationMenuItem(volumeName,
650193a4de1SStephan Aßmus				volume.FreeBytes(), path.Path());
65144f919daSRyan Leavengood
652193a4de1SStephan Aßmus			// The first volume becomes the default element
653193a4de1SStephan Aßmus			if (!defaultPathSet) {
65444f919daSRyan Leavengood				item->SetMarked(true);
65544f919daSRyan Leavengood				fCurrentPath.SetTo(path.Path());
656193a4de1SStephan Aßmus				defaultPathSet = true;
65744f919daSRyan Leavengood			}
658193a4de1SStephan Aßmus		}
65944f919daSRyan Leavengood
660193a4de1SStephan Aßmus		fDestField->SetEnabled(true);
661193a4de1SStephan Aßmus	} else
662193a4de1SStephan Aßmus		fDestField->SetEnabled(false);
66344f919daSRyan Leavengood
664193a4de1SStephan Aßmus	return B_OK;
665193a4de1SStephan Aßmus}
66644f919daSRyan Leavengood
667