Added application which is supposed to replace the "Do you wish to run the

Installer or continue booting to the Desktop" alert that pops up on CD boots.
It allows to set the language and keymap as the very first thing before a Haiku
installation. (Aside from replacing the alert.) Everything tested and working,
I just need to test integration in the Bootscript.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35221 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2010-01-21 14:41:58 +00:00
parent 9471043456
commit fa74162f8a
7 changed files with 592 additions and 0 deletions
+1
View File
@@ -43,6 +43,7 @@ HaikuSubInclude poorman ;
HaikuSubInclude powerstatus ;
HaikuSubInclude processcontroller ;
HaikuSubInclude pulse ;
HaikuSubInclude readonlybootprompt ;
HaikuSubInclude remotedesktop ;
HaikuSubInclude resedit ;
HaikuSubInclude screenshot ;
@@ -0,0 +1,78 @@
/*
* Copyright 2010, Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "BootPrompt.h"
#include <stdlib.h>
#include <AboutWindow.h>
#include <Locale.h>
#include "BootPromptWindow.h"
int
main(int, char **)
{
BootPromptApp app;
app.Run();
return 0;
}
// #pragma mark -
const char* kAppSignature = "application/x-vnd.Haiku-ReadOnlyBootPrompt";
BootPromptApp::BootPromptApp()
:
BApplication(kAppSignature)
{
}
void
BootPromptApp::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_BOOT_DESKTOP:
// TODO: Exit with some value that the Bootscript can deal with.
exit(1);
break;
case MSG_RUN_INSTALLER:
// TODO: Exit with some value that the Bootscript can deal with.
exit(0);
break;
default:
BApplication::MessageReceived(message);
}
}
void
BootPromptApp::AboutRequested()
{
const char* kAuthors[] = {
"Stephan Aßmus",
NULL
};
BAboutWindow* aboutWindow = new BAboutWindow("ReadOnlyBootPrompt", 2010,
kAuthors);
aboutWindow->Show();
}
void
BootPromptApp::ReadyToRun()
{
// Prompt the user to select his preferred language.
new BootPromptWindow();
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright 2010, Stephan Aßmus <[email protected]>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef BOOT_PROMPT_APP_H
#define BOOT_PROMPT_APP_H
#include <Application.h>
enum {
MSG_BOOT_DESKTOP = 'dktp',
MSG_RUN_INSTALLER = 'inst'
};
extern const char* kAppSignature;
class BootPromptApp : public BApplication {
public:
BootPromptApp();
virtual void MessageReceived(BMessage* message);
virtual void AboutRequested();
virtual void ReadyToRun();
};
#endif // BOOT_PROMPT_APP_H
@@ -0,0 +1,17 @@
resource app_signature "application/x-vnd.Haiku-ReadOnlyBootPrompt";
resource app_version {
major = 1,
middle = 0,
minor = 0,
variety = B_APPV_BETA,
internal = 0,
short_info = "ReadOnlyBootPrompt",
long_info = "ReadOnlyBootPrompt ©2010 The Haiku Project"
};
resource app_flags B_EXCLUSIVE_LAUNCH;
@@ -0,0 +1,398 @@
/*
* Copyright 2010, Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "BootPromptWindow.h"
#include <stdio.h>
#include <Button.h>
#include <ControlLook.h>
#include <Directory.h>
#include <Entry.h>
#include <Font.h>
#include <FindDirectory.h>
#include <File.h>
#include <GroupLayoutBuilder.h>
#include <ListView.h>
#include <Locale.h>
#include <LocaleRoster.h>
#include <Path.h>
#include <ScrollView.h>
#include <SeparatorView.h>
#include <StringItem.h>
#include <StringView.h>
#include <TextView.h>
#include "BootPrompt.h"
#include "Keymap.h"
#include "KeymapListItem.h"
enum {
MSG_LANGUAGE_SELECTED = 'lngs',
MSG_KEYMAP_SELECTED = 'kmps'
};
#undef TR_CONTEXT
#define TR_CONTEXT "BootPromptWindow"
class LanguageItem : public BStringItem {
public:
LanguageItem(const char* label, const char* language)
:
BStringItem(label),
fLanguage(language)
{
}
const char* Language() const
{
return fLanguage.String();
}
private:
BString fLanguage;
};
BootPromptWindow::BootPromptWindow()
:
BWindow(BRect(0, 0, 450, 380), "",
B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_NOT_CLOSABLE
| B_AUTO_UPDATE_SIZE_LIMITS)
{
// TODO: Remove once BLocalRoster is fixed.
be_locale_roster->GetInstalledLanguages(&fInstalledLanguages);
fInfoTextView = new BTextView("info", be_plain_font, NULL, B_WILL_DRAW);
fInfoTextView->SetInsets(10, 10, 10, 10);
fInfoTextView->MakeEditable(false);
fInfoTextView->MakeSelectable(false);
BScrollView* infoScrollView = new BScrollView("infoScroll",
fInfoTextView, B_WILL_DRAW, false, true);
fDesktopButton = new BButton("", new BMessage(MSG_BOOT_DESKTOP));
fDesktopButton->SetTarget(be_app);
fDesktopButton->MakeDefault(true);
fInstallerButton = new BButton("", new BMessage(MSG_RUN_INSTALLER));
fInstallerButton->SetTarget(be_app);
fLanguagesLabelView = new BStringView("languagesLabel", "");
fLanguagesLabelView->SetFont(be_bold_font);
fLanguagesLabelView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,
B_SIZE_UNSET));
fKeymapsLabelView = new BStringView("keymapsLabel", "");
fKeymapsLabelView->SetFont(be_bold_font);
fKeymapsLabelView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,
B_SIZE_UNSET));
fLanguagesListView = new BListView();
BScrollView* languagesScrollView = new BScrollView("languagesScroll",
fLanguagesListView, B_WILL_DRAW, false, true);
fKeymapsListView = new BListView();
BScrollView* keymapsScrollView = new BScrollView("keymapsScroll",
fKeymapsListView, B_WILL_DRAW, false, true);
_InitCatalog(false);
_UpdateStrings();
float spacing = be_control_look->DefaultItemSpacing();
SetLayout(new BGroupLayout(B_HORIZONTAL));
AddChild(BGroupLayoutBuilder(B_VERTICAL)
.Add(BGroupLayoutBuilder(B_VERTICAL, spacing)
.Add(infoScrollView)
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
.Add(BGroupLayoutBuilder(B_VERTICAL, spacing)
.Add(fLanguagesLabelView)
.Add(languagesScrollView)
)
.Add(BGroupLayoutBuilder(B_VERTICAL, spacing)
.Add(fKeymapsLabelView)
.Add(keymapsScrollView)
)
)
.SetInsets(spacing, spacing, spacing, spacing)
)
.Add(new BSeparatorView(B_HORIZONTAL))
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
.AddGlue()
.Add(fInstallerButton)
.Add(fDesktopButton)
.SetInsets(spacing, spacing, spacing, spacing)
)
);
CenterOnScreen();
Show();
}
void
BootPromptWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_LANGUAGE_SELECTED:
if (BListItem* item = fLanguagesListView->ItemAt(
fLanguagesListView->CurrentSelection(0))) {
LanguageItem* languageItem = dynamic_cast<LanguageItem*>(item);
BMessage preferredLanguages;
preferredLanguages.AddString("language",
languageItem->Language());
be_locale_roster->SetPreferredLanguages(&preferredLanguages);
_InitCatalog(true);
}
// Calling it here is a cheap way of preventing the user to have
// no item selected. Always the current item will be selected.
_UpdateStrings();
break;
case MSG_KEYMAP_SELECTED:
_StoreKeymap();
break;
default:
BWindow::MessageReceived(message);
}
}
void
BootPromptWindow::_InitCatalog(bool saveSettings)
{
// Initilialize the Locale Kit
// TODO: The below code is a work-around for not being able to
// call GetAppCatalog() more than once.
be_catalog = be_app_catalog = NULL;
// NOTE: be_catalog and be_app_catalog will point fo &fCatalog!
be_locale->GetAppCatalog(&fCatalog);
// Generate a settings file
// TODO: This should not be necessary.
// be_locale_roster->SetPreferredLanguages() should take care of things
if (!saveSettings)
return;
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|| path.Append("Locale settings") != B_OK) {
return;
}
BMessage settings;
BFile file;
if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK)
settings.Unflatten(&file);
BString language;
if (fCatalog.GetLanguage(&language) == B_OK) {
settings.RemoveName("language");
settings.AddString("language", language.String());
}
settings.RemoveName("country");
BCountry country(language.String(), language.ToUpper());
settings.AddString("country", country.Code());
if (file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)
!= B_OK
|| settings.Flatten(&file) != B_OK) {
fprintf(stderr, "Failed to write Local Kit settings!\n");
}
}
void
BootPromptWindow::_UpdateStrings()
{
SetTitle(TR("Welcome to Haiku"));
const char* infoText = TR(
"Welcome to Haiku!\n\n"
"Do you wish to want to run the Installer or continue booting "
"to the Desktop?\n\n"
"Please select your preferred language and keyboard layout from "
"the list below."
);
fInfoTextView->SetText(infoText);
fDesktopButton->SetLabel(TR("Desktop"));
fInstallerButton->SetLabel(TR("Installer"));
fLanguagesLabelView->SetText(TR("Language"));
fKeymapsLabelView->SetText(TR("Keymap"));
_PopulateLanguages();
_PopulateKeymaps();
}
void
BootPromptWindow::_PopulateLanguages()
{
// Disable sending the selection message while we change the selection.
fLanguagesListView->SetSelectionMessage(NULL);
// Clear the list view first
while (BListItem* item = fLanguagesListView->RemoveItem(
fLanguagesListView->CountItems() - 1)) {
delete item;
}
// Get current first preferred language of the user
BMessage preferredLanguages;
be_locale_roster->GetPreferredLanguages(&preferredLanguages);
const char* firstPreferredLanguage;
if (preferredLanguages.FindString("language", &firstPreferredLanguage)
!= B_OK) {
// Fall back to built-in language of this application.
firstPreferredLanguage = "en";
}
// TODO: Use this API instead once it's ready.
// BMessage installedCatalogs;
// be_locale_roster->GetInstalledCatalogs(&installedCatalogs);
// installedCatalogs.PrintToStream();
// TODO: BLocaleRoster uses static variables!! Fix this! Or else one can only
// call this once!
// // Get the list of all known languages
// BMessage installedLanguages;
// be_locale_roster->GetInstalledLanguages(&installedLanguages);
// Try to instantiate a BCatalog for each language, it will only work
// for translations of this application. So the list of languages will be
// limited to catalogs written for this application, which is on purpose!
const char* languageString;
for (int32 i = 0;
fInstalledLanguages.FindString("langs", i, &languageString) == B_OK;
i++) {
BCatalog catalog("x-vnd.Haiku-ReadOnlyBootPrompt", languageString);
if (catalog.InitCheck() == B_OK) {
BLanguage* language;
if (be_locale_roster->GetLanguage(&language,
BString(languageString)) == B_OK) {
BString name;
language->GetName(&name);
LanguageItem* item = new LanguageItem(name.String(),
languageString);
fLanguagesListView->AddItem(item);
// Select this item if it is the first preferred language
if (strcmp(firstPreferredLanguage, languageString) == 0) {
fLanguagesListView->Select(
fLanguagesListView->CountItems() - 1);
}
} else
printf("failed to get BLanguage for %s\n", languageString);
}
}
// Re-enable sending the selection message.
fLanguagesListView->SetSelectionMessage(
new BMessage(MSG_LANGUAGE_SELECTED));
}
void
BootPromptWindow::_PopulateKeymaps()
{
// Disable sending the selection message while we change the selection.
fKeymapsListView->SetSelectionMessage(NULL);
// Clean the list view first
while (BListItem* item = fKeymapsListView->RemoveItem(
fKeymapsListView->CountItems() - 1)) {
delete item;
}
// Get the name of the current keymap, so we can mark the correct entry
// in the list view.
BString currentKeymapName;
entry_ref ref;
if (_GetCurrentKeymapRef(ref) == B_OK) {
BNode node(&ref);
node.ReadAttrString("keymap:name", &currentKeymapName);
}
// TODO: common keymaps!
BPath path;
if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) != B_OK
|| path.Append("Keymaps") != B_OK) {
return;
}
// Populate the list
BDirectory directory;
if (directory.SetTo(path.Path()) == B_OK) {
while (directory.GetNextRef(&ref) == B_OK) {
fKeymapsListView->AddItem(new KeymapListItem(ref));
if (currentKeymapName == ref.name)
fKeymapsListView->Select(fKeymapsListView->CountItems() - 1);
}
}
fKeymapsListView->ScrollToSelection();
// Re-enable sending the selection message.
fKeymapsListView->SetSelectionMessage(
new BMessage(MSG_KEYMAP_SELECTED));
}
void
BootPromptWindow::_StoreKeymap() const
{
KeymapListItem* item = dynamic_cast<KeymapListItem*>(
fKeymapsListView->ItemAt(fKeymapsListView->CurrentSelection(0)));
if (item == NULL)
return;
// Load and use the new keymap
Keymap keymap;
if (keymap.Load(item->EntryRef()) != B_OK) {
fprintf(stderr, "Failed to load new keymap file (%s).\n",
item->EntryRef().name);
return;
}
// Get entry_ref to the Key_map file in the user settings.
entry_ref ref;
if (_GetCurrentKeymapRef(ref) != B_OK) {
fprintf(stderr, "Failed to get ref to user keymap file.\n");
return;
}
if (keymap.Save(ref) != B_OK) {
fprintf(stderr, "Failed to save new keymap file (%s).\n",
item->EntryRef().name);
return;
}
keymap.Use();
}
status_t
BootPromptWindow::_GetCurrentKeymapRef(entry_ref& ref) const
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|| path.Append("Key_map") != B_OK) {
return B_ERROR;
}
return get_ref_for_path(path.Path(), &ref);
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010, Stephan Aßmus <[email protected]>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef BOOT_PROMPT_WINDOW_H
#define BOOT_PROMPT_WINDOW_H
#include <Catalog.h>
#include <Message.h>
#include <Window.h>
class BButton;
class BListView;
class BStringView;
class BTextView;
class BootPromptWindow : public BWindow {
public:
BootPromptWindow();
virtual void MessageReceived(BMessage* message);
private:
void _InitCatalog(bool saveSettings);
void _UpdateStrings();
void _PopulateLanguages();
void _PopulateKeymaps();
void _StoreKeymap() const;
status_t _GetCurrentKeymapRef(entry_ref& ref) const;
private:
BCatalog fCatalog;
BTextView* fInfoTextView;
BStringView* fLanguagesLabelView;
BListView* fLanguagesListView;
BStringView* fKeymapsLabelView;
BListView* fKeymapsListView;
BButton* fDesktopButton;
BButton* fInstallerButton;
// TODO: Should not be needed, see TODO in _PopulateLanguages()
BMessage fInstalledLanguages;
};
#endif // BOOT_PROMPT_WINDOW_H
+24
View File
@@ -0,0 +1,24 @@
SubDir HAIKU_TOP src apps readonlybootprompt ;
UsePrivateHeaders interface shared ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src preferences keymap ] ;
Application ReadOnlyBootPrompt :
BootPrompt.cpp
BootPromptWindow.cpp
Keymap.cpp
KeymapListItem.cpp
: be libshared.a $(TARGET_LIBSTDC++) liblocale.so
: BootPrompt.rdef
;
DoCatalogs ReadOnlyBootPrompt :
x-vnd.Haiku-ReadOnlyBootPrompt
:
BootPrompt.cpp
BootPromptWindow.cpp
: en.catalog
: de.catkeys
;