libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / preferences / filetypes / FileTypeWindow.cpp
blobc91317c5961892f54d487eb91340f520b4d576a6
1 /*
2 * Copyright 2006-2010, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "FileTypes.h"
8 #include "FileTypeWindow.h"
9 #include "IconView.h"
10 #include "PreferredAppMenu.h"
11 #include "TypeListWindow.h"
13 #include <Application.h>
14 #include <Bitmap.h>
15 #include <Box.h>
16 #include <Button.h>
17 #include <Catalog.h>
18 #include <ControlLook.h>
19 #include <File.h>
20 #include <LayoutBuilder.h>
21 #include <Locale.h>
22 #include <MenuField.h>
23 #include <MenuItem.h>
24 #include <Mime.h>
25 #include <NodeInfo.h>
26 #include <PopUpMenu.h>
27 #include <SpaceLayoutItem.h>
28 #include <TextControl.h>
30 #include <stdio.h>
33 #undef B_TRANSLATION_CONTEXT
34 #define B_TRANSLATION_CONTEXT "FileType Window"
37 const uint32 kMsgTypeEntered = 'type';
38 const uint32 kMsgSelectType = 'sltp';
39 const uint32 kMsgTypeSelected = 'tpsd';
40 const uint32 kMsgSameTypeAs = 'stpa';
41 const uint32 kMsgSameTypeAsOpened = 'stpO';
43 const uint32 kMsgPreferredAppChosen = 'papc';
44 const uint32 kMsgSelectPreferredApp = 'slpa';
45 const uint32 kMsgSamePreferredAppAs = 'spaa';
46 const uint32 kMsgPreferredAppOpened = 'paOp';
47 const uint32 kMsgSamePreferredAppAsOpened = 'spaO';
50 FileTypeWindow::FileTypeWindow(BPoint position, const BMessage& refs)
52 BWindow(BRect(0.0f, 0.0f, 300.0f, 200.0f).OffsetBySelf(position),
53 B_TRANSLATE("File type"), B_TITLED_WINDOW,
54 B_NOT_V_RESIZABLE | B_NOT_ZOOMABLE
55 | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS)
57 float padding = be_control_look->DefaultItemSpacing();
59 // "File Type" group
60 BBox* fileTypeBox = new BBox("file type BBox");
61 fileTypeBox->SetLabel(B_TRANSLATE("File type"));
63 fTypeControl = new BTextControl("type", NULL, "Type Control",
64 new BMessage(kMsgTypeEntered));
66 // filter out invalid characters that can't be part of a MIME type name
67 BTextView* textView = fTypeControl->TextView();
68 const char* disallowedCharacters = "<>@,;:\"()[]?=";
69 for (int32 i = 0; disallowedCharacters[i]; i++) {
70 textView->DisallowChar(disallowedCharacters[i]);
73 fSelectTypeButton = new BButton("select type",
74 B_TRANSLATE("Select" B_UTF8_ELLIPSIS), new BMessage(kMsgSelectType));
76 fSameTypeAsButton = new BButton("same type as",
77 B_TRANSLATE_COMMENT("Same as" B_UTF8_ELLIPSIS,
78 "The same TYPE as ..."), new BMessage(kMsgSameTypeAs));
80 BLayoutBuilder::Grid<>(fileTypeBox, padding, padding / 2)
81 .SetInsets(padding, padding * 2, padding, padding)
82 .Add(fTypeControl, 0, 0, 3, 1)
83 .Add(fSelectTypeButton, 0, 1)
84 .Add(fSameTypeAsButton, 1, 1);
86 // "Icon" group
88 BBox* iconBox = new BBox("icon BBox");
89 iconBox->SetLabel(B_TRANSLATE("Icon"));
90 fIconView = new IconView("icon");
91 BLayoutBuilder::Group<>(iconBox, B_HORIZONTAL)
92 .SetInsets(padding, padding * 2, padding, padding)
93 .Add(fIconView);
95 // "Preferred Application" group
97 BBox* preferredBox = new BBox("preferred BBox");
98 preferredBox->SetLabel(B_TRANSLATE("Preferred application"));
100 BMenu* menu = new BPopUpMenu("preferred");
101 BMenuItem* item;
102 menu->AddItem(item = new BMenuItem(B_TRANSLATE("Default application"),
103 new BMessage(kMsgPreferredAppChosen)));
104 item->SetMarked(true);
106 fPreferredField = new BMenuField("preferred", NULL, menu);
108 fSelectAppButton = new BButton("select app",
109 B_TRANSLATE("Select" B_UTF8_ELLIPSIS),
110 new BMessage(kMsgSelectPreferredApp));
112 fSameAppAsButton = new BButton("same app as",
113 B_TRANSLATE_COMMENT("Same as" B_UTF8_ELLIPSIS,
114 "The same APPLICATION as ..."),
115 new BMessage(kMsgSamePreferredAppAs));
117 BLayoutBuilder::Grid<>(preferredBox, padding, padding / 2)
118 .SetInsets(padding, padding * 2, padding, padding)
119 .Add(fPreferredField, 0, 0, 2, 1)
120 .Add(fSelectAppButton, 0, 1)
121 .Add(fSameAppAsButton, 1, 1);
123 BLayoutBuilder::Grid<>(this)
124 .SetInsets(padding)
125 .Add(fileTypeBox, 0, 0, 2, 1)
126 .Add(preferredBox, 0, 1, 1, 1)
127 .Add(iconBox, 1, 1, 1, 1);
129 fTypeControl->MakeFocus(true);
130 BMimeType::StartWatching(this);
131 _SetTo(refs);
135 FileTypeWindow::~FileTypeWindow()
137 BMimeType::StopWatching(this);
141 BString
142 FileTypeWindow::_Title(const BMessage& refs)
144 BString title;
146 entry_ref ref;
147 if (refs.FindRef("refs", 1, &ref) == B_OK) {
148 bool same = false;
149 BEntry entry, parent;
150 if (entry.SetTo(&ref) == B_OK
151 && entry.GetParent(&parent) == B_OK) {
152 same = true;
154 // Check if all entries have the same parent directory
155 for (int32 i = 0; refs.FindRef("refs", i, &ref) == B_OK; i++) {
156 BEntry directory;
157 if (entry.SetTo(&ref) == B_OK
158 && entry.GetParent(&directory) == B_OK) {
159 if (directory != parent) {
160 same = false;
161 break;
167 char name[B_FILE_NAME_LENGTH];
168 if (same && parent.GetName(name) == B_OK) {
169 char buffer[512];
170 snprintf(buffer, sizeof(buffer),
171 B_TRANSLATE("Multiple files from \"%s\" file type"), name);
172 title = buffer;
173 } else
174 title = B_TRANSLATE("[Multiple files] file types");
175 } else if (refs.FindRef("refs", 0, &ref) == B_OK) {
176 char buffer[512];
177 snprintf(buffer, sizeof(buffer), B_TRANSLATE("%s file type"), ref.name);
178 title = buffer;
181 return title;
185 void
186 FileTypeWindow::_SetTo(const BMessage& refs)
188 SetTitle(_Title(refs).String());
190 // get common info and icons
192 fCommonPreferredApp = "";
193 fCommonType = "";
194 entry_ref ref;
195 for (int32 i = 0; refs.FindRef("refs", i, &ref) == B_OK; i++) {
196 BNode node(&ref);
197 if (node.InitCheck() != B_OK)
198 continue;
200 BNodeInfo info(&node);
201 if (info.InitCheck() != B_OK)
202 continue;
204 // TODO: watch entries?
206 entry_ref* copiedRef = new entry_ref(ref);
207 fEntries.AddItem(copiedRef);
209 char type[B_MIME_TYPE_LENGTH];
210 if (info.GetType(type) != B_OK)
211 type[0] = '\0';
213 if (i > 0) {
214 if (fCommonType != type)
215 fCommonType = "";
216 } else
217 fCommonType = type;
219 char preferredApp[B_MIME_TYPE_LENGTH];
220 if (info.GetPreferredApp(preferredApp) != B_OK)
221 preferredApp[0] = '\0';
223 if (i > 0) {
224 if (fCommonPreferredApp != preferredApp)
225 fCommonPreferredApp = "";
226 } else
227 fCommonPreferredApp = preferredApp;
229 if (i == 0)
230 fIconView->SetTo(ref);
233 fTypeControl->SetText(fCommonType.String());
234 _UpdatePreferredApps();
236 fIconView->ShowIconHeap(fEntries.CountItems() != 1);
240 void
241 FileTypeWindow::_AdoptType(BMessage* message)
243 entry_ref ref;
244 if (message == NULL || message->FindRef("refs", &ref) != B_OK)
245 return;
247 BNode node(&ref);
248 status_t status = node.InitCheck();
250 char type[B_MIME_TYPE_LENGTH];
252 if (status == B_OK) {
253 // get type from file
254 BNodeInfo nodeInfo(&node);
255 status = nodeInfo.InitCheck();
256 if (status == B_OK) {
257 if (nodeInfo.GetType(type) != B_OK)
258 type[0] = '\0';
262 if (status != B_OK) {
263 error_alert(B_TRANSLATE("Could not open file"), status);
264 return;
267 fCommonType = type;
268 fTypeControl->SetText(type);
269 _AdoptType();
273 void
274 FileTypeWindow::_AdoptType()
276 for (int32 i = 0; i < fEntries.CountItems(); i++) {
277 BNode node(fEntries.ItemAt(i));
278 BNodeInfo info(&node);
279 if (node.InitCheck() != B_OK
280 || info.InitCheck() != B_OK)
281 continue;
283 info.SetType(fCommonType.String());
288 void
289 FileTypeWindow::_AdoptPreferredApp(BMessage* message, bool sameAs)
291 if (retrieve_preferred_app(message, sameAs, fCommonType.String(),
292 fCommonPreferredApp) == B_OK) {
293 _AdoptPreferredApp();
294 _UpdatePreferredApps();
299 void
300 FileTypeWindow::_AdoptPreferredApp()
302 for (int32 i = 0; i < fEntries.CountItems(); i++) {
303 BNode node(fEntries.ItemAt(i));
304 if (fCommonPreferredApp.Length() == 0) {
305 node.RemoveAttr("BEOS:PREF_APP");
306 continue;
309 BNodeInfo info(&node);
310 if (node.InitCheck() != B_OK
311 || info.InitCheck() != B_OK)
312 continue;
314 info.SetPreferredApp(fCommonPreferredApp.String());
319 void
320 FileTypeWindow::_UpdatePreferredApps()
322 BMimeType type(fCommonType.String());
323 update_preferred_app_menu(fPreferredField->Menu(), &type,
324 kMsgPreferredAppChosen, fCommonPreferredApp.String());
328 void
329 FileTypeWindow::MessageReceived(BMessage* message)
331 switch (message->what) {
332 // File Type group
334 case kMsgTypeEntered:
335 fCommonType = fTypeControl->Text();
336 _AdoptType();
337 break;
339 case kMsgSelectType:
341 BWindow* window = new TypeListWindow(fCommonType.String(),
342 kMsgTypeSelected, this);
343 window->Show();
344 break;
346 case kMsgTypeSelected:
348 const char* type;
349 if (message->FindString("type", &type) == B_OK) {
350 fCommonType = type;
351 fTypeControl->SetText(type);
352 _AdoptType();
354 break;
357 case kMsgSameTypeAs:
359 BMessage panel(kMsgOpenFilePanel);
360 panel.AddString("title", B_TRANSLATE("Select same type as"));
361 panel.AddInt32("message", kMsgSameTypeAsOpened);
362 panel.AddMessenger("target", this);
363 panel.AddBool("allowDirs", true);
365 be_app_messenger.SendMessage(&panel);
366 break;
368 case kMsgSameTypeAsOpened:
369 _AdoptType(message);
370 break;
372 // Preferred Application group
374 case kMsgPreferredAppChosen:
376 const char* signature;
377 if (message->FindString("signature", &signature) == B_OK)
378 fCommonPreferredApp = signature;
379 else
380 fCommonPreferredApp = "";
382 _AdoptPreferredApp();
383 break;
386 case kMsgSelectPreferredApp:
388 BMessage panel(kMsgOpenFilePanel);
389 panel.AddString("title",
390 B_TRANSLATE("Select preferred application"));
391 panel.AddInt32("message", kMsgPreferredAppOpened);
392 panel.AddMessenger("target", this);
394 be_app_messenger.SendMessage(&panel);
395 break;
397 case kMsgPreferredAppOpened:
398 _AdoptPreferredApp(message, false);
399 break;
401 case kMsgSamePreferredAppAs:
403 BMessage panel(kMsgOpenFilePanel);
404 panel.AddString("title",
405 B_TRANSLATE("Select same preferred application as"));
406 panel.AddInt32("message", kMsgSamePreferredAppAsOpened);
407 panel.AddMessenger("target", this);
408 panel.AddBool("allowDirs", true);
410 be_app_messenger.SendMessage(&panel);
411 break;
413 case kMsgSamePreferredAppAsOpened:
414 _AdoptPreferredApp(message, true);
415 break;
417 // Other
419 case B_SIMPLE_DATA:
421 entry_ref ref;
422 if (message->FindRef("refs", &ref) != B_OK)
423 break;
425 BFile file(&ref, B_READ_ONLY);
426 if (is_application(file))
427 _AdoptPreferredApp(message, false);
428 else
429 _AdoptType(message);
430 break;
433 case B_META_MIME_CHANGED:
434 const char* type;
435 int32 which;
436 if (message->FindString("be:type", &type) != B_OK
437 || message->FindInt32("be:which", &which) != B_OK)
438 break;
440 if (which == B_MIME_TYPE_DELETED
441 || which == B_SUPPORTED_TYPES_CHANGED) {
442 _UpdatePreferredApps();
444 break;
446 default:
447 BWindow::MessageReceived(message);
452 bool
453 FileTypeWindow::QuitRequested()
455 be_app->PostMessage(kMsgTypeWindowClosed);
456 return true;