From 739dbdfae4dca5237d84062a640c569d2ed28ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 12 May 2008 11:38:10 +0000 Subject: [PATCH] * Patch from Christian Fasshauer: provides a cancel button * fixed a few things: one couldn't restart the install process when cancelled, use B_QUIT_REQUESTED instead of QuitRequested(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25466 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/installer/CopyEngine.cpp | 30 ++++++++-- src/apps/installer/CopyEngine.h | 1 + .../installer/InstallerCopyLoopControl.cpp | 23 +++++++- src/apps/installer/InstallerCopyLoopControl.h | 3 + src/apps/installer/InstallerWindow.cpp | 57 ++++++++++++++----- src/apps/installer/InstallerWindow.h | 9 +++ 6 files changed, 103 insertions(+), 20 deletions(-) diff --git a/src/apps/installer/CopyEngine.cpp b/src/apps/installer/CopyEngine.cpp index 1aacfc51f0..e5134800fe 100644 --- a/src/apps/installer/CopyEngine.cpp +++ b/src/apps/installer/CopyEngine.cpp @@ -74,8 +74,10 @@ CopyEngine::MessageReceived(BMessage*msg) { status_t err = Start(fWindow->GetSourceMenu(), fWindow->GetTargetMenu()); - if (err != B_OK) + if (err != B_OK) { ERR("Start failed"); + BMessenger(fWindow).SendMessage(RESET_INSTALL); + } break; } } @@ -123,6 +125,9 @@ status_t CopyEngine::Start(BMenu *srcMenu, BMenu *targetMenu) { CALLED(); + + fControl->Reset(); + status_t err = B_OK; PartitionMenuItem *targetItem = (PartitionMenuItem *)targetMenu->FindMarked(); PartitionMenuItem *srcItem = (PartitionMenuItem *)srcMenu->FindMarked(); @@ -182,6 +187,7 @@ CopyEngine::Start(BMenu *srcMenu, BMenu *targetMenu) "Try choosing a different disk or choose to not install optional " "items.", "Try installing anyway", "Cancel", 0, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) { + BMessenger(fWindow).SendMessage(RESET_INSTALL); return B_OK; } @@ -203,6 +209,7 @@ CopyEngine::Start(BMenu *srcMenu, BMenu *targetMenu) if (strcmp(srcDirectory.Path(), targetDirectory.Path()) == 0) { SetStatusMessage("You can't install the contents of a disk onto " "itself. Please choose a different disk."); + BMessenger(fWindow).SendMessage(RESET_INSTALL); return B_OK; } @@ -213,6 +220,7 @@ CopyEngine::Start(BMenu *srcMenu, BMenu *targetMenu) "machine if you proceed.", "OK", "Cancel", 0, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) { SetStatusMessage("Installation stopped."); + BMessenger(fWindow).SendMessage(RESET_INSTALL); return B_OK; } @@ -230,16 +238,20 @@ CopyEngine::Start(BMenu *srcMenu, BMenu *targetMenu) BDirectory packageDir; int32 count = fPackages->CountItems(); for (int32 i = 0; i < count; i++) { + if (fControl->CheckUserCanceled()) + return B_OK; Package *p = static_cast(fPackages->ItemAt(i)); packageDir.SetTo(&srcDir, p->Folder()); CopyFolder(packageDir, targetDir); } } - LaunchFinishScript(targetDirectory); + if (!fControl->CheckUserCanceled()) { + LaunchFinishScript(targetDirectory); - BMessage msg(INSTALL_FINISHED); - BMessenger(fWindow).SendMessage(&msg); + BMessage msg(INSTALL_FINISHED); + BMessenger(fWindow).SendMessage(&msg); + } return B_OK; } @@ -250,7 +262,8 @@ CopyEngine::CopyFolder(BDirectory &srcDir, BDirectory &targetDir) { BEntry entry; status_t err; - while (srcDir.GetNextEntry(&entry) == B_OK) { + while (srcDir.GetNextEntry(&entry) == B_OK + && !fControl->CheckUserCanceled()) { StatStruct statbuf; entry.GetStat(&statbuf); @@ -299,6 +312,13 @@ CopyEngine::SetPackagesList(BList *list) } +bool +CopyEngine::Cancel() +{ + return fControl->Cancel(); +} + + // #pragma mark - diff --git a/src/apps/installer/CopyEngine.h b/src/apps/installer/CopyEngine.h index 7f01d3798e..2c42fd4de6 100644 --- a/src/apps/installer/CopyEngine.h +++ b/src/apps/installer/CopyEngine.h @@ -28,6 +28,7 @@ class CopyEngine : public BLooper { void ScanDisksPartitions(BMenu *srcMenu, BMenu *targetMenu); void SetPackagesList(BList *list); void SetSpaceRequired(off_t bytes) { fSpaceRequired = bytes; }; + bool Cancel(); private: void LaunchInitScript(BPath &path); void LaunchFinishScript(BPath &path); diff --git a/src/apps/installer/InstallerCopyLoopControl.cpp b/src/apps/installer/InstallerCopyLoopControl.cpp index a4e2c9e729..ea64fae341 100644 --- a/src/apps/installer/InstallerCopyLoopControl.cpp +++ b/src/apps/installer/InstallerCopyLoopControl.cpp @@ -9,7 +9,8 @@ InstallerCopyLoopControl::InstallerCopyLoopControl(InstallerWindow *window) : fWindow(window), - fMessenger(window) + fMessenger(window), + fUserCanceled(false) { } @@ -48,7 +49,7 @@ InstallerCopyLoopControl::UpdateStatus(const char *name, entry_ref ref, int32 co bool InstallerCopyLoopControl::CheckUserCanceled() { - return false; + return fUserCanceled; } @@ -97,3 +98,21 @@ InstallerCopyLoopControl::PreserveAttribute(const char *attributeName) return false; } + +bool +InstallerCopyLoopControl::Cancel() +{ + fUserCanceled = (new BAlert("", + "Are you sure you want to to stop the installation?", + "Continue", "Stop", 0, + B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0; + return fUserCanceled; +} + + +void +InstallerCopyLoopControl::Reset() +{ + fUserCanceled = false; +} + diff --git a/src/apps/installer/InstallerCopyLoopControl.h b/src/apps/installer/InstallerCopyLoopControl.h index db038deaed..67716a495c 100644 --- a/src/apps/installer/InstallerCopyLoopControl.h +++ b/src/apps/installer/InstallerCopyLoopControl.h @@ -35,10 +35,13 @@ class InstallerCopyLoopControl : public CopyLoopControl virtual bool ChecksumFile(const entry_ref *); virtual bool SkipAttribute(const char *attributeName); virtual bool PreserveAttribute(const char *attributeName); + bool Cancel(); + void Reset(); private: InstallerWindow *fWindow; BMessenger fMessenger; + bool fUserCanceled; }; #endif diff --git a/src/apps/installer/InstallerWindow.cpp b/src/apps/installer/InstallerWindow.cpp index 0f8113859e..d969345de0 100644 --- a/src/apps/installer/InstallerWindow.cpp +++ b/src/apps/installer/InstallerWindow.cpp @@ -71,6 +71,7 @@ InstallerWindow::InstallerWindow(BRect frame_rect) : BWindow(frame_rect, "Installer", B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE), fDriveSetupLaunched(false), + fInstallStatus(kReadyForInstall), fLastSrcItem(NULL), fLastTargetItem(NULL) { @@ -110,6 +111,7 @@ InstallerWindow::InstallerWindow(BRect frame_rect) "begin_button", "Begin", new BMessage(BEGIN_MESSAGE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); fBeginButton->MakeDefault(true); + fBeginButton->SetEnabled(false); fBackBox->AddChild(fBeginButton); fSetupButton = new BButton(BRect(bounds.left + 11, bounds.bottom - 35, @@ -135,18 +137,18 @@ InstallerWindow::InstallerWindow(BRect frame_rect) fDestMenu = new BPopUpMenu("scanning" B_UTF8_ELLIPSIS, true, false); fSrcMenu = new BPopUpMenu("scanning" B_UTF8_ELLIPSIS, true, false); - BRect fieldRect(bounds.left + 50, bounds.top + 70, bounds.right - 13, + BRect fieldRect(bounds.left + 13, bounds.top + 70, bounds.right - 13, bounds.top + 90); fSrcMenuField = new BMenuField(fieldRect, "srcMenuField", "Install from: ", fSrcMenu); - fSrcMenuField->SetDivider(bounds.right - 274); + fSrcMenuField->SetDivider(bounds.right - 300); fSrcMenuField->SetAlignment(B_ALIGN_RIGHT); fBackBox->AddChild(fSrcMenuField); fieldRect.OffsetBy(0, 23); fDestMenuField = new BMenuField(fieldRect, "destMenuField", "Onto: ", fDestMenu); - fDestMenuField->SetDivider(bounds.right - 274); + fDestMenuField->SetDivider(bounds.right - 300); fDestMenuField->SetAlignment(B_ALIGN_RIGHT); fBackBox->AddChild(fDestMenuField); @@ -182,20 +184,45 @@ void InstallerWindow::MessageReceived(BMessage *msg) { switch (msg->what) { + case RESET_INSTALL: + fInstallStatus = kReadyForInstall; + fBeginButton->SetEnabled(true); + DisableInterface(false); + fBeginButton->SetLabel("Begin"); + break; case START_SCAN: StartScan(); + fBeginButton->SetEnabled(true); break; case BEGIN_MESSAGE: - { - BList *list = new BList(); - int32 size = 0; - fPackagesView->GetPackagesToInstall(list, &size); - fCopyEngine->SetPackagesList(list); - fCopyEngine->SetSpaceRequired(size); - BMessenger(fCopyEngine).SendMessage(ENGINE_START); - DisableInterface(true); + switch (fInstallStatus) { + case kReadyForInstall: + { + BList *list = new BList(); + int32 size = 0; + fPackagesView->GetPackagesToInstall(list, &size); + fCopyEngine->SetPackagesList(list); + fCopyEngine->SetSpaceRequired(size); + BMessenger(fCopyEngine).SendMessage(ENGINE_START); + fBeginButton->SetLabel("Stop"); + DisableInterface(true); + fInstallStatus = kInstalling; + break; + } + case kInstalling: + if (fCopyEngine->Cancel()) { + fInstallStatus = kCancelled; + SetStatusMessage("Installation cancelled."); + PostMessage(RESET_INSTALL); + } + break; + case kFinished: + PostMessage(B_QUIT_REQUESTED); + break; + case kCancelled: + break; + } break; - } case SHOW_BOTTOM_MESSAGE: ShowBottom(); break; @@ -224,6 +251,8 @@ InstallerWindow::MessageReceived(BMessage *msg) break; } case STATUS_MESSAGE: { + if (fInstallStatus != kInstalling) + break; const char *status; if (msg->FindString("status", &status) == B_OK) { fLastStatus = fStatusView->Text(); @@ -233,6 +262,8 @@ InstallerWindow::MessageReceived(BMessage *msg) break; } case INSTALL_FINISHED: + fBeginButton->SetLabel("Quit"); + fInstallStatus = kFinished; DisableInterface(false); break; case B_SOME_APP_LAUNCHED: @@ -242,6 +273,7 @@ InstallerWindow::MessageReceived(BMessage *msg) if (msg->FindString("be:signature", &signature) == B_OK && strcasecmp(signature, DRIVESETUP_SIG) == 0) { fDriveSetupLaunched = msg->what == B_SOME_APP_LAUNCHED; + fBeginButton->SetEnabled(!fDriveSetupLaunched); DisableInterface(fDriveSetupLaunched); if (fDriveSetupLaunched) SetStatusMessage("Running DriveSetup" B_UTF8_ELLIPSIS @@ -307,7 +339,6 @@ InstallerWindow::LaunchDriveSetup() void InstallerWindow::DisableInterface(bool disable) { - fBeginButton->SetEnabled(!disable); fSetupButton->SetEnabled(!disable); fSrcMenuField->SetEnabled(!disable); fDestMenuField->SetEnabled(!disable); diff --git a/src/apps/installer/InstallerWindow.h b/src/apps/installer/InstallerWindow.h index aac5f78b91..7e372710cd 100644 --- a/src/apps/installer/InstallerWindow.h +++ b/src/apps/installer/InstallerWindow.h @@ -20,8 +20,16 @@ #define INSTALLER_RIGHT 402 +enum InstallStatus { + kReadyForInstall, + kInstalling, + kFinished, + kCancelled +}; + const uint32 STATUS_MESSAGE = 'iSTM'; const uint32 INSTALL_FINISHED = 'iIFN'; +const uint32 RESET_INSTALL = 'iRSI'; const char PACKAGES_DIRECTORY[] = "_packages_"; class InstallerWindow : public BWindow { @@ -46,6 +54,7 @@ class InstallerWindow : public BWindow { BButton *fBeginButton, *fSetupButton; DrawButton *fDrawButton; bool fDriveSetupLaunched; + InstallStatus fInstallStatus; BTextView *fStatusView; BMenu* fSrcMenu, *fDestMenu; BMenuField* fSrcMenuField, *fDestMenuField;