You can now create new file types and groups.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16393 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-02-14 14:41:57 +00:00
parent 5acbf1f50e
commit 879c65a301
8 changed files with 337 additions and 13 deletions

View File

@ -164,7 +164,7 @@ FileTypes::MessageReceived(BMessage *message)
case kMsgOpenFilePanel:
// the open file panel sends us a message when it's done
fFilePanel->Window()->SetTitle("Open File");
fFilePanel->Window()->SetTitle("FileTypes: Open File");
fFilePanel->SetMessage(new BMessage(B_REFS_RECEIVED));
if (!fFilePanel->IsShowing())
@ -172,7 +172,7 @@ FileTypes::MessageReceived(BMessage *message)
break;
case kMsgOpenSelectPanel:
fFilePanel->Window()->SetTitle("Select Preferred Application");
fFilePanel->Window()->SetTitle("FileTypes: Select Preferred Application");
fFilePanel->SetMessage(new BMessage(kMsgPreferredAppOpened));
if (!fFilePanel->IsShowing())
@ -184,7 +184,7 @@ FileTypes::MessageReceived(BMessage *message)
break;
case kMsgOpenSameAsPanel:
fFilePanel->Window()->SetTitle("Select Same Preferred Application As");
fFilePanel->Window()->SetTitle("FileTypes: Select Same Preferred Application As");
fFilePanel->SetMessage(new BMessage(kMsgSamePreferredAppAsOpened));
if (!fFilePanel->IsShowing())

View File

@ -7,8 +7,8 @@
#include "FileTypes.h"
#include "FileTypesWindow.h"
#include "MimeTypeListView.h"
#include "NewFileTypeWindow.h"
#include <Alert.h>
#include <AppFileInfo.h>
#include <Application.h>
#include <Bitmap.h>
@ -52,7 +52,6 @@ const uint32 kMsgSamePreferredAppAs = 'spaa';
const uint32 kMsgTypeEntered = 'type';
const uint32 kMsgDescriptionEntered = 'dsce';
const struct type_map {
const char* name;
type_code type;
@ -113,7 +112,7 @@ class AttributeItem : public BStringItem {
public:
AttributeItem(const char* name, const char* publicName, type_code type,
int32 alignment, int32 width, bool visible, bool editable);
~AttributeItem();
virtual ~AttributeItem();
virtual void DrawItem(BView* owner, BRect itemRect,
bool drawEverything = false);
@ -128,9 +127,6 @@ class AttributeItem : public BStringItem {
bool fEditable;
};
static void error_alert(const char* message, status_t status = B_OK,
alert_type type = B_WARNING_ALERT);
// #pragma mark -
@ -187,7 +183,7 @@ name_for_type(BString& string, type_code type)
}
static void
void
error_alert(const char* message, status_t status, alert_type type)
{
char warning[512];
@ -501,7 +497,10 @@ AttributeListView::Draw(BRect updateRect)
FileTypesWindow::FileTypesWindow(BRect frame)
: BWindow(frame, "FileTypes", B_TITLED_WINDOW,
B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS)
B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS),
fNewTypeWindow(NULL),
fExtensionWindow(NULL),
fAttributeWindow(NULL)
{
// add the menu
@ -1116,6 +1115,14 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
}
void
FileTypesWindow::PlaceSubWindow(BWindow* window)
{
window->MoveTo(Frame().left + (Frame().Width() - window->Frame().Width()) / 2.0f,
Frame().top + (Frame().Height() - window->Frame().Height()) / 2.0f);
}
void
FileTypesWindow::MessageReceived(BMessage* message)
{
@ -1135,7 +1142,16 @@ FileTypesWindow::MessageReceived(BMessage* message)
}
case kMsgAddType:
puts("add type");
{
if (fNewTypeWindow == NULL) {
fNewTypeWindow = new NewFileTypeWindow(this, fCurrentType.Type());
fNewTypeWindow->Show();
} else
fNewTypeWindow->Activate();
break;
}
case kMsgNewTypeWindowClosed:
fNewTypeWindow = NULL;
break;
case kMsgRemoveType:
@ -1168,6 +1184,14 @@ FileTypesWindow::MessageReceived(BMessage* message)
break;
}
case kMsgSelectNewType:
{
const char* type;
if (message->FindString("type", &type) == B_OK)
fTypeListView->SelectNewType(type);
break;
}
// File Extensions group
case kMsgExtensionSelected:

View File

@ -6,6 +6,7 @@
#define FILE_TYPES_WINDOW_H
#include <Alert.h>
#include <Mime.h>
#include <Window.h>
@ -29,6 +30,8 @@ class FileTypesWindow : public BWindow {
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
void PlaceSubWindow(BWindow* window);
private:
void _UpdateExtensions(BMimeType* type);
void _AdoptPreferredApplication(BMessage* message, bool sameAs);
@ -62,9 +65,19 @@ class FileTypesWindow : public BWindow {
BButton* fAddAttributeButton;
BButton* fRemoveAttributeButton;
BWindow* fNewTypeWindow;
BWindow* fExtensionWindow;
BWindow* fAttributeWindow;
};
static const uint32 kMsgPreferredAppOpened = 'paOp';
static const uint32 kMsgSamePreferredAppAsOpened = 'spaO';
static const uint32 kMsgSelectNewType = 'slnt';
static const uint32 kMsgNewTypeWindowClosed = 'ntwc';
extern void error_alert(const char* message, status_t status = B_OK,
alert_type type = B_WARNING_ALERT);
#endif // FILE_TYPES_WINDOW_H

View File

@ -9,6 +9,7 @@ Preference FileTypes :
FileTypes.cpp
FileTypesWindow.cpp
MimeTypeListView.cpp
NewFileTypeWindow.cpp
: be tracker
: FileTypes.rdef FileTypes.icons.rdef
;

View File

@ -335,6 +335,11 @@ MimeTypeListView::MessageReceived(BMessage* message)
AddItem(item);
UpdateItem(item);
if (!fSelectNewType.ICompare(type)) {
SelectItem(item);
fSelectNewType = "";
}
break;
}
case B_MIME_TYPE_DELETED:
@ -360,6 +365,57 @@ MimeTypeListView::MessageReceived(BMessage* message)
}
/*!
\brief This method makes sure a new MIME type will be selected.
If it's not in the list yet, it will be selected as soon as it's
added.
*/
void
MimeTypeListView::SelectNewType(const char* type)
{
if (SelectType(type))
return;
fSelectNewType = type;
}
bool
MimeTypeListView::SelectType(const char* type)
{
MimeTypeItem* item = FindItem(type);
if (item == NULL)
return false;
SelectItem(item);
return true;
}
void
MimeTypeListView::SelectItem(MimeTypeItem* item)
{
if (item == NULL) {
Select(-1);
return;
}
// Make sure the item is visible
BListItem* superItem = item;
while ((superItem = Superitem(superItem)) != NULL) {
Expand(superItem);
}
// Select it, and make it visible
int32 index = IndexOf(item);
Select(index);
ScrollToSelection();
}
MimeTypeItem*
MimeTypeListView::FindItem(const char* type)
{
@ -370,7 +426,7 @@ MimeTypeListView::FindItem(const char* type)
MimeTypeItem* item = dynamic_cast<MimeTypeItem*>(FullListItemAt(i));
if (item == NULL)
continue;
if (!strcasecmp(item->Type(), type))
return item;
}

View File

@ -49,6 +49,10 @@ class MimeTypeListView : public BOutlineListView {
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP);
virtual ~MimeTypeListView();
void SelectNewType(const char* type);
bool SelectType(const char* type);
void SelectItem(MimeTypeItem* item);
MimeTypeItem* FindItem(const char* type);
void UpdateItem(MimeTypeItem* item);
@ -62,6 +66,8 @@ class MimeTypeListView : public BOutlineListView {
private:
void _CollectTypes();
void _MakeTypesUnique(MimeTypeItem* underItem = NULL);
BString fSelectNewType;
};
bool mimetype_is_application_signature(BMimeType& type);

View File

@ -0,0 +1,192 @@
/*
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "FileTypesWindow.h"
#include "NewFileTypeWindow.h"
#include <Button.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Mime.h>
#include <PopUpMenu.h>
#include <String.h>
#include <TextControl.h>
#include <string.h>
const uint32 kMsgSupertypeChosen = 'sptc';
const uint32 kMsgNewSupertypeChosen = 'nstc';
const uint32 kMsgNameUpdated = 'nmup';
const uint32 kMsgAddType = 'atyp';
NewFileTypeWindow::NewFileTypeWindow(FileTypesWindow* target, const char* currentType)
: BWindow(BRect(100, 100, 350, 200), "New File Type", B_TITLED_WINDOW,
B_NOT_ZOOMABLE | B_NOT_V_RESIZABLE | B_ASYNCHRONOUS_CONTROLS),
fTarget(target)
{
BRect rect = Bounds();
BView* topView = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
AddChild(topView);
rect.InsetBy(8.0f, 8.0f);
fNameControl = new BTextControl(rect, "internal", "Internal Name:", "",
NULL, B_FOLLOW_LEFT_RIGHT);
float labelWidth = fNameControl->StringWidth(fNameControl->Label()) + 2.0f;
fNameControl->SetModificationMessage(new BMessage(kMsgNameUpdated));
fNameControl->SetDivider(labelWidth);
fNameControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
// filter out invalid characters that can't be part of a MIME type name
BTextView* textView = fNameControl->TextView();
const char* disallowedCharacters = "/<>@,;:\"()[]?=";
for (int32 i = 0; disallowedCharacters[i]; i++) {
textView->DisallowChar(disallowedCharacters[i]);
}
float width, height;
fNameControl->GetPreferredSize(&width, &height);
fNameControl->ResizeTo(rect.Width(), height);
fNameControl->MoveTo(8.0f, 12.0f + fNameControl->Bounds().Height());
topView->AddChild(fNameControl);
fSupertypesMenu = new BPopUpMenu("supertypes");
BMenuItem* item;
BMessage types;
if (BMimeType::GetInstalledSupertypes(&types) == B_OK) {
const char* type;
int32 i = 0;
while (types.FindString("super_types", i++, &type) == B_OK) {
fSupertypesMenu->AddItem(item = new BMenuItem(type,
new BMessage(kMsgSupertypeChosen)));
// select super type close to the current type
if (currentType != NULL) {
if (!strncmp(type, currentType, strlen(type)))
item->SetMarked(true);
} else if (i == 1)
item->SetMarked(true);
}
if (i > 1)
fSupertypesMenu->AddSeparatorItem();
}
fSupertypesMenu->AddItem(new BMenuItem("Add New Group",
new BMessage(kMsgNewSupertypeChosen)));
rect.bottom = rect.top + fNameControl->Bounds().Height() + 2.0f;
BMenuField* menuField = new BMenuField(rect, "supertypes",
"Group:", fSupertypesMenu);
menuField->SetDivider(labelWidth);
menuField->SetAlignment(B_ALIGN_RIGHT);
menuField->GetPreferredSize(&width, &height);
menuField->ResizeTo(rect.Width(), height);
topView->AddChild(menuField);
fAddButton = new BButton(rect, "add", "Add Type", new BMessage(kMsgAddType),
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
fAddButton->ResizeToPreferred();
fAddButton->MoveTo(Bounds().Width() - 8.0f - fAddButton->Bounds().Width(),
Bounds().Height() - 8.0f - fAddButton->Bounds().Height());
fAddButton->SetEnabled(false);
topView->AddChild(fAddButton);
BButton* button = new BButton(rect, "cancel", "Cancel",
new BMessage(B_QUIT_REQUESTED), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
button->ResizeToPreferred();
button->MoveTo(fAddButton->Frame().left - 10.0f - button->Bounds().Width(),
fAddButton->Frame().top);
topView->AddChild(button);
ResizeTo(labelWidth * 4.0f + 24.0f, fNameControl->Bounds().Height() * 3.0f + 34.0f);
SetSizeLimits(button->Bounds().Width() + fAddButton->Bounds().Width() + 26.0f,
32767.0f, Frame().Height(), Frame().Height());
fAddButton->MakeDefault(true);
fNameControl->MakeFocus(true);
target->PlaceSubWindow(this);
}
NewFileTypeWindow::~NewFileTypeWindow()
{
}
#include <stdio.h>
void
NewFileTypeWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgSupertypeChosen:
fAddButton->SetLabel("Add Type");
fNameControl->SetLabel("Internal Name:");
fNameControl->MakeFocus(true);
break;
case kMsgNewSupertypeChosen:
fAddButton->SetLabel("Add Group");
fNameControl->SetLabel("Group Name:");
fNameControl->MakeFocus(true);
break;
case kMsgNameUpdated:
{
bool empty = fNameControl->Text() == NULL
|| fNameControl->Text()[0] == '\0';
if (fAddButton->IsEnabled() == empty)
fAddButton->SetEnabled(!empty);
break;
}
case kMsgAddType:
{
BMenuItem* item = fSupertypesMenu->FindMarked();
if (item != NULL) {
BString type;
if (fSupertypesMenu->IndexOf(item) != fSupertypesMenu->CountItems() - 1) {
// add normal type
type = item->Label();
type.Append("/");
}
type.Append(fNameControl->Text());
BMimeType mimeType(type.String());
if (mimeType.IsInstalled()) {
error_alert("This file type already exists.");
break;
}
status_t status = mimeType.Install();
if (status != B_OK)
error_alert("Could not install file type", status);
else {
BMessage update(kMsgSelectNewType);
update.AddString("type", type.String());
fTarget.SendMessage(&update);
}
}
PostMessage(B_QUIT_REQUESTED);
break;
}
}
}
bool
NewFileTypeWindow::QuitRequested()
{
fTarget.SendMessage(kMsgNewTypeWindowClosed);
return true;
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef NEW_FILE_TYPE_WINDOW_H
#define NEW_FILE_TYPE_WINDOW_H
#include <Messenger.h>
#include <Window.h>
class BButton;
class BMenu;
class BTextControl;
class NewFileTypeWindow : public BWindow {
public:
NewFileTypeWindow(FileTypesWindow* target, const char* currentType);
virtual ~NewFileTypeWindow();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
private:
BMessenger fTarget;
BMenu* fSupertypesMenu;
BTextControl* fNameControl;
BButton* fAddButton;
};
#endif // NEW_FILE_TYPE_WINDOW_H