* Copyright 2006-2010, Axel DΓΆrfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "ExtensionWindow.h"
#include "FileTypes.h"
#include "FileTypesWindow.h"
#include <Button.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <LayoutBuilder.h>
#include <Locale.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Mime.h>
#include <PopUpMenu.h>
#include <String.h>
#include <TextControl.h>
#include <strings.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Extension Window"
const uint32 kMsgExtensionUpdated = 'exup';
const uint32 kMsgAccept = 'acpt';
static int
compare_extensions(const void* _a, const void* _b)
{
const char* a = *(const char **)_a;
const char* b = *(const char **)_b;
int compare = strcasecmp(a, b);
if (compare != 0)
return compare;
return -strcmp(a, b);
}
status_t
merge_extensions(BMimeType& type, const BList& newExtensionsList,
const char* removeExtension)
{
BMessage extensions;
status_t status = type.GetFileExtensions(&extensions);
if (status < B_OK)
return status;
BList mergedList;
mergedList.AddList(&newExtensionsList);
int32 originalCount = mergedList.CountItems();
const char* extension;
for (int32 i = 0; extensions.FindString("extensions", i,
&extension) == B_OK; i++) {
for (int32 j = originalCount; j-- > 0;) {
if (!strcmp((const char*)mergedList.ItemAt(j), extension)) {
mergedList.RemoveItem(j);
originalCount--;
}
}
if (removeExtension == NULL || strcmp(removeExtension, extension))
mergedList.AddItem((void *)extension);
}
mergedList.SortItems(compare_extensions);
BMessage newExtensions;
for (int32 i = 0; i < mergedList.CountItems(); i++) {
newExtensions.AddString("extensions",
(const char*)mergedList.ItemAt(i));
}
return type.SetFileExtensions(&newExtensions);
}
status_t
replace_extension(BMimeType& type, const char* newExtension,
const char* oldExtension)
{
BList list;
list.AddItem((void *)newExtension);
return merge_extensions(type, list, oldExtension);
}
ExtensionWindow::ExtensionWindow(FileTypesWindow* target, BMimeType& type,
const char* extension)
: BWindow(BRect(100, 100, 350, 200), B_TRANSLATE("Extension"),
B_MODAL_WINDOW_LOOK, B_MODAL_SUBSET_WINDOW_FEEL,
B_NOT_ZOOMABLE | B_NOT_RESIZABLE
| B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
fTarget(target),
fMimeType(type.Type()),
fExtension(extension)
{
fExtensionControl = new BTextControl(B_TRANSLATE("Extension:"),
extension, NULL);
fExtensionControl->SetModificationMessage(
new BMessage(kMsgExtensionUpdated));
fExtensionControl->SetAlignment(B_ALIGN_LEFT, B_ALIGN_LEFT);
BTextView* textView = fExtensionControl->TextView();
const char* disallowedCharacters = "/:";
for (int32 i = 0; disallowedCharacters[i]; i++) {
textView->DisallowChar(disallowedCharacters[i]);
}
fAcceptButton = new BButton(extension
? B_TRANSLATE("Done") : B_TRANSLATE("Add"),
new BMessage(kMsgAccept));
fAcceptButton->SetEnabled(false);
BButton* cancelButton = new BButton(B_TRANSLATE("Cancel"),
new BMessage(B_QUIT_REQUESTED));
float padding = be_control_look->DefaultItemSpacing();
BLayoutBuilder::Grid<>(this, padding, padding)
.SetInsets(padding, padding, padding, padding)
.AddTextControl(fExtensionControl, 0, 0, B_ALIGN_HORIZONTAL_UNSET, 1, 2)
.Add(BSpaceLayoutItem::CreateGlue(), 0, 1)
.Add(cancelButton, 1, 1)
.Add(fAcceptButton, 2, 1);
if (fExtension.ByteAt(0) == '.')
fExtension.Remove(0, 1);
fAcceptButton->MakeDefault(true);
fExtensionControl->MakeFocus(true);
target->PlaceSubWindow(this);
AddToSubset(target);
}
ExtensionWindow::~ExtensionWindow()
{
}
void
ExtensionWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgExtensionUpdated:
{
bool enabled = fExtensionControl->Text() != NULL
&& fExtensionControl->Text()[0] != '\0';
if (enabled) {
enabled = strcmp(fExtensionControl->Text(), fExtension.String());
}
if (fAcceptButton->IsEnabled() != enabled)
fAcceptButton->SetEnabled(enabled);
break;
}
case kMsgAccept:
{
const char* newExtension = fExtensionControl->Text();
if (newExtension[0] == '.')
newExtension++;
status_t status = replace_extension(fMimeType, newExtension,
fExtension.String());
if (status != B_OK)
error_alert(B_TRANSLATE("Could not change file extensions"),
status);
PostMessage(B_QUIT_REQUESTED);
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}