2005-05-23 04:58:42 +04:00
|
|
|
/*
|
|
|
|
Open Tracker License
|
|
|
|
|
|
|
|
Terms and Conditions
|
|
|
|
|
|
|
|
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
|
|
the Software without restriction, including without limitation the rights to
|
|
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
|
|
of the Software, and to permit persons to whom the Software is furnished to do
|
|
|
|
so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice applies to all licensees
|
|
|
|
and shall be included in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
|
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name of Be Incorporated shall not be
|
|
|
|
used in advertising or otherwise to promote the sale, use or other dealings in
|
|
|
|
this Software without prior written authorization from Be Incorporated.
|
|
|
|
|
|
|
|
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
|
|
|
|
of Be Incorporated in the United States and other countries. Other brand product
|
|
|
|
names are registered trademarks or trademarks of their respective holders.
|
|
|
|
All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
#include "Attributes.h"
|
|
|
|
#include "AutoLock.h"
|
|
|
|
#include "Commands.h"
|
|
|
|
#include "FSUtils.h"
|
|
|
|
#include "IconMenuItem.h"
|
|
|
|
#include "OpenWithWindow.h"
|
|
|
|
#include "MimeTypes.h"
|
|
|
|
#include "StopWatch.h"
|
|
|
|
#include "Tracker.h"
|
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
#include <Alert.h>
|
|
|
|
#include <Button.h>
|
2010-07-13 16:39:53 +04:00
|
|
|
#include <Catalog.h>
|
|
|
|
#include <Locale.h>
|
2005-05-23 04:58:42 +04:00
|
|
|
#include <Mime.h>
|
|
|
|
#include <NodeInfo.h>
|
|
|
|
#include <Path.h>
|
|
|
|
#include <Roster.h>
|
|
|
|
#include <Volume.h>
|
|
|
|
#include <VolumeRoster.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2010-07-13 16:39:53 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
const char *kDefaultOpenWithTemplate = "OpenWithSettings";
|
|
|
|
|
|
|
|
// ToDo:
|
|
|
|
// filter out trash
|
|
|
|
// allow column configuring
|
|
|
|
// make SaveState/RestoreState save the current window setting for
|
|
|
|
// other windows
|
|
|
|
|
|
|
|
const float kMaxMenuWidth = 150;
|
|
|
|
|
2006-06-11 14:19:44 +04:00
|
|
|
const int32 kDocumentKnobWidth = 16;
|
2005-05-23 04:58:42 +04:00
|
|
|
const int32 kOpenAndMakeDefault = 'OpDf';
|
|
|
|
const rgb_color kOpenWithDefaultColor = { 0xFF, 0xFF, 0xCC, 255};
|
|
|
|
|
|
|
|
|
2012-04-16 23:31:22 +04:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "OpenWithWindow"
|
2010-07-13 16:39:53 +04:00
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
OpenWithContainerWindow::OpenWithContainerWindow(BMessage *entriesToOpen,
|
|
|
|
LockingList<BWindow> *windowList, window_look look, window_feel feel,
|
|
|
|
uint32 flags, uint32 workspace)
|
|
|
|
: BContainerWindow(windowList, 0, look, feel, flags, workspace),
|
|
|
|
fEntriesToOpen(entriesToOpen)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
AutoLock<BWindow> lock(this);
|
|
|
|
|
2012-05-21 17:10:47 +04:00
|
|
|
BRect windowRect(85, 50, 718, 296);
|
2005-05-23 04:58:42 +04:00
|
|
|
MoveTo(windowRect.LeftTop());
|
|
|
|
ResizeTo(windowRect.Width(), windowRect.Height());
|
|
|
|
|
|
|
|
// add a background view; use the standard BackgroundView here, the same
|
|
|
|
// as the file panel is using
|
|
|
|
BRect rect(Bounds());
|
|
|
|
BackgroundView *backgroundView = new BackgroundView(rect);
|
|
|
|
AddChild(backgroundView);
|
|
|
|
|
|
|
|
rect = Bounds();
|
|
|
|
|
|
|
|
// add buttons
|
2006-06-11 14:19:44 +04:00
|
|
|
|
2010-07-13 16:39:53 +04:00
|
|
|
fLaunchButton = new BButton(rect, "ok", B_TRANSLATE("Open"),
|
2005-05-23 04:58:42 +04:00
|
|
|
new BMessage(kDefaultButton), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
2006-06-11 14:19:44 +04:00
|
|
|
fLaunchButton->ResizeToPreferred();
|
|
|
|
fLaunchButton->MoveTo(rect.right - 10 - kDocumentKnobWidth
|
|
|
|
- fLaunchButton->Bounds().Width(),
|
|
|
|
rect.bottom - 10 - fLaunchButton->Bounds().Height());
|
2005-05-23 04:58:42 +04:00
|
|
|
backgroundView->AddChild(fLaunchButton);
|
|
|
|
|
2006-06-11 14:19:44 +04:00
|
|
|
BRect buttonRect = fLaunchButton->Frame();
|
2005-05-23 04:58:42 +04:00
|
|
|
fLaunchAndMakeDefaultButton = new BButton(buttonRect, "make default",
|
2010-07-13 16:39:53 +04:00
|
|
|
B_TRANSLATE("Open and make preferred"), new BMessage(kOpenAndMakeDefault),
|
2005-05-23 04:58:42 +04:00
|
|
|
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
|
|
|
// wide button, have to resize to fit text
|
|
|
|
fLaunchAndMakeDefaultButton->ResizeToPreferred();
|
|
|
|
fLaunchAndMakeDefaultButton->MoveBy(
|
2006-06-11 14:19:44 +04:00
|
|
|
- 10 - fLaunchAndMakeDefaultButton->Bounds().Width(), 0);
|
2005-05-23 04:58:42 +04:00
|
|
|
backgroundView->AddChild(fLaunchAndMakeDefaultButton);
|
|
|
|
fLaunchAndMakeDefaultButton->SetEnabled(false);
|
2006-06-11 14:19:44 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
buttonRect = fLaunchAndMakeDefaultButton->Frame();
|
2010-07-13 16:39:53 +04:00
|
|
|
BButton *button = new BButton(buttonRect, "cancel", B_TRANSLATE("Cancel"),
|
2006-06-11 14:19:44 +04:00
|
|
|
new BMessage(kCancelButton), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
|
|
|
button->ResizeToPreferred();
|
|
|
|
button->MoveBy(- 10 - button->Bounds().Width(), 0);
|
|
|
|
backgroundView->AddChild(button);
|
|
|
|
|
|
|
|
fMinimalWidth = button->Bounds().Width() + fLaunchButton->Bounds().Width()
|
|
|
|
+ fLaunchAndMakeDefaultButton->Bounds().Width() + kDocumentKnobWidth + 40;
|
|
|
|
|
|
|
|
fLaunchButton->MakeDefault(true);
|
|
|
|
|
|
|
|
// add pose view
|
|
|
|
|
|
|
|
rect.OffsetTo(10, 10);
|
|
|
|
rect.bottom = buttonRect.top - 15;
|
|
|
|
|
|
|
|
rect.right -= B_V_SCROLL_BAR_WIDTH + 20;
|
|
|
|
rect.bottom -= B_H_SCROLL_BAR_HEIGHT;
|
|
|
|
// make room for scrollbars and a margin
|
|
|
|
fPoseView = NewPoseView(0, rect, kListMode);
|
|
|
|
backgroundView->AddChild(fPoseView);
|
|
|
|
|
|
|
|
fPoseView->SetFlags(fPoseView->Flags() | B_NAVIGABLE);
|
|
|
|
fPoseView->SetPoseEditing(false);
|
2005-05-23 04:58:42 +04:00
|
|
|
|
|
|
|
// set the window title
|
|
|
|
if (CountRefs(fEntriesToOpen) == 1) {
|
|
|
|
// if opening just one file, use it in the title
|
|
|
|
entry_ref ref;
|
|
|
|
fEntriesToOpen->FindRef("refs", &ref);
|
2010-09-16 18:30:20 +04:00
|
|
|
BString buffer(B_TRANSLATE("Open %name with:"));
|
|
|
|
buffer.ReplaceFirst("%name", ref.name);
|
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
SetTitle(buffer.String());
|
|
|
|
} else
|
|
|
|
// use generic title
|
2010-07-13 16:39:53 +04:00
|
|
|
SetTitle(B_TRANSLATE("Open selection with:"));
|
2005-05-23 04:58:42 +04:00
|
|
|
|
|
|
|
AddCommonFilter(new BMessageFilter(B_KEY_DOWN, &OpenWithContainerWindow::KeyDownFilter));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
OpenWithContainerWindow::~OpenWithContainerWindow()
|
|
|
|
{
|
|
|
|
delete fEntriesToOpen;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BPoseView *
|
|
|
|
OpenWithContainerWindow::NewPoseView(Model *, BRect rect, uint32)
|
|
|
|
{
|
|
|
|
return new OpenWithPoseView(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
OpenWithPoseView *
|
|
|
|
OpenWithContainerWindow::PoseView() const
|
|
|
|
{
|
|
|
|
ASSERT(dynamic_cast<OpenWithPoseView *>(fPoseView));
|
|
|
|
return static_cast<OpenWithPoseView *>(fPoseView);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const BMessage *
|
|
|
|
OpenWithContainerWindow::EntryList() const
|
|
|
|
{
|
|
|
|
return fEntriesToOpen;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithContainerWindow::OpenWithSelection()
|
|
|
|
{
|
|
|
|
int32 count = PoseView()->SelectionList()->CountItems();
|
|
|
|
ASSERT(count == 1);
|
|
|
|
if (!count)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PoseView()->OpenSelection(PoseView()->SelectionList()->FirstItem(), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const BString *
|
|
|
|
FindOne(const BString *element, void *castToString)
|
|
|
|
{
|
|
|
|
if (strcasecmp(element->String(), (const char *)castToString) == 0)
|
|
|
|
return element;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const entry_ref *
|
|
|
|
AddOneUniqueDocumentType(const entry_ref *ref, void *castToList)
|
|
|
|
{
|
|
|
|
BObjectList<BString> *list = (BObjectList<BString> *)castToList;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
BEntry entry(ref, true);
|
|
|
|
// traverse symlinks
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
// get this documents type
|
|
|
|
char type[B_MIME_TYPE_LENGTH];
|
|
|
|
BFile file(&entry, O_RDONLY);
|
|
|
|
if (file.InitCheck() != B_OK)
|
|
|
|
return 0;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
BNodeInfo info(&file);
|
|
|
|
if (info.GetType(type) != B_OK)
|
|
|
|
return 0;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
if (list->EachElement(FindOne, &type))
|
|
|
|
// type already in list, bail
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// add type to list
|
|
|
|
list->AddItem(new BString(type));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const BString *
|
|
|
|
SetDefaultAppForOneType(const BString *element, void *castToEntryRef)
|
|
|
|
{
|
|
|
|
const entry_ref *appRef = (const entry_ref *)castToEntryRef;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
// set entry as default handler for one mime string
|
|
|
|
BMimeType mime(element->String());
|
|
|
|
if (!mime.IsInstalled())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// first set it's app signature as the preferred type
|
|
|
|
BFile appFile(appRef, O_RDONLY);
|
|
|
|
if (appFile.InitCheck() != B_OK)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
char appSignature[B_MIME_TYPE_LENGTH];
|
|
|
|
if (GetAppSignatureFromAttr(&appFile, appSignature) != B_OK)
|
|
|
|
return 0;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
if (mime.SetPreferredApp(appSignature) != B_OK)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// set the app hint on the metamime for this signature
|
|
|
|
mime.SetTo(appSignature);
|
|
|
|
#if xDEBUG
|
|
|
|
status_t result =
|
|
|
|
#endif
|
|
|
|
mime.SetAppHint(appRef);
|
|
|
|
|
|
|
|
#if xDEBUG
|
|
|
|
BEntry debugEntry(appRef);
|
|
|
|
BPath debugPath;
|
|
|
|
debugEntry.GetPath(&debugPath);
|
|
|
|
|
|
|
|
PRINT(("setting %s, sig %s as default app for %s, result %s\n",
|
|
|
|
debugPath.Path(), appSignature, element->String(), strerror(result)));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithContainerWindow::MakeDefaultAndOpen()
|
|
|
|
{
|
|
|
|
int32 count = PoseView()->SelectionList()->CountItems();
|
|
|
|
ASSERT(count == 1);
|
|
|
|
if (!count)
|
|
|
|
return;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
BPose *selectedAppPose = PoseView()->SelectionList()->FirstItem();
|
|
|
|
ASSERT(selectedAppPose);
|
|
|
|
if (!selectedAppPose)
|
|
|
|
return;
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
// collect all the types of all the opened documents into a list
|
2005-05-23 04:58:42 +04:00
|
|
|
BObjectList<BString> openedFileTypes(10, true);
|
2008-10-05 00:30:29 +04:00
|
|
|
EachEntryRef(EntryList(), AddOneUniqueDocumentType, &openedFileTypes, 100);
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
// set the default application to be the selected pose for all the
|
|
|
|
// mime types in the list
|
|
|
|
openedFileTypes.EachElement(SetDefaultAppForOneType,
|
|
|
|
(void *)selectedAppPose->TargetModel()->EntryRef());
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
// done setting the default application, now launch the app with the
|
|
|
|
// documents
|
|
|
|
OpenWithSelection();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::MessageReceived(BMessage *message)
|
|
|
|
{
|
|
|
|
switch (message->what) {
|
|
|
|
case kDefaultButton:
|
|
|
|
OpenWithSelection();
|
|
|
|
PostMessage(B_QUIT_REQUESTED);
|
|
|
|
return;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
case kOpenAndMakeDefault:
|
|
|
|
MakeDefaultAndOpen();
|
|
|
|
PostMessage(B_QUIT_REQUESTED);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case kCancelButton:
|
|
|
|
PostMessage(B_QUIT_REQUESTED);
|
|
|
|
return;
|
2009-01-11 20:39:54 +03:00
|
|
|
|
|
|
|
case B_OBSERVER_NOTICE_CHANGE:
|
|
|
|
return;
|
2012-05-21 17:10:47 +04:00
|
|
|
|
|
|
|
case kResizeToFit:
|
|
|
|
ResizeToFit();
|
|
|
|
break;
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
|
|
|
_inherited::MessageReceived(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
filter_result
|
|
|
|
OpenWithContainerWindow::KeyDownFilter(BMessage *message, BHandler **,
|
|
|
|
BMessageFilter *filter)
|
|
|
|
{
|
|
|
|
uchar key;
|
|
|
|
if (message->FindInt8("byte", (int8 *)&key) != B_OK)
|
|
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
|
|
|
|
int32 modifier=0;
|
|
|
|
message->FindInt32("modifiers", &modifier);
|
|
|
|
if (!modifier && key == B_ESCAPE) {
|
|
|
|
filter->Looper()->PostMessage(kCancelButton);
|
|
|
|
return B_SKIP_MESSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
|
|
|
OpenWithContainerWindow::ShouldAddMenus() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithContainerWindow::ShowContextMenu(BPoint, const entry_ref *, BView *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::AddShortcuts()
|
|
|
|
{
|
2012-05-21 17:10:47 +04:00
|
|
|
AddShortcut('I', B_COMMAND_KEY, new BMessage(kGetInfo), PoseView());
|
|
|
|
AddShortcut('Y', B_COMMAND_KEY, new BMessage(kResizeToFit), PoseView());
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithContainerWindow::NewAttributeMenu(BMenu *menu)
|
|
|
|
{
|
|
|
|
_inherited::NewAttributeMenu(menu);
|
|
|
|
BMessage *message = new BMessage(kAttributeItem);
|
|
|
|
message->AddString("attr_name", kAttrOpenWithRelation);
|
|
|
|
message->AddInt32("attr_type", B_STRING_TYPE);
|
|
|
|
message->AddInt32("attr_hash", (int32)AttrHashString(kAttrOpenWithRelation, B_STRING_TYPE));
|
|
|
|
message->AddFloat("attr_width", 180);
|
|
|
|
message->AddInt32("attr_align", B_ALIGN_LEFT);
|
|
|
|
message->AddBool("attr_editable", false);
|
|
|
|
message->AddBool("attr_statfield", false);
|
2010-07-13 16:39:53 +04:00
|
|
|
BMenuItem *item = new BMenuItem(B_TRANSLATE("Relation"), message);
|
2005-05-23 04:58:42 +04:00
|
|
|
menu->AddItem(item);
|
|
|
|
message = new BMessage(kAttributeItem);
|
|
|
|
message->AddString("attr_name", kAttrAppVersion);
|
|
|
|
message->AddInt32("attr_type", B_STRING_TYPE);
|
|
|
|
message->AddInt32("attr_hash", (int32)AttrHashString(kAttrAppVersion, B_STRING_TYPE));
|
|
|
|
message->AddFloat("attr_width", 70);
|
|
|
|
message->AddInt32("attr_align", B_ALIGN_LEFT);
|
|
|
|
message->AddBool("attr_editable", false);
|
|
|
|
message->AddBool("attr_statfield", false);
|
2010-07-13 16:39:53 +04:00
|
|
|
item = new BMenuItem(B_TRANSLATE("Version"), message);
|
2005-05-23 04:58:42 +04:00
|
|
|
menu->AddItem(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::SaveState(bool)
|
|
|
|
{
|
|
|
|
BNode defaultingNode;
|
|
|
|
if (DefaultStateSourceNode(kDefaultOpenWithTemplate, &defaultingNode,
|
2006-05-31 17:43:17 +04:00
|
|
|
true, false)) {
|
2005-05-23 04:58:42 +04:00
|
|
|
AttributeStreamFileNode streamNodeDestination(&defaultingNode);
|
|
|
|
SaveWindowState(&streamNodeDestination);
|
|
|
|
fPoseView->SaveState(&streamNodeDestination);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::SaveState(BMessage &message) const
|
|
|
|
{
|
|
|
|
_inherited::SaveState(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::Init(const BMessage *message)
|
|
|
|
{
|
|
|
|
_inherited::Init(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithContainerWindow::RestoreState()
|
|
|
|
{
|
|
|
|
BNode defaultingNode;
|
|
|
|
if (DefaultStateSourceNode(kDefaultOpenWithTemplate, &defaultingNode, false)) {
|
|
|
|
AttributeStreamFileNode streamNodeSource(&defaultingNode);
|
|
|
|
RestoreWindowState(&streamNodeSource);
|
|
|
|
fPoseView->Init(&streamNodeSource);
|
|
|
|
} else {
|
|
|
|
RestoreWindowState(NULL);
|
|
|
|
fPoseView->Init(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithContainerWindow::RestoreState(const BMessage &message)
|
|
|
|
{
|
|
|
|
_inherited::RestoreState(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::RestoreWindowState(AttributeStreamNode *node)
|
|
|
|
{
|
2006-06-11 14:19:44 +04:00
|
|
|
SetSizeLimits(fMinimalWidth, 10000, 160, 10000);
|
2005-05-23 04:58:42 +04:00
|
|
|
if (!node)
|
|
|
|
return;
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
const char *rectAttributeName = kAttrWindowFrame;
|
2005-05-23 04:58:42 +04:00
|
|
|
BRect frame(Frame());
|
|
|
|
if (node->Read(rectAttributeName, 0, B_RECT_TYPE, sizeof(BRect), &frame)
|
2008-10-05 00:30:29 +04:00
|
|
|
== sizeof(BRect)) {
|
2005-05-23 04:58:42 +04:00
|
|
|
MoveTo(frame.LeftTop());
|
|
|
|
ResizeTo(frame.Width(), frame.Height());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::RestoreWindowState(const BMessage &message)
|
|
|
|
{
|
|
|
|
_inherited::RestoreWindowState(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::NeedsDefaultStateSetup()
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::SetUpDefaultState()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::IsShowing(const node_ref *) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::IsShowing(const entry_ref *) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::SetCanSetAppAsDefault(bool on)
|
|
|
|
{
|
|
|
|
fLaunchAndMakeDefaultButton->SetEnabled(on);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithContainerWindow::SetCanOpen(bool on)
|
|
|
|
{
|
|
|
|
fLaunchButton->SetEnabled(on);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
OpenWithPoseView::OpenWithPoseView(BRect frame, uint32 resizeMask)
|
2006-05-31 17:43:17 +04:00
|
|
|
: BPoseView(0, frame, kListMode, resizeMask),
|
|
|
|
fHaveCommonPreferredApp(false),
|
|
|
|
fIterator(NULL)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
fSavePoseLocations = false;
|
|
|
|
fMultipleSelection = false;
|
|
|
|
fDragEnabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
OpenWithContainerWindow *
|
|
|
|
OpenWithPoseView::ContainerWindow() const
|
|
|
|
{
|
|
|
|
ASSERT(dynamic_cast<OpenWithContainerWindow *>(Window()));
|
|
|
|
return static_cast<OpenWithContainerWindow *>(Window());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::AttachedToWindow()
|
|
|
|
{
|
|
|
|
_inherited::AttachedToWindow();
|
|
|
|
SetViewColor(kOpenWithDefaultColor);
|
|
|
|
SetLowColor(kOpenWithDefaultColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::CanHandleDragSelection(const Model *, const BMessage *, bool)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
AddSupportingAppForTypeToQuery(SearchForSignatureEntryList *queryIterator,
|
2006-09-28 19:59:04 +04:00
|
|
|
const char *type)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
// get supporting apps for type
|
2006-09-28 19:59:04 +04:00
|
|
|
BMimeType mime(type);
|
2005-05-23 04:58:42 +04:00
|
|
|
if (!mime.IsInstalled())
|
|
|
|
return;
|
|
|
|
|
|
|
|
BMessage message;
|
|
|
|
mime.GetSupportingApps(&message);
|
|
|
|
|
2006-09-28 19:59:04 +04:00
|
|
|
// push each of the supporting apps signature uniquely
|
2005-05-23 04:58:42 +04:00
|
|
|
|
2006-09-28 19:59:04 +04:00
|
|
|
const char *signature;
|
|
|
|
for (int32 index = 0; message.FindString("applications", index,
|
|
|
|
&signature) == B_OK; index++) {
|
2005-05-23 04:58:42 +04:00
|
|
|
queryIterator->PushUniqueSignature(signature);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const entry_ref *
|
|
|
|
AddOneRefSignatures(const entry_ref *ref, void *castToIterator)
|
|
|
|
{
|
2008-10-05 00:30:29 +04:00
|
|
|
// TODO: resolve cases where each entry has a different type and
|
2005-05-23 04:58:42 +04:00
|
|
|
// their supporting apps are disjoint sets
|
|
|
|
|
|
|
|
SearchForSignatureEntryList *queryIterator =
|
|
|
|
(SearchForSignatureEntryList *)castToIterator;
|
|
|
|
|
|
|
|
Model model(ref, true, true);
|
|
|
|
if (model.InitCheck() != B_OK)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
BString mimeType(model.MimeType());
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
if (!mimeType.Length() || mimeType.ICompare(B_FILE_MIMETYPE) == 0)
|
2005-05-23 04:58:42 +04:00
|
|
|
// if model is of unknown type, try mimeseting it first
|
|
|
|
model.Mimeset(true);
|
|
|
|
|
|
|
|
entry_ref preferredRef;
|
|
|
|
|
|
|
|
// add preferred app for file, if any
|
|
|
|
if (model.PreferredAppSignature()[0]) {
|
|
|
|
// got one, mark it as preferred for this node
|
|
|
|
if (be_roster->FindApp(model.PreferredAppSignature(), &preferredRef) == B_OK) {
|
2009-04-26 19:52:01 +04:00
|
|
|
queryIterator->PushUniqueSignature(model.PreferredAppSignature());
|
2005-05-23 04:58:42 +04:00
|
|
|
queryIterator->TrySettingPreferredAppForFile(&preferredRef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mimeType = model.MimeType();
|
|
|
|
mimeType.ToLower();
|
|
|
|
|
|
|
|
if (mimeType.Length() && !mimeType.ICompare(B_FILE_MIMETYPE) == 0)
|
|
|
|
queryIterator->NonGenericFileFound();
|
|
|
|
|
|
|
|
// get supporting apps for type
|
|
|
|
AddSupportingAppForTypeToQuery(queryIterator, mimeType.String());
|
|
|
|
|
|
|
|
// find the preferred app for this type
|
|
|
|
if (be_roster->FindApp(mimeType.String(), &preferredRef) == B_OK)
|
|
|
|
queryIterator->TrySettingPreferredApp(&preferredRef);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EntryListBase *
|
|
|
|
OpenWithPoseView::InitDirentIterator(const entry_ref *)
|
|
|
|
{
|
|
|
|
OpenWithContainerWindow *window = ContainerWindow();
|
|
|
|
|
|
|
|
const BMessage *entryList = window->EntryList();
|
|
|
|
|
|
|
|
fIterator = new SearchForSignatureEntryList(true);
|
|
|
|
|
|
|
|
// push all the supporting apps from all the entries into the
|
|
|
|
// search for signature iterator
|
|
|
|
EachEntryRef(entryList, AddOneRefSignatures, fIterator, 100);
|
|
|
|
|
|
|
|
// push superhandlers
|
|
|
|
AddSupportingAppForTypeToQuery(fIterator, B_FILE_MIMETYPE);
|
|
|
|
fHaveCommonPreferredApp = fIterator->GetPreferredApp(&fPreferredRef);
|
|
|
|
|
|
|
|
if (fIterator->Rewind() != B_OK) {
|
|
|
|
delete fIterator;
|
|
|
|
fIterator = NULL;
|
|
|
|
HideBarberPole();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return fIterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithPoseView::OpenSelection(BPose *pose, int32 *)
|
|
|
|
{
|
|
|
|
OpenWithContainerWindow *window = ContainerWindow();
|
|
|
|
|
|
|
|
int32 count = fSelectionList->CountItems();
|
|
|
|
if (!count)
|
|
|
|
return;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
if (!pose)
|
|
|
|
pose = fSelectionList->FirstItem();
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
ASSERT(pose);
|
|
|
|
|
|
|
|
BEntry entry(pose->TargetModel()->EntryRef());
|
|
|
|
if (entry.InitCheck() != B_OK) {
|
2010-09-16 18:30:20 +04:00
|
|
|
BString errorString(
|
|
|
|
B_TRANSLATE("Could not find application \"%appname\""));
|
|
|
|
errorString.ReplaceFirst("%appname", pose->TargetModel()->Name());
|
2005-05-23 04:58:42 +04:00
|
|
|
|
2010-07-13 16:39:53 +04:00
|
|
|
(new BAlert("", errorString.String(), B_TRANSLATE("OK"), 0, 0,
|
|
|
|
B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
|
2005-05-23 04:58:42 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OpenWithRelation(pose->TargetModel()) == kNoRelation) {
|
|
|
|
if (!fIterator->GenericFilesOnly()) {
|
2010-09-16 18:30:20 +04:00
|
|
|
BString warning(B_TRANSLATE(
|
2010-09-16 20:36:56 +04:00
|
|
|
"The application \"%appname\" does not support the type of "
|
|
|
|
"document you are about to open. Are you sure you want to "
|
|
|
|
"proceed? If you know that the application supports the "
|
|
|
|
"document type, you should contact the publisher of the "
|
|
|
|
"application and ask them to update their application to list "
|
|
|
|
"the type of your document as supported."));
|
2010-09-16 18:30:20 +04:00
|
|
|
warning.ReplaceFirst("%appname", pose->TargetModel()->Name());
|
2005-05-23 04:58:42 +04:00
|
|
|
|
2010-07-13 16:39:53 +04:00
|
|
|
BAlert* alert = new BAlert("", warning.String(),
|
|
|
|
B_TRANSLATE("Cancel"), B_TRANSLATE("Open"), 0, B_WIDTH_AS_USUAL,
|
|
|
|
B_WARNING_ALERT);
|
2009-04-06 03:47:58 +04:00
|
|
|
alert->SetShortcut(0, B_ESCAPE);
|
|
|
|
if (alert->Go() == 0)
|
2005-05-23 04:58:42 +04:00
|
|
|
return;
|
2006-05-31 17:43:17 +04:00
|
|
|
}
|
|
|
|
// else - once we have an extensible sniffer, tell users to ask
|
|
|
|
// publishers to fix up sniffers
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
BMessage message(*window->EntryList());
|
|
|
|
// make a clone to send
|
|
|
|
message.RemoveName("launchUsingSelector");
|
|
|
|
// make sure the old selector is not in the message
|
|
|
|
message.AddRef("handler", pose->TargetModel()->EntryRef());
|
|
|
|
// add ref of the selected handler
|
|
|
|
|
|
|
|
ASSERT(fSelectionHandler);
|
|
|
|
|
|
|
|
if (fSelectionHandler)
|
|
|
|
fSelectionHandler->PostMessage(&message);
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
window->PostMessage(B_QUIT_REQUESTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::Pulse()
|
|
|
|
{
|
|
|
|
// disable the Open and make default button if the default
|
|
|
|
// app matches the selected app
|
|
|
|
//
|
|
|
|
// disable the Open button if no apps selected
|
|
|
|
|
|
|
|
OpenWithContainerWindow *window = ContainerWindow();
|
|
|
|
|
|
|
|
if (!fSelectionList->CountItems()) {
|
|
|
|
window->SetCanSetAppAsDefault(false);
|
|
|
|
window->SetCanOpen(false);
|
|
|
|
_inherited::Pulse();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we selected a non-handling application, don't allow setting
|
|
|
|
// it as preferred
|
|
|
|
Model *firstSelected = fSelectionList->FirstItem()->TargetModel();
|
|
|
|
if (OpenWithRelation(firstSelected) == kNoRelation) {
|
|
|
|
window->SetCanSetAppAsDefault(false);
|
|
|
|
window->SetCanOpen(true);
|
|
|
|
_inherited::Pulse();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make the open button enabled, because we have na app selected
|
|
|
|
window->SetCanOpen(true);
|
|
|
|
if (!fHaveCommonPreferredApp) {
|
|
|
|
window->SetCanSetAppAsDefault(true);
|
|
|
|
_inherited::Pulse();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(fSelectionList->CountItems() == 1);
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
// enable the Open and make default if selected application different
|
|
|
|
// from preferred app ref
|
|
|
|
window->SetCanSetAppAsDefault((*fSelectionList->FirstItem()->
|
|
|
|
TargetModel()->EntryRef()) != fPreferredRef);
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
_inherited::Pulse();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithPoseView::SetUpDefaultColumnsIfNeeded()
|
|
|
|
{
|
|
|
|
// in case there were errors getting some columns
|
|
|
|
if (fColumnList->CountItems() != 0)
|
|
|
|
return;
|
|
|
|
|
2010-07-13 16:39:53 +04:00
|
|
|
BColumn *nameColumn = new BColumn(B_TRANSLATE("Name"), kColumnStart, 125,
|
|
|
|
B_ALIGN_LEFT, kAttrStatName, B_STRING_TYPE, true, true);
|
2005-05-23 04:58:42 +04:00
|
|
|
fColumnList->AddItem(nameColumn);
|
2010-07-13 16:39:53 +04:00
|
|
|
BColumn *relationColumn = new BColumn(B_TRANSLATE("Relation"), 180, 100,
|
|
|
|
B_ALIGN_LEFT, kAttrOpenWithRelation, B_STRING_TYPE, false, false);
|
2005-05-23 04:58:42 +04:00
|
|
|
fColumnList->AddItem(relationColumn);
|
2010-07-13 16:39:53 +04:00
|
|
|
fColumnList->AddItem(new BColumn(B_TRANSLATE("Location"), 290, 225,
|
|
|
|
B_ALIGN_LEFT, kAttrPath, B_STRING_TYPE, true, false));
|
|
|
|
fColumnList->AddItem(new BColumn(B_TRANSLATE("Version"), 525, 70,
|
|
|
|
B_ALIGN_LEFT, kAttrAppVersion, B_STRING_TYPE, false, false));
|
2005-05-23 04:58:42 +04:00
|
|
|
|
|
|
|
// sort by relation and by name
|
|
|
|
SetPrimarySort(relationColumn->AttrHash());
|
|
|
|
SetSecondarySort(nameColumn->AttrHash());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
OpenWithPoseView::AddPosesThreadValid(const entry_ref *) const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OpenWithPoseView::CreatePoses(Model **models, PoseInfo *poseInfoArray, int32 count,
|
|
|
|
BPose **resultingPoses, bool insertionSort, int32 *lastPoseIndexPtr,
|
|
|
|
BRect *boundsPtr, bool forceDraw)
|
|
|
|
{
|
|
|
|
// overridden to try to select the preferred handling app
|
|
|
|
_inherited::CreatePoses(models, poseInfoArray, count, resultingPoses, insertionSort,
|
|
|
|
lastPoseIndexPtr, boundsPtr, forceDraw);
|
2008-10-05 00:30:29 +04:00
|
|
|
|
|
|
|
if (resultingPoses) {
|
|
|
|
for (int32 index = 0; index < count; index++) {
|
2005-05-23 04:58:42 +04:00
|
|
|
if (resultingPoses[index] && fHaveCommonPreferredApp
|
2008-10-05 00:30:29 +04:00
|
|
|
&& *(models[index]->EntryRef()) == fPreferredRef) {
|
2005-05-23 04:58:42 +04:00
|
|
|
// this is our preferred app, select it's pose
|
|
|
|
SelectPose(resultingPoses[index], IndexOfPose(resultingPoses[index]));
|
2008-10-05 00:30:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::KeyDown(const char *bytes, int32 count)
|
|
|
|
{
|
2008-10-05 00:30:29 +04:00
|
|
|
if (bytes[0] == B_TAB) {
|
2005-05-23 04:58:42 +04:00
|
|
|
// just shift the focus, don't tab to the next pose
|
|
|
|
BView::KeyDown(bytes, count);
|
2008-10-05 00:30:29 +04:00
|
|
|
} else
|
2005-05-23 04:58:42 +04:00
|
|
|
_inherited::KeyDown(bytes, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::SaveState(AttributeStreamNode *node)
|
|
|
|
{
|
|
|
|
_inherited::SaveState(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::RestoreState(AttributeStreamNode *node)
|
|
|
|
{
|
|
|
|
_inherited::RestoreState(node);
|
|
|
|
fViewState->SetViewMode(kListMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::SaveState(BMessage &message) const
|
|
|
|
{
|
|
|
|
_inherited::SaveState(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::RestoreState(const BMessage &message)
|
|
|
|
{
|
|
|
|
_inherited::RestoreState(message);
|
|
|
|
fViewState->SetViewMode(kListMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::SavePoseLocations(BRect *)
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::MoveSelectionToTrash(bool)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::MoveSelectionTo(BPoint, BPoint, BContainerWindow *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::MoveSelectionInto(Model *, BContainerWindow *, bool, bool)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::Represents(const node_ref *) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::Represents(const entry_ref *) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::HandleMessageDropped(BMessage *DEBUG_ONLY(message))
|
|
|
|
{
|
|
|
|
#if DEBUG
|
|
|
|
// in debug mode allow tweaking the colors
|
|
|
|
const rgb_color *color;
|
|
|
|
int32 size;
|
|
|
|
// handle roColour-style color drops
|
|
|
|
if (message->FindData("RGBColor", 'RGBC', (const void **)&color, &size) == B_OK) {
|
|
|
|
SetViewColor(*color);
|
|
|
|
SetLowColor(*color);
|
|
|
|
Invalidate();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::OpenWithRelation(const Model *model) const
|
|
|
|
{
|
|
|
|
OpenWithContainerWindow *window = ContainerWindow();
|
|
|
|
|
|
|
|
return SearchForSignatureEntryList::Relation(window->EntryList(),
|
|
|
|
model, fHaveCommonPreferredApp ? &fPreferredRef : 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithPoseView::OpenWithRelationDescription(const Model *model,
|
|
|
|
BString *description) const
|
|
|
|
{
|
|
|
|
OpenWithContainerWindow *window = ContainerWindow();
|
|
|
|
|
|
|
|
SearchForSignatureEntryList::RelationDescription(window->EntryList(),
|
|
|
|
model, description, fHaveCommonPreferredApp ? &fPreferredRef : 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
OpenWithPoseView::ShouldShowPose(const Model *model, const PoseInfo *poseInfo)
|
|
|
|
{
|
|
|
|
OpenWithContainerWindow *window = ContainerWindow();
|
|
|
|
// filter for add_poses
|
|
|
|
if (!fIterator->CanOpenWithFilter(model, window->EntryList(),
|
|
|
|
fHaveCommonPreferredApp ? &fPreferredRef : 0))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return _inherited::ShouldShowPose(model, poseInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
RelationCachingModelProxy::RelationCachingModelProxy(Model *model)
|
2006-05-31 17:43:17 +04:00
|
|
|
:
|
|
|
|
fModel(model),
|
|
|
|
fRelation(kUnknownRelation)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RelationCachingModelProxy::~RelationCachingModelProxy()
|
|
|
|
{
|
|
|
|
delete fModel;
|
|
|
|
}
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
|
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
RelationCachingModelProxy::Relation(SearchForSignatureEntryList *iterator,
|
|
|
|
BMessage *entries) const
|
|
|
|
{
|
2008-10-05 00:30:29 +04:00
|
|
|
if (fRelation == kUnknownRelation)
|
2006-05-31 17:43:17 +04:00
|
|
|
fRelation = iterator->Relation(entries, fModel);
|
2005-05-23 04:58:42 +04:00
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
return fRelation;
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
OpenWithMenu::OpenWithMenu(const char *label, const BMessage *entriesToOpen,
|
2006-05-31 17:43:17 +04:00
|
|
|
BWindow *parentWindow, BHandler *target)
|
|
|
|
: BSlowMenu(label),
|
|
|
|
fEntriesToOpen(*entriesToOpen),
|
|
|
|
target(target),
|
|
|
|
fIterator(NULL),
|
|
|
|
fSupportingAppList(NULL),
|
|
|
|
fParentWindow(parentWindow)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
InitIconPreloader();
|
|
|
|
|
|
|
|
SetFont(be_plain_font);
|
|
|
|
|
|
|
|
// too long to have triggers
|
|
|
|
SetTriggersEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
OpenWithMenu::OpenWithMenu(const char *label, const BMessage *entriesToOpen,
|
2006-05-31 17:43:17 +04:00
|
|
|
BWindow *parentWindow, const BMessenger &messenger)
|
|
|
|
: BSlowMenu(label),
|
|
|
|
fEntriesToOpen(*entriesToOpen),
|
|
|
|
target(NULL),
|
|
|
|
fMessenger(messenger),
|
|
|
|
fIterator(NULL),
|
|
|
|
fSupportingAppList(NULL),
|
|
|
|
fParentWindow(parentWindow)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
InitIconPreloader();
|
|
|
|
|
|
|
|
SetFont(be_plain_font);
|
|
|
|
|
|
|
|
// too long to have triggers
|
|
|
|
SetTriggersEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace BPrivate {
|
|
|
|
|
|
|
|
int
|
|
|
|
SortByRelationAndName(const RelationCachingModelProxy *model1,
|
|
|
|
const RelationCachingModelProxy *model2, void *castToMenu)
|
|
|
|
{
|
|
|
|
OpenWithMenu *menu = (OpenWithMenu *)castToMenu;
|
|
|
|
|
|
|
|
// find out the relations of app models to the opened entries
|
|
|
|
int32 relation1 = model1->Relation(menu->fIterator, &menu->fEntriesToOpen);
|
|
|
|
int32 relation2 = model2->Relation(menu->fIterator, &menu->fEntriesToOpen);
|
|
|
|
|
|
|
|
if (relation1 < relation2) {
|
|
|
|
// relation with the lowest number goes first
|
|
|
|
return 1;
|
|
|
|
} else if (relation1 > relation2)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
// if relations match, sort by app name
|
|
|
|
return strcmp(model1->fModel->Name(), model2->fModel->Name());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace BPrivate
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
OpenWithMenu::StartBuildingItemList()
|
|
|
|
{
|
|
|
|
fIterator = new SearchForSignatureEntryList(false);
|
|
|
|
// push all the supporting apps from all the entries into the
|
|
|
|
// search for signature iterator
|
|
|
|
EachEntryRef(&fEntriesToOpen, AddOneRefSignatures, fIterator, 100);
|
|
|
|
// add superhandlers
|
|
|
|
AddSupportingAppForTypeToQuery(fIterator, B_FILE_MIMETYPE);
|
|
|
|
|
|
|
|
fHaveCommonPreferredApp = fIterator->GetPreferredApp(&fPreferredRef);
|
|
|
|
status_t error = fIterator->Rewind();
|
|
|
|
if (error != B_OK) {
|
|
|
|
PRINT(("failed to initialize iterator %s\n", strerror(error)));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
fSupportingAppList = new BObjectList<RelationCachingModelProxy>(20, true);
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
//queryRetrieval = new BStopWatch("get next entry on BQuery");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithMenu::AddNextItem()
|
|
|
|
{
|
|
|
|
BEntry entry;
|
|
|
|
if (fIterator->GetNextEntry(&entry) != B_OK)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Model *model = new Model(&entry, true);
|
|
|
|
if (model->InitCheck() != B_OK
|
|
|
|
|| !fIterator->CanOpenWithFilter(model, &fEntriesToOpen,
|
|
|
|
fHaveCommonPreferredApp ? &fPreferredRef : 0)) {
|
|
|
|
// only allow executables, filter out multiple copies of the
|
|
|
|
// Tracker, filter out version that don't list the correct types,
|
|
|
|
// etc.
|
|
|
|
delete model;
|
2008-10-05 00:30:29 +04:00
|
|
|
} else
|
2005-05-23 04:58:42 +04:00
|
|
|
fSupportingAppList->AddItem(new RelationCachingModelProxy(model));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithMenu::DoneBuildingItemList()
|
|
|
|
{
|
|
|
|
// sort by app name
|
|
|
|
fSupportingAppList->SortItems(SortByRelationAndName, this);
|
|
|
|
|
|
|
|
// check if each app is unique
|
|
|
|
bool unique = true;
|
|
|
|
int32 count = fSupportingAppList->CountItems();
|
|
|
|
for (int32 index = 0; index < count - 1; index++) {
|
|
|
|
// the list is sorted, just compare two adjacent models
|
|
|
|
if (strcmp(fSupportingAppList->ItemAt(index)->fModel->Name(),
|
|
|
|
fSupportingAppList->ItemAt(index + 1)->fModel->Name()) == 0) {
|
|
|
|
unique = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add apps as menu items
|
|
|
|
BFont font;
|
|
|
|
GetFont(&font);
|
|
|
|
|
|
|
|
int32 lastRelation = -1;
|
|
|
|
for (int32 index = 0; index < count ; index++) {
|
|
|
|
RelationCachingModelProxy *modelProxy = fSupportingAppList->ItemAt(index);
|
|
|
|
Model *model = modelProxy->fModel;
|
|
|
|
BMessage *message = new BMessage(fEntriesToOpen);
|
|
|
|
message->AddRef("handler", model->EntryRef());
|
|
|
|
BContainerWindow *window = dynamic_cast<BContainerWindow *>(fParentWindow);
|
|
|
|
if (window)
|
|
|
|
message->AddData("nodeRefsToClose", B_RAW_TYPE, window->TargetModel()->NodeRef(),
|
|
|
|
sizeof (node_ref));
|
|
|
|
|
|
|
|
BString result;
|
|
|
|
if (unique) {
|
|
|
|
// just use the app name
|
|
|
|
result = model->Name();
|
|
|
|
} else {
|
|
|
|
// get a truncated full path
|
|
|
|
BPath path;
|
|
|
|
BEntry entry(model->EntryRef());
|
|
|
|
if (entry.GetPath(&path) != B_OK) {
|
|
|
|
PRINT(("stale entry ref %s\n", model->Name()));
|
|
|
|
delete message;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
result = path.Path();
|
|
|
|
font.TruncateString(&result, B_TRUNCATE_MIDDLE, kMaxMenuWidth);
|
|
|
|
}
|
|
|
|
#if DEBUG
|
|
|
|
BString relationDescription;
|
|
|
|
fIterator->RelationDescription(&fEntriesToOpen, model, &relationDescription);
|
|
|
|
result += " (";
|
|
|
|
result += relationDescription;
|
|
|
|
result += ")";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// divide different relations of opening with a separator
|
|
|
|
int32 relation = modelProxy->Relation(fIterator, &fEntriesToOpen);
|
|
|
|
if (lastRelation != -1 && relation != lastRelation)
|
2008-10-05 00:30:29 +04:00
|
|
|
AddSeparatorItem();
|
2005-05-23 04:58:42 +04:00
|
|
|
lastRelation = relation;
|
|
|
|
|
|
|
|
ModelMenuItem *item = new ModelMenuItem(model, result.String(), message);
|
|
|
|
AddItem(item);
|
|
|
|
// mark item if it represents the preferred app
|
|
|
|
if (fHaveCommonPreferredApp && *(model->EntryRef()) == fPreferredRef) {
|
|
|
|
//PRINT(("marking item for % as preferred", model->Name()));
|
|
|
|
item->SetMarked(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// target the menu
|
|
|
|
if (target)
|
|
|
|
SetTargetForItems(target);
|
|
|
|
else
|
|
|
|
SetTargetForItems(fMessenger);
|
|
|
|
|
|
|
|
if (!CountItems()) {
|
2010-07-13 16:39:53 +04:00
|
|
|
BMenuItem* item = new BMenuItem(B_TRANSLATE("no supporting apps"), 0);
|
2005-05-23 04:58:42 +04:00
|
|
|
item->SetEnabled(false);
|
|
|
|
AddItem(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
OpenWithMenu::ClearMenuBuildingState()
|
|
|
|
{
|
|
|
|
delete fIterator;
|
|
|
|
fIterator = NULL;
|
|
|
|
delete fSupportingAppList;
|
|
|
|
fSupportingAppList = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
SearchForSignatureEntryList::SearchForSignatureEntryList(bool canAddAllApps)
|
2006-05-31 17:43:17 +04:00
|
|
|
:
|
|
|
|
fIteratorList(NULL),
|
|
|
|
fSignatures(20, true),
|
|
|
|
fPreferredAppCount(0),
|
|
|
|
fPreferredAppForFileCount(0),
|
|
|
|
fGenericFilesOnly(true),
|
|
|
|
fCanAddAllApps(canAddAllApps),
|
|
|
|
fFoundOneNonSuperHandler(false)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SearchForSignatureEntryList::~SearchForSignatureEntryList()
|
|
|
|
{
|
|
|
|
delete fIteratorList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::PushUniqueSignature(const char *str)
|
|
|
|
{
|
|
|
|
// do a unique add
|
|
|
|
if (fSignatures.EachElement(FindOne, (void *)str))
|
|
|
|
return;
|
2006-09-28 19:59:04 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
fSignatures.AddItem(new BString(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
status_t
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::GetNextEntry(BEntry *entry, bool)
|
|
|
|
{
|
|
|
|
return fIteratorList->GetNextEntry(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
status_t
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::GetNextRef(entry_ref *ref)
|
|
|
|
{
|
|
|
|
return fIteratorList->GetNextRef(ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::GetNextDirents(struct dirent *buffer,
|
|
|
|
size_t length, int32 count)
|
|
|
|
{
|
|
|
|
return fIteratorList->GetNextDirents(buffer, length, count);
|
|
|
|
}
|
|
|
|
|
2006-09-28 19:59:04 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
struct AddOneTermParams {
|
|
|
|
BString *result;
|
|
|
|
bool first;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const BString *
|
|
|
|
AddOnePredicateTerm(const BString *item, void *castToParams)
|
|
|
|
{
|
|
|
|
AddOneTermParams *params = (AddOneTermParams *)castToParams;
|
|
|
|
if (!params->first)
|
|
|
|
(*params->result) << " || ";
|
|
|
|
(*params->result) << kAttrAppSignature << " = " << item->String();
|
|
|
|
|
|
|
|
params->first = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
status_t
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::Rewind()
|
|
|
|
{
|
|
|
|
if (fIteratorList)
|
|
|
|
return fIteratorList->Rewind();
|
|
|
|
|
|
|
|
if (!fSignatures.CountItems())
|
|
|
|
return ENOENT;
|
|
|
|
|
|
|
|
// build up the iterator
|
2008-10-05 00:33:20 +04:00
|
|
|
fIteratorList = new CachedEntryIteratorList(false);
|
|
|
|
// We cannot sort the cached inodes, as CanOpenWithFilter() relies
|
|
|
|
// on the fact that ConditionalAllAppsIterator results come last.
|
2005-05-23 04:58:42 +04:00
|
|
|
|
|
|
|
// build the predicate string by oring queries for the individual
|
|
|
|
// signatures
|
|
|
|
BString predicateString;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
AddOneTermParams params;
|
|
|
|
params.result = &predicateString;
|
|
|
|
params.first = true;
|
|
|
|
|
|
|
|
fSignatures.EachElement(AddOnePredicateTerm, ¶ms);
|
|
|
|
|
|
|
|
ASSERT(predicateString.Length());
|
|
|
|
// PRINT(("query predicate %s\n", predicateString.String()));
|
|
|
|
fIteratorList->AddItem(new TWalkerWrapper(
|
2010-07-14 19:32:00 +04:00
|
|
|
new BTrackerPrivate::TQueryWalker(predicateString.String())));
|
2005-05-23 04:58:42 +04:00
|
|
|
fIteratorList->AddItem(new ConditionalAllAppsIterator(this));
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
return fIteratorList->Rewind();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::CountEntries()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::GetPreferredApp(entry_ref *ref) const
|
|
|
|
{
|
|
|
|
if (fPreferredAppCount == 1)
|
|
|
|
*ref = fPreferredRef;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
return fPreferredAppCount == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
SearchForSignatureEntryList::TrySettingPreferredApp(const entry_ref *ref)
|
|
|
|
{
|
|
|
|
if (!fPreferredAppCount) {
|
|
|
|
fPreferredRef = *ref;
|
|
|
|
fPreferredAppCount++;
|
|
|
|
} else if (fPreferredRef != *ref)
|
|
|
|
// if more than one, will not return any
|
|
|
|
fPreferredAppCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::TrySettingPreferredAppForFile(const entry_ref *ref)
|
|
|
|
{
|
|
|
|
if (!fPreferredAppForFileCount) {
|
|
|
|
fPreferredRefForFile = *ref;
|
|
|
|
fPreferredAppForFileCount++;
|
|
|
|
} else if (fPreferredRefForFile != *ref) {
|
|
|
|
// if more than one, will not return any
|
|
|
|
fPreferredAppForFileCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::NonGenericFileFound()
|
|
|
|
{
|
|
|
|
fGenericFilesOnly = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::GenericFilesOnly() const
|
|
|
|
{
|
|
|
|
return fGenericFilesOnly;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::ShowAllApplications() const
|
|
|
|
{
|
|
|
|
return fCanAddAllApps && !fFoundOneNonSuperHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::Relation(const Model *nodeModel,
|
|
|
|
const Model *applicationModel)
|
|
|
|
{
|
|
|
|
switch (applicationModel->SupportsMimeType(nodeModel->MimeType(), 0, true)) {
|
|
|
|
case kDoesNotSupportType:
|
|
|
|
return kNoRelation;
|
|
|
|
|
|
|
|
case kSuperhandlerModel:
|
|
|
|
return kSuperhandler;
|
|
|
|
|
|
|
|
case kModelSupportsSupertype:
|
|
|
|
return kSupportsSupertype;
|
|
|
|
|
|
|
|
case kModelSupportsType:
|
|
|
|
return kSupportsType;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRESPASS();
|
|
|
|
return kNoRelation;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::Relation(const BMessage *entriesToOpen,
|
|
|
|
const Model *model) const
|
|
|
|
{
|
|
|
|
return Relation(entriesToOpen, model,
|
|
|
|
fPreferredAppCount == 1 ? &fPreferredRef : 0,
|
|
|
|
fPreferredAppForFileCount == 1 ? &fPreferredRefForFile : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::RelationDescription(const BMessage *entriesToOpen,
|
|
|
|
const Model *model, BString *description) const
|
|
|
|
{
|
|
|
|
RelationDescription(entriesToOpen, model, description,
|
|
|
|
fPreferredAppCount == 1 ? &fPreferredRef : 0,
|
|
|
|
fPreferredAppForFileCount == 1 ? &fPreferredRefForFile : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::Relation(const BMessage *entriesToOpen,
|
|
|
|
const Model *applicationModel, const entry_ref *preferredApp,
|
|
|
|
const entry_ref *preferredAppForFile)
|
|
|
|
{
|
|
|
|
for (int32 index = 0; ; index++) {
|
|
|
|
entry_ref ref;
|
|
|
|
if (entriesToOpen->FindRef("refs", index, &ref) != B_OK)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// need to init a model so that typeless folders etc. will still appear to
|
|
|
|
// have a mime type
|
|
|
|
|
|
|
|
Model model(&ref, true, true);
|
|
|
|
if (model.InitCheck())
|
|
|
|
continue;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
int32 result = Relation(&model, applicationModel);
|
|
|
|
if (result != kNoRelation) {
|
|
|
|
if (preferredAppForFile
|
|
|
|
&& *applicationModel->EntryRef() == *preferredAppForFile)
|
|
|
|
return kPreferredForFile;
|
|
|
|
|
|
|
|
if (result == kSupportsType && preferredApp
|
2008-10-05 00:30:29 +04:00
|
|
|
&& *applicationModel->EntryRef() == *preferredApp)
|
2005-05-23 04:58:42 +04:00
|
|
|
// application matches cached preferred app, we are done
|
|
|
|
return kPreferredForType;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
return kNoRelation;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-05 00:30:29 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
SearchForSignatureEntryList::RelationDescription(const BMessage *entriesToOpen,
|
|
|
|
const Model *applicationModel, BString *description, const entry_ref *preferredApp,
|
|
|
|
const entry_ref *preferredAppForFile)
|
|
|
|
{
|
|
|
|
for (int32 index = 0; ;index++) {
|
|
|
|
entry_ref ref;
|
|
|
|
if (entriesToOpen->FindRef("refs", index, &ref) != B_OK)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (preferredAppForFile && ref == *preferredAppForFile) {
|
2010-09-16 18:30:20 +04:00
|
|
|
description->SetTo(B_TRANSLATE("Preferred for file"));
|
2005-05-23 04:58:42 +04:00
|
|
|
return;
|
|
|
|
}
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
Model model(&ref, true, true);
|
|
|
|
if (model.InitCheck())
|
|
|
|
continue;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
BMimeType mimeType;
|
|
|
|
int32 result = Relation(&model, applicationModel);
|
|
|
|
switch (result) {
|
|
|
|
case kDoesNotSupportType:
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case kSuperhandler:
|
2010-09-16 18:30:20 +04:00
|
|
|
description->SetTo(B_TRANSLATE("Handles any file"));
|
2005-05-23 04:58:42 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
case kSupportsSupertype:
|
2008-10-05 00:30:29 +04:00
|
|
|
{
|
|
|
|
mimeType.SetTo(model.MimeType());
|
|
|
|
// status_t result = mimeType.GetSupertype(&mimeType);
|
|
|
|
|
|
|
|
char *type = (char *)mimeType.Type();
|
|
|
|
char *tmp = strchr(type, '/');
|
|
|
|
if (tmp)
|
|
|
|
*tmp = '\0';
|
|
|
|
|
|
|
|
//PRINT(("getting supertype for %s, result %s, got %s\n",
|
|
|
|
// model.MimeType(), strerror(result), mimeType.Type()));
|
2010-09-16 18:30:20 +04:00
|
|
|
description->SetTo(B_TRANSLATE("Handles any %type"));
|
2008-10-05 00:30:29 +04:00
|
|
|
// *description += mimeType.Type();
|
2010-09-16 18:30:20 +04:00
|
|
|
description->ReplaceFirst("%type", type);
|
2008-10-05 00:30:29 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
case kSupportsType:
|
2008-10-05 00:30:29 +04:00
|
|
|
{
|
|
|
|
mimeType.SetTo(model.MimeType());
|
|
|
|
|
|
|
|
if (preferredApp && *applicationModel->EntryRef() == *preferredApp)
|
|
|
|
// application matches cached preferred app, we are done
|
2010-09-16 18:30:20 +04:00
|
|
|
description->SetTo(B_TRANSLATE("Preferred for %type"));
|
2008-10-05 00:30:29 +04:00
|
|
|
else
|
2010-09-16 18:30:20 +04:00
|
|
|
description->SetTo(B_TRANSLATE("Handles %type"));
|
2008-10-05 00:30:29 +04:00
|
|
|
|
|
|
|
char shortDescription[256];
|
|
|
|
if (mimeType.GetShortDescription(shortDescription) == B_OK)
|
2010-09-16 18:30:20 +04:00
|
|
|
description->ReplaceFirst("%type", shortDescription);
|
2008-10-05 00:30:29 +04:00
|
|
|
else
|
2010-09-16 18:30:20 +04:00
|
|
|
description->ReplaceFirst("%type", mimeType.Type());
|
2008-10-05 00:30:29 +04:00
|
|
|
return;
|
|
|
|
}
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
|
|
|
}
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2010-09-16 18:30:20 +04:00
|
|
|
description->SetTo(B_TRANSLATE("Does not handle file"));
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
SearchForSignatureEntryList::CanOpenWithFilter(const Model *appModel,
|
|
|
|
const BMessage *entriesToOpen, const entry_ref *preferredApp)
|
|
|
|
{
|
|
|
|
if (!appModel->IsExecutable() || !appModel->Node()) {
|
|
|
|
// weed out non-executable
|
|
|
|
#if xDEBUG
|
|
|
|
BPath path;
|
|
|
|
BEntry entry(appModel->EntryRef());
|
|
|
|
entry.GetPath(&path);
|
|
|
|
PRINT(("filtering out %s- not executable \n", path.Path()));
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-05-31 17:45:12 +04:00
|
|
|
if (strcasecmp(appModel->MimeType(), B_APP_MIME_TYPE) != 0) {
|
2005-05-23 04:58:42 +04:00
|
|
|
// filter out pe containers on PPC etc.
|
|
|
|
return false;
|
2006-05-31 17:43:17 +04:00
|
|
|
}
|
2005-05-23 04:58:42 +04:00
|
|
|
|
|
|
|
ASSERT(dynamic_cast<BFile *>(appModel->Node()));
|
|
|
|
char signature[B_MIME_TYPE_LENGTH];
|
|
|
|
status_t result = GetAppSignatureFromAttr(
|
|
|
|
dynamic_cast<BFile *>(appModel->Node()), signature);
|
|
|
|
|
|
|
|
if (result == B_OK && strcasecmp(signature, kTrackerSignature) == 0) {
|
|
|
|
// special case the Tracker - make sure only the running copy is
|
|
|
|
// in the list
|
|
|
|
app_info trackerInfo;
|
|
|
|
result = be_roster->GetActiveAppInfo(&trackerInfo);
|
|
|
|
if (*appModel->EntryRef() != trackerInfo.ref) {
|
|
|
|
// this is an inactive copy of the Tracker, remove it
|
|
|
|
|
|
|
|
#if xDEBUG
|
|
|
|
BPath path, path2;
|
|
|
|
BEntry entry(appModel->EntryRef());
|
|
|
|
entry.GetPath(&path);
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
BEntry entry2(&trackerInfo.ref);
|
|
|
|
entry2.GetPath(&path2);
|
|
|
|
|
|
|
|
PRINT(("filtering out %s, sig %s, active Tracker at %s, result %s, refName %s\n",
|
|
|
|
path.Path(), signature, path2.Path(), strerror(result),
|
|
|
|
trackerInfo.ref.name));
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
if (FSInTrashDir(appModel->EntryRef()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ShowAllApplications()) {
|
|
|
|
// don't check for these if we didn't look for every single app
|
|
|
|
// to not slow filtering down
|
|
|
|
uint32 flags;
|
|
|
|
BAppFileInfo appFileInfo(dynamic_cast<BFile *>(appModel->Node()));
|
|
|
|
if (appFileInfo.GetAppFlags(&flags) != B_OK)
|
|
|
|
return false;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
if ((flags & B_BACKGROUND_APP) || (flags & B_ARGV_ONLY))
|
|
|
|
return false;
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
if (!signature[0])
|
|
|
|
// weed out apps with empty signatures
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32 relation = Relation(entriesToOpen, appModel, preferredApp, 0);
|
|
|
|
if (relation == kNoRelation && !ShowAllApplications()) {
|
|
|
|
#if xDEBUG
|
|
|
|
BPath path;
|
|
|
|
BEntry entry(appModel->EntryRef());
|
|
|
|
entry.GetPath(&path);
|
2008-10-05 00:30:29 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
PRINT(("filtering out %s, does not handle any of opened files\n",
|
|
|
|
path.Path()));
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
if (relation != kNoRelation && relation != kSuperhandler && !fGenericFilesOnly) {
|
2005-05-23 04:58:42 +04:00
|
|
|
// we hit at least one app that is not a superhandler and
|
|
|
|
// handles the document
|
|
|
|
fFoundOneNonSuperHandler = true;
|
2006-05-31 17:43:17 +04:00
|
|
|
}
|
2005-05-23 04:58:42 +04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
ConditionalAllAppsIterator::ConditionalAllAppsIterator(
|
2006-05-31 17:43:17 +04:00
|
|
|
SearchForSignatureEntryList *parent)
|
|
|
|
:
|
|
|
|
fParent(parent),
|
|
|
|
fWalker(NULL)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
void
|
2005-05-23 04:58:42 +04:00
|
|
|
ConditionalAllAppsIterator::Instantiate()
|
|
|
|
{
|
|
|
|
if (fWalker)
|
|
|
|
return;
|
|
|
|
|
|
|
|
BString lookForAppsPredicate;
|
|
|
|
lookForAppsPredicate << "(" << kAttrAppSignature << " = \"*\" ) && ( "
|
|
|
|
<< kAttrMIMEType << " = " << B_APP_MIME_TYPE << " ) ";
|
2010-07-14 19:32:00 +04:00
|
|
|
fWalker = new BTrackerPrivate::TQueryWalker(lookForAppsPredicate.String());
|
2005-05-23 04:58:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ConditionalAllAppsIterator::~ConditionalAllAppsIterator()
|
|
|
|
{
|
|
|
|
delete fWalker;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
status_t
|
2005-05-23 04:58:42 +04:00
|
|
|
ConditionalAllAppsIterator::GetNextEntry(BEntry *entry, bool traverse)
|
|
|
|
{
|
|
|
|
if (!Iterate())
|
|
|
|
return B_ENTRY_NOT_FOUND;
|
|
|
|
|
|
|
|
Instantiate();
|
|
|
|
return fWalker->GetNextEntry(entry, traverse);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
status_t
|
2005-05-23 04:58:42 +04:00
|
|
|
ConditionalAllAppsIterator::GetNextRef(entry_ref *ref)
|
|
|
|
{
|
|
|
|
if (!Iterate())
|
|
|
|
return B_ENTRY_NOT_FOUND;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
Instantiate();
|
|
|
|
return fWalker->GetNextRef(ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
int32
|
2008-10-05 00:30:29 +04:00
|
|
|
ConditionalAllAppsIterator::GetNextDirents(struct dirent *buffer, size_t length,
|
|
|
|
int32 count)
|
2005-05-23 04:58:42 +04:00
|
|
|
{
|
|
|
|
if (!Iterate())
|
|
|
|
return 0;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
Instantiate();
|
|
|
|
return fWalker->GetNextDirents(buffer, length, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
status_t
|
2005-05-23 04:58:42 +04:00
|
|
|
ConditionalAllAppsIterator::Rewind()
|
|
|
|
{
|
|
|
|
if (!Iterate())
|
|
|
|
return B_OK;
|
2006-05-31 17:43:17 +04:00
|
|
|
|
2005-05-23 04:58:42 +04:00
|
|
|
Instantiate();
|
|
|
|
return fWalker->Rewind();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
int32
|
2005-05-23 04:58:42 +04:00
|
|
|
ConditionalAllAppsIterator::CountEntries()
|
|
|
|
{
|
|
|
|
if (!Iterate())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Instantiate();
|
|
|
|
return fWalker->CountEntries();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 17:43:17 +04:00
|
|
|
bool
|
2005-05-23 04:58:42 +04:00
|
|
|
ConditionalAllAppsIterator::Iterate() const
|
|
|
|
{
|
|
|
|
return fParent->ShowAllApplications();
|
|
|
|
}
|
|
|
|
|