* Copyright 2017 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Brian Hill
*/
#include "TaskTimer.h"
#include <Application.h>
#include <Catalog.h>
#include "constants.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "TaskTimer"
static int32 sAlertStackCount = 0;
TaskTimer::TaskTimer(const BMessenger& target, Task* owner)
:
BLooper(),
fTimeoutMicroSeconds(kTimerTimeoutSeconds * 1000000),
fTimerIsRunning(false),
fReplyTarget(target),
fMessageRunner(NULL),
fTimeoutMessage(TASK_TIMEOUT),
fTimeoutAlert(NULL),
fOwner(owner)
{
Run();
fMessenger.SetTo(this);
fTimeoutAlertInvoker.SetMessage(
new BMessage(TIMEOUT_ALERT_BUTTON_SELECTION));
fTimeoutAlertInvoker.SetTarget(this);
}
TaskTimer::~TaskTimer()
{
if (fTimeoutAlert) {
fTimeoutAlert->Lock();
fTimeoutAlert->Quit();
}
if (fMessageRunner)
fMessageRunner->SetCount(0);
}
bool
TaskTimer::QuitRequested()
{
return true;
}
void
TaskTimer::MessageReceived(BMessage* message)
{
switch (message->what)
{
case TASK_TIMEOUT:
{
fMessageRunner = NULL;
if (fTimerIsRunning) {
BString text(B_TRANSLATE_COMMENT("The task for repository"
" %name% is taking a long time to complete.",
"Alert message. Do not translate %name%"));
BString nameString("\"");
nameString.Append(fRepositoryName).Append("\"");
text.ReplaceFirst("%name%", nameString);
fTimeoutAlert = new BAlert("timeout", text,
B_TRANSLATE_COMMENT("Keep trying", "Button label"),
B_TRANSLATE_COMMENT("Cancel task", "Button label"),
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
fTimeoutAlert->SetShortcut(0, B_ESCAPE);
BRect windowFrame = be_app->WindowAt(0)->Frame();
int32 stackPos = _NextAlertStackCount();
float xPos = windowFrame.left
+ windowFrame.Width()/2 + stackPos * kTimerAlertOffset;
float yPos = windowFrame.top
+ (stackPos + 1) * kTimerAlertOffset;
fTimeoutAlert->Go(&fTimeoutAlertInvoker);
xPos -= fTimeoutAlert->Frame().Width()/2;
fTimeoutAlert->MoveTo(xPos, yPos);
}
break;
}
case TIMEOUT_ALERT_BUTTON_SELECTION:
{
fTimeoutAlert = NULL;
if (fTimerIsRunning) {
int32 selection = -1;
message->FindInt32("which", &selection);
if (selection == 1) {
BMessage reply(TASK_KILL_REQUEST);
reply.AddPointer(key_taskptr, fOwner);
fReplyTarget.SendMessage(&reply);
} else if (selection == 0) {
fMessageRunner = new BMessageRunner(fMessenger,
&fTimeoutMessage, kTimerRetrySeconds * 1000000, 1);
}
}
break;
}
}
}
void
TaskTimer::Start(const char* name)
{
fTimerIsRunning = true;
fRepositoryName.SetTo(name);
if (fMessageRunner == NULL) {
fMessageRunner = new BMessageRunner(fMessenger, &fTimeoutMessage,
fTimeoutMicroSeconds, 1);
}
else
fMessageRunner->SetInterval(fTimeoutMicroSeconds);
}
void
TaskTimer::Stop(const char* name)
{
fTimerIsRunning = false;
if (fMessageRunner != NULL)
fMessageRunner->SetInterval(LLONG_MAX);
if (fTimeoutAlert) {
BRect frame = fTimeoutAlert->Frame();
fTimeoutAlert->Quit();
fTimeoutAlert = NULL;
BString text(B_TRANSLATE_COMMENT("Good news! The task for repository "
"%name% completed.", "Alert message. Do not translate %name%"));
BString nameString("\"");
nameString.Append(name).Append("\"");
text.ReplaceFirst("%name%", nameString);
BAlert* newAlert = new BAlert("timeout", text, kOKLabel, NULL, NULL,
B_WIDTH_AS_USUAL, B_WARNING_ALERT);
newAlert->SetShortcut(0, B_ESCAPE);
newAlert->MoveTo(frame.left, frame.top);
newAlert->Go(NULL);
}
}
int32
TaskTimer::_NextAlertStackCount()
{
if (sAlertStackCount > 9)
sAlertStackCount = 0;
return sAlertStackCount++;
}