In the spirit of giving exposure to as many Haiku features as possible,

integrate the Boot Manager into Installer. There was a patch for this in ticket
#4425, but I have implemented this myself, since the patch didn't implement
the interaction with running and quitting DriveSetup and Bootman correctly.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36482 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2010-04-26 10:09:14 +00:00
parent 21629aa53d
commit 2061b030b8
2 changed files with 123 additions and 32 deletions
+118 -30
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2009, Stephan Aßmus <[email protected]> * Copyright 2009-2010, Stephan Aßmus <[email protected]>
* Copyright 2005-2008, Jérôme DUVAL * Copyright 2005-2008, Jérôme DUVAL
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@@ -48,10 +48,12 @@
#define TR_CONTEXT "InstallerWindow" #define TR_CONTEXT "InstallerWindow"
#define DRIVESETUP_SIG "application/x-vnd.Haiku-DriveSetup" #define DRIVESETUP_SIG "application/x-vnd.Haiku-DriveSetup"
#define BOOTMAN_SIG "application/x-vnd.Haiku-Bootman"
const uint32 BEGIN_MESSAGE = 'iBGN'; const uint32 BEGIN_MESSAGE = 'iBGN';
const uint32 SHOW_BOTTOM_MESSAGE = 'iSBT'; const uint32 SHOW_BOTTOM_MESSAGE = 'iSBT';
const uint32 SETUP_MESSAGE = 'iSEP'; const uint32 LAUNCH_DRIVE_SETUP = 'iSEP';
const uint32 LAUNCH_BOOTMAN = 'iWBM';
const uint32 START_SCAN = 'iSSC'; const uint32 START_SCAN = 'iSSC';
const uint32 PACKAGE_CHECKBOX = 'iPCB'; const uint32 PACKAGE_CHECKBOX = 'iPCB';
const uint32 ENCOURAGE_DRIVESETUP = 'iENC'; const uint32 ENCOURAGE_DRIVESETUP = 'iENC';
@@ -151,6 +153,7 @@ InstallerWindow::InstallerWindow()
B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
fEncouragedToSetupPartitions(false), fEncouragedToSetupPartitions(false),
fDriveSetupLaunched(false), fDriveSetupLaunched(false),
fBootmanLaunched(false),
fInstallStatus(kReadyForInstall), fInstallStatus(kReadyForInstall),
fWorkerThread(new WorkerThread(this)), fWorkerThread(new WorkerThread(this)),
fCopyEngineCancelSemaphore(-1) fCopyEngineCancelSemaphore(-1)
@@ -206,8 +209,13 @@ InstallerWindow::InstallerWindow()
fBeginButton->MakeDefault(true); fBeginButton->MakeDefault(true);
fBeginButton->SetEnabled(false); fBeginButton->SetEnabled(false);
fSetupButton = new BButton("setup_button", fLaunchDriveSetupButton = new BButton("setup_button",
TR("Set up partitions" B_UTF8_ELLIPSIS), new BMessage(SETUP_MESSAGE)); TR("Set up partitions" B_UTF8_ELLIPSIS),
new BMessage(LAUNCH_DRIVE_SETUP));
fLaunchBootmanButton = new BButton("bootman_button",
TR("Set up boot menu"), new BMessage(LAUNCH_BOOTMAN));
fLaunchBootmanButton->SetEnabled(false);
fMakeBootableButton = new BButton("makebootable_button", fMakeBootableButton = new BButton("makebootable_button",
TR("Write boot sector"), new BMessage(MSG_WRITE_BOOT_SECTOR)); TR("Write boot sector"), new BMessage(MSG_WRITE_BOOT_SECTOR));
@@ -236,7 +244,8 @@ InstallerWindow::InstallerWindow()
) )
.Add(BGroupLayoutBuilder(B_HORIZONTAL, 10) .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10)
.Add(fSetupButton) .Add(fLaunchDriveSetupButton)
.Add(fLaunchBootmanButton)
.Add(fMakeBootableButton) .Add(fMakeBootableButton)
.AddGlue() .AddGlue()
.Add(fBeginButton) .Add(fBeginButton)
@@ -256,12 +265,17 @@ InstallerWindow::InstallerWindow()
fProgressLayoutItem->SetVisible(false); fProgressLayoutItem->SetVisible(false);
// Setup tool tips for the non-obvious features // Setup tool tips for the non-obvious features
fSetupButton->SetToolTip( fLaunchDriveSetupButton->SetToolTip(
TR("Launch the DriveSetup utility to partition\n" TR("Launch the DriveSetup utility to partition\n"
"available hard drives and other media.\n" "available hard drives and other media.\n"
"Partitions can be initialized with the\n" "Partitions can be initialized with the\n"
"Be File System needed for a Haiku boot\n" "Be File System needed for a Haiku boot\n"
"partition.")); "partition."));
fLaunchBootmanButton->SetToolTip(
TR("Install or uninstall the Haiku boot menu, which allows to "
"choose an operating system to boot when the computer starts.\n"
"If this computer already has a boot manager such as GRUB installed, "
"it is better to add Haiku to that menu than to overwrite it."));
fMakeBootableButton->SetToolTip( fMakeBootableButton->SetToolTip(
TR("Writes the Haiku boot code to the partition start\n" TR("Writes the Haiku boot code to the partition start\n"
"sector. This step is automatically performed by\n" "sector. This step is automatically performed by\n"
@@ -276,15 +290,18 @@ InstallerWindow::InstallerWindow()
CenterOnScreen(); CenterOnScreen();
Show(); Show();
// Register to receive notifications when apps launch or quit...
be_roster->StartWatching(this);
// ... and check the two we are interested in.
fDriveSetupLaunched = be_roster->IsRunning(DRIVESETUP_SIG); fDriveSetupLaunched = be_roster->IsRunning(DRIVESETUP_SIG);
fBootmanLaunched = be_roster->IsRunning(BOOTMAN_SIG);
if (Lock()) { if (Lock()) {
fSetupButton->SetEnabled(!fDriveSetupLaunched); fLaunchDriveSetupButton->SetEnabled(!fDriveSetupLaunched);
fLaunchBootmanButton->SetEnabled(!fBootmanLaunched);
Unlock(); Unlock();
} }
be_roster->StartWatching(this);
PostMessage(START_SCAN); PostMessage(START_SCAN);
} }
@@ -372,9 +389,12 @@ InstallerWindow::MessageReceived(BMessage *msg)
case TARGET_PARTITION: case TARGET_PARTITION:
_UpdateControls(); _UpdateControls();
break; break;
case SETUP_MESSAGE: case LAUNCH_DRIVE_SETUP:
_LaunchDriveSetup(); _LaunchDriveSetup();
break; break;
case LAUNCH_BOOTMAN:
_LaunchBootman();
break;
case PACKAGE_CHECKBOX: case PACKAGE_CHECKBOX:
{ {
char buffer[15]; char buffer[15];
@@ -468,17 +488,46 @@ InstallerWindow::MessageReceived(BMessage *msg)
case B_SOME_APP_QUIT: case B_SOME_APP_QUIT:
{ {
const char *signature; const char *signature;
if (msg->FindString("be:signature", &signature) == B_OK if (msg->FindString("be:signature", &signature) != B_OK)
&& strcasecmp(signature, DRIVESETUP_SIG) == 0) { break;
fDriveSetupLaunched = msg->what == B_SOME_APP_LAUNCHED; bool isDriveSetup = strcasecmp(signature, DRIVESETUP_SIG) == 0;
fBeginButton->SetEnabled(!fDriveSetupLaunched); bool isBootman = strcasecmp(signature, BOOTMAN_SIG) == 0;
_DisableInterface(fDriveSetupLaunched); if (isDriveSetup || isBootman) {
if (fDriveSetupLaunched) bool scanPartitions = false;
if (isDriveSetup) {
bool launched = msg->what == B_SOME_APP_LAUNCHED;
// We need to scan partitions if DriveSetup has quit.
scanPartitions = fDriveSetupLaunched && !launched;
fDriveSetupLaunched = launched;
}
if (isBootman)
fBootmanLaunched = msg->what == B_SOME_APP_LAUNCHED;
fBeginButton->SetEnabled(
!fDriveSetupLaunched && !fBootmanLaunched);
_DisableInterface(fDriveSetupLaunched || fBootmanLaunched);
if (fDriveSetupLaunched && fBootmanLaunched) {
_SetStatusMessage(TR("Running Boot Manager and "
"DriveSetup" B_UTF8_ELLIPSIS
"\n\nClose both applications to continue with the "
"installation."));
} else if (fDriveSetupLaunched) {
_SetStatusMessage(TR("Running DriveSetup" B_UTF8_ELLIPSIS _SetStatusMessage(TR("Running DriveSetup" B_UTF8_ELLIPSIS
"\n\nClose DriveSetup to continue with the " "\n\nClose DriveSetup to continue with the "
"installation.")); "installation."));
else } else if (fBootmanLaunched) {
_ScanPartitions(); _SetStatusMessage(TR("Running Boot Manager" B_UTF8_ELLIPSIS
"\n\nClose Boot Manager to continue with the "
"installation."));
} else {
// If neither DriveSetup nor Bootman is running, we need
// to scan partitions in case DriveSetup has quit, or
// we need to update the guidance message.
if (scanPartitions)
_ScanPartitions();
else
_UpdateControls();
}
} }
break; break;
} }
@@ -496,11 +545,21 @@ InstallerWindow::MessageReceived(BMessage *msg)
bool bool
InstallerWindow::QuitRequested() InstallerWindow::QuitRequested()
{ {
if (fDriveSetupLaunched) { if (fDriveSetupLaunched && fBootmanLaunched) {
(new BAlert("driveSetup", (new BAlert(TR("Quit Boot Manager and DriveSetup"),
TR("Please close the Boot Manager and DriveSetup windows before "
"closing the Installer window."), TR("OK")))->Go();
return false;
} else if (fDriveSetupLaunched) {
(new BAlert(TR("Quit DriveSetup"),
TR("Please close the DriveSetup window before closing the " TR("Please close the DriveSetup window before closing the "
"Installer window."), TR("OK")))->Go(); "Installer window."), TR("OK")))->Go();
return false; return false;
} else if (fBootmanLaunched) {
(new BAlert(TR("Quit Boot Manager"),
TR("Please close the Boot Manager window before closing the "
"Installer window."), TR("OK")))->Go();
return false;
} }
if (fInstallStatus != kFinished && (Flags() & B_NOT_MINIMIZABLE) != 0) { if (fInstallStatus != kFinished && (Flags() & B_NOT_MINIMIZABLE) != 0) {
@@ -558,10 +617,38 @@ InstallerWindow::_LaunchDriveSetup()
} }
void
InstallerWindow::_LaunchBootman()
{
// TODO: Currently bootman always tries to install to the "first" harddisk.
// If/when it later supports being installed to a certain harddisk, we
// would have to pass it the disk that contains the target partition here.
if (be_roster->Launch(BOOTMAN_SIG) != B_OK) {
// Try really hard to launch it. It's very likely that this fails,
// when we run from the CD and there is only an incomplete mime
// database for example...
BPath path;
if (find_directory(B_SYSTEM_BIN_DIRECTORY, &path) != B_OK
|| path.Append("bootman") != B_OK) {
path.SetTo("/boot/system/bin/bootman");
}
BEntry entry(path.Path());
entry_ref ref;
if (entry.GetRef(&ref) != B_OK || be_roster->Launch(&ref) != B_OK) {
BAlert* alert = new BAlert("error", TR("Bootman, the "
"application to configure the Haiku boot menu, could not be "
"launched."), TR("OK"));
alert->Go();
}
}
}
void void
InstallerWindow::_DisableInterface(bool disable) InstallerWindow::_DisableInterface(bool disable)
{ {
fSetupButton->SetEnabled(!disable); fLaunchDriveSetupButton->SetEnabled(!disable);
fLaunchBootmanButton->SetEnabled(!disable);
fMakeBootableButton->SetEnabled(!disable); fMakeBootableButton->SetEnabled(!disable);
fSrcMenuField->SetEnabled(!disable); fSrcMenuField->SetEnabled(!disable);
fDestMenuField->SetEnabled(!disable); fDestMenuField->SetEnabled(!disable);
@@ -581,9 +668,9 @@ InstallerWindow::_ScanPartitions()
fWorkerThread->ScanDisksPartitions(fSrcMenu, fDestMenu); fWorkerThread->ScanDisksPartitions(fSrcMenu, fDestMenu);
if (fSrcMenu->ItemAt(0)) { if (fSrcMenu->ItemAt(0) != NULL)
_PublishPackages(); _PublishPackages();
}
_UpdateControls(); _UpdateControls();
} }
@@ -632,15 +719,15 @@ InstallerWindow::_UpdateControls()
} }
fDestMenuField->MenuItem()->SetLabel(label.String()); fDestMenuField->MenuItem()->SetLabel(label.String());
if (srcItem && dstItem) { if (srcItem != NULL && dstItem != NULL) {
char message[255]; char message[255];
sprintf(message, TR("Press the Begin button to install from '%1s' " sprintf(message, TR("Press the Begin button to install from '%1s' "
"onto '%2s'."), srcItem->Name(), dstItem->Name()); "onto '%2s'."), srcItem->Name(), dstItem->Name());
_SetStatusMessage(message); _SetStatusMessage(message);
} else if (srcItem) { } else if (srcItem != NULL) {
_SetStatusMessage(TR("Choose the disk you want to install onto from " _SetStatusMessage(TR("Choose the disk you want to install onto from "
"the pop-up menu. Then click \"Begin\".")); "the pop-up menu. Then click \"Begin\"."));
} else if (dstItem) { } else if (dstItem != NULL) {
_SetStatusMessage(TR("Choose the source disk from the " _SetStatusMessage(TR("Choose the source disk from the "
"pop-up menu. Then click \"Begin\".")); "pop-up menu. Then click \"Begin\"."));
} else { } else {
@@ -652,16 +739,17 @@ InstallerWindow::_UpdateControls()
fBeginButton->SetLabel(TR("Begin")); fBeginButton->SetLabel(TR("Begin"));
fBeginButton->SetEnabled(srcItem && dstItem); fBeginButton->SetEnabled(srcItem && dstItem);
// adjust "Write Boot Sector" button // adjust "Write Boot Sector" and "Set up boot menu" buttons
if (dstItem) { if (dstItem != NULL) {
char buffer[256]; char buffer[256];
snprintf(buffer, sizeof(buffer), TR("Write boot sector to '%s'"), snprintf(buffer, sizeof(buffer), TR("Write boot sector to '%s'"),
dstItem->Name()); dstItem->Name());
label = buffer; label = buffer;
} else } else
label = TR("Write boot sector"); label = TR("Write boot sector");
fMakeBootableButton->SetEnabled(dstItem); fMakeBootableButton->SetEnabled(dstItem != NULL);
fMakeBootableButton->SetLabel(label.String()); fMakeBootableButton->SetLabel(label.String());
fLaunchBootmanButton->SetEnabled(dstItem != NULL);
if (!fEncouragedToSetupPartitions && !foundOneSuitableTarget) { if (!fEncouragedToSetupPartitions && !foundOneSuitableTarget) {
// Focus the users attention on the DriveSetup button // Focus the users attention on the DriveSetup button
@@ -676,7 +764,7 @@ InstallerWindow::_PublishPackages()
{ {
fPackagesView->Clean(); fPackagesView->Clean();
PartitionMenuItem *item = (PartitionMenuItem *)fSrcMenu->FindMarked(); PartitionMenuItem *item = (PartitionMenuItem *)fSrcMenu->FindMarked();
if (!item) if (item == NULL)
return; return;
BPath directory; BPath directory;
+5 -2
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2009, Stephan Aßmus <[email protected]> * Copyright 2009-2010, Stephan Aßmus <[email protected]>
* Copyright 2005, Jérôme DUVAL * Copyright 2005, Jérôme DUVAL
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@@ -53,6 +53,7 @@ public:
private: private:
void _ShowOptionalPackages(); void _ShowOptionalPackages();
void _LaunchDriveSetup(); void _LaunchDriveSetup();
void _LaunchBootman();
void _DisableInterface(bool disable); void _DisableInterface(bool disable);
void _ScanPartitions(); void _ScanPartitions();
void _UpdateControls(); void _UpdateControls();
@@ -84,12 +85,14 @@ private:
BLayoutItem* fProgressLayoutItem; BLayoutItem* fProgressLayoutItem;
BButton* fBeginButton; BButton* fBeginButton;
BButton* fSetupButton; BButton* fLaunchDriveSetupButton;
BButton* fLaunchBootmanButton;
BButton* fMakeBootableButton; BButton* fMakeBootableButton;
bool fEncouragedToSetupPartitions; bool fEncouragedToSetupPartitions;
bool fDriveSetupLaunched; bool fDriveSetupLaunched;
bool fBootmanLaunched;
InstallStatus fInstallStatus; InstallStatus fInstallStatus;
WorkerThread* fWorkerThread; WorkerThread* fWorkerThread;