Files
haiku-beta6/src/preferences/notifications/GeneralView.cpp
T
Adrien Destugues 267479782d Various build fixes.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40033 a95241bf-73f2-0310-859d-f6bbb57e9c96
2010-12-29 17:02:32 +00:00

373 lines
9.1 KiB
C++

/*
* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License.
*
* Authors:
* Pier Luigi Fiorini, [email protected]
*/
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <Roster.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <Alert.h>
#include <Font.h>
#include <Button.h>
#include <Catalog.h>
#include <StringView.h>
#include <TextControl.h>
#include <CheckBox.h>
#include <String.h>
#include <FindDirectory.h>
#include <Node.h>
#include <notification/Notifications.h>
#include <Path.h>
#include <File.h>
#include <Directory.h>
#include <VolumeRoster.h>
#include <Volume.h>
#include <Query.h>
#include <SymLink.h>
#include "GeneralView.h"
#include "SettingsHost.h"
#undef B_TRANSLATE_CONTEXT
#define B_TRANSLATE_CONTEXT "GeneralView"
const int32 kServer = '_TSR';
const char* kStartServer = B_TRANSLATE("Enable notifications");
const char* kStopServer = B_TRANSLATE("Disable notifications");
const char* kStarted = B_TRANSLATE("Events are notified");
const char* kStopped = B_TRANSLATE("Events are not notified");
GeneralView::GeneralView(SettingsHost* host)
:
SettingsPane("general", host)
{
BFont statusFont;
// Set a smaller font for the status label
statusFont.SetSize(be_plain_font->Size() * 0.8);
// Status button and label
fServerButton = new BButton("server", kStartServer, new BMessage(kServer));
fStatusLabel = new BStringView("status", kStopped);
fStatusLabel->SetFont(&statusFont);
// Update status label and server button
if (_IsServerRunning()) {
fServerButton->SetLabel(kStopServer);
fStatusLabel->SetText(kStarted);
} else {
fServerButton->SetLabel(kStartServer);
fStatusLabel->SetText(kStopped);
}
// Autostart
fAutoStart = new BCheckBox("autostart",
B_TRANSLATE("Enable notifications at startup"),
new BMessage(kSettingChanged));
// Display time
fTimeout = new BTextControl(B_TRANSLATE("Hide notifications from screen"
" after"), NULL, new BMessage(kSettingChanged));
BStringView* displayTimeLabel = new BStringView("dt_label",
B_TRANSLATE("seconds of inactivity"));
// Default position
// TODO: Here will come a screen representation with the four corners clickable
// Load settings
Load();
// Calculate inset
float inset = ceilf(be_plain_font->Size() * 0.7f);
SetLayout(new BGroupLayout(B_VERTICAL));
AddChild(BGroupLayoutBuilder(B_VERTICAL, inset)
.AddGroup(B_HORIZONTAL, inset)
.Add(fServerButton)
.Add(fStatusLabel)
.AddGlue()
.End()
.AddGroup(B_VERTICAL, inset)
.Add(fAutoStart)
.AddGroup(B_HORIZONTAL)
.AddGroup(B_HORIZONTAL, 2)
.Add(fTimeout)
.Add(displayTimeLabel)
.End()
.End()
.End()
.AddGlue()
);
}
void
GeneralView::AttachedToWindow()
{
fServerButton->SetTarget(this);
fAutoStart->SetTarget(this);
fTimeout->SetTarget(this);
}
void
GeneralView::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case kServer: {
entry_ref ref;
// Check if server is available
if (!_CanFindServer(&ref)) {
BAlert* alert = new BAlert(B_TRANSLATE("Notifications"),
B_TRANSLATE("The notifications server cannot be"
" found, this means your InfoPopper installation was"
" not successfully completed."), B_TRANSLATE("OK"),
NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
return;
}
if (_IsServerRunning()) {
// Server team
team_id team = be_roster->TeamFor(kNotificationServerSignature);
// Establish a connection to infopopper_server
status_t ret = B_ERROR;
BMessenger messenger(kNotificationServerSignature, team, &ret);
if (ret != B_OK) {
BAlert* alert = new BAlert(B_TRANSLATE(
"Notifications"), B_TRANSLATE("Notifications "
"cannot be stopped, because the server can't be"
" reached."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
return;
}
// Send quit message
if (messenger.SendMessage(new BMessage(B_QUIT_REQUESTED)) != B_OK) {
BAlert* alert = new BAlert(B_TRANSLATE(
"Notifications"), B_TRANSLATE("Cannot disable"
" notifications because the server can't be "
"reached."), B_TRANSLATE("OK"),
NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
return;
}
fServerButton->SetLabel(kStartServer);
fStatusLabel->SetText(kStopped);
} else {
// Start server
status_t err = be_roster->Launch(kNotificationServerSignature);
if (err != B_OK) {
BAlert* alert = new BAlert(B_TRANSLATE(
"Notifications"), B_TRANSLATE("Cannot enable"
" notifications because the server cannot be "
"found.\nThis means your InfoPopper installation"
" was not successfully completed."),
B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
B_STOP_ALERT);
(void)alert->Go();
return;
}
fServerButton->SetLabel(kStopServer);
fStatusLabel->SetText(kStarted);
}
} break;
case kSettingChanged:
SettingsPane::MessageReceived(msg);
break;
default:
BView::MessageReceived(msg);
break;
}
}
status_t
GeneralView::Load()
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append(kSettingsDirectory);
if (create_directory(path.Path(), 0755) != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("There was a problem saving the preferences.\n"
"It's possible you don't have write access to the "
"settings directory."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
}
path.Append(kGeneralSettings);
BMessage settings;
BFile file(path.Path(), B_READ_ONLY);
settings.Unflatten(&file);
char buffer[255];
bool autoStart;
if (settings.FindBool(kAutoStartName, &autoStart) != B_OK)
autoStart = kDefaultAutoStart;
fAutoStart->SetValue(autoStart ? B_CONTROL_ON : B_CONTROL_OFF);
int32 timeout;
if (settings.FindInt32(kTimeoutName, &timeout) != B_OK)
timeout = kDefaultTimeout;
(void)sprintf(buffer, "%ld", timeout);
fTimeout->SetText(buffer);
return B_OK;
}
status_t
GeneralView::Save()
{
BPath path;
status_t ret = B_OK;
ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
if (ret != B_OK)
return ret;
path.Append(kSettingsDirectory);
path.Append(kGeneralSettings);
BMessage settings;
bool autoStart = (fAutoStart->Value() == B_CONTROL_ON);
settings.AddBool(kAutoStartName, autoStart);
int32 timeout = atol(fTimeout->Text());
settings.AddInt32(kTimeoutName, timeout);
// Save settings file
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
ret = settings.Flatten(&file);
if (ret != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("An error occurred saving the preferences.\n"
"It's possible you are running out of disk space."),
B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
return ret;
}
// Find server path
entry_ref ref;
if (!_CanFindServer(&ref)) {
BAlert* alert = new BAlert("",
B_TRANSLATE("The notifications server cannot be found.\n"
"A possible cause is an installation not done correctly"),
B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
return B_ERROR;
}
// UserBootscript command
BPath serverPath(&ref);
// Start server at boot time
ret = find_directory(B_USER_BOOT_DIRECTORY, &path, true);
if (ret != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("Can't save preferences, you probably don't have "
"write access to the boot settings directory."), B_TRANSLATE("OK"),
NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
return ret;
}
path.Append("launch");
BDirectory directory(path.Path());
BEntry entry(&directory, serverPath.Leaf());
// Remove symbolic link
entry.Remove();
if (autoStart) {
// Put a symlink into ~/config/boot/launch
if ((ret = directory.CreateSymLink(serverPath.Leaf(),
serverPath.Path(), NULL) != B_OK)) {
BAlert* alert = new BAlert("",
B_TRANSLATE("Can't enable notifications at startup time, "
"you probably don't have write permission to the boot settings"
" directory."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
(void)alert->Go();
return ret;
}
}
return B_OK;
}
status_t
GeneralView::Revert()
{
return B_ERROR;
}
bool
GeneralView::_CanFindServer(entry_ref* ref)
{
// Try searching with be_roster
if (be_roster->FindApp(kNotificationServerSignature, ref) == B_OK)
return true;
// Try with a query and take the first result
BVolumeRoster vroster;
BVolume volume;
char volName[B_FILE_NAME_LENGTH];
vroster.Rewind();
while (vroster.GetNextVolume(&volume) == B_OK) {
if ((volume.InitCheck() != B_OK) || !volume.KnowsQuery())
continue;
volume.GetName(volName);
BQuery *query = new BQuery();
query->SetPredicate("(BEOS:APP_SIG==\""kNotificationServerSignature"\")");
query->SetVolume(&volume);
query->Fetch();
if (query->GetNextRef(ref) == B_OK)
return true;
}
return false;
}
bool
GeneralView::_IsServerRunning()
{
return be_roster->IsRunning(kNotificationServerSignature);
}