void BSlowContextMenu::BuildVolumeMenu() { BVolumeRoster roster; BVolume volume; roster.Rewind(); while (roster.GetNextVolume(&volume) == B_OK) { if (!volume.IsPersistent()) continue; BDirectory startDir; if (volume.GetRootDirectory(&startDir) == B_OK) { BEntry entry; startDir.GetEntry(&entry); Model *model = new Model(&entry); if (model->InitCheck() != B_OK) { delete model; continue; } BNavMenu *menu = new BNavMenu(model->Name(), fMessage.what, fMessenger, fParentWindow, fTypesList); menu->SetNavDir(model->EntryRef()); menu->InitTrackingHook(fTrackingHook.fTrackingHook, &(fTrackingHook.fTarget), fTrackingHook.fDragMessage); ASSERT(menu->Name()); ModelMenuItem *item = new ModelMenuItem(model, menu); BMessage *message = new BMessage(fMessage); message->AddRef("refs", model->EntryRef()); item->SetMessage(message); fItemList->AddItem(item); ASSERT(item->Label()); } } }
void TFilePanel::HandleOpenButton() { PoseView()->CommitActivePose(); BObjectList<BPose>* selection = PoseView()->SelectionList(); // if we have only one directory and we're not opening dirs, enter. if ((fNodeFlavors & B_DIRECTORY_NODE) == 0 && selection->CountItems() == 1) { Model* model = selection->FirstItem()->TargetModel(); if (model->IsDirectory() || (model->IsSymLink() && !(fNodeFlavors & B_SYMLINK_NODE) && model->ResolveIfLink()->IsDirectory())) { BMessage message(B_REFS_RECEIVED); message.AddRef("refs", model->EntryRef()); PostMessage(&message); return; } } // don't do anything unless there are items selected // message->fMessage->message from here to end if (selection->CountItems()) { BMessage message(*fMessage); // go through selection and add appropriate items for (int32 index = 0; index < selection->CountItems(); index++) { Model* model = selection->ItemAt(index)->TargetModel(); if (((fNodeFlavors & B_DIRECTORY_NODE) != 0 && model->ResolveIfLink()->IsDirectory()) || ((fNodeFlavors & B_SYMLINK_NODE) != 0 && model->IsSymLink()) || ((fNodeFlavors & B_FILE_NODE) != 0 && model->ResolveIfLink()->IsFile())) { message.AddRef("refs", model->EntryRef()); } } OpenSelectionCommon(&message); } }
status_t VirtualDirectoryPoseView::_UpdateDirectoryPaths() { VirtualDirectoryManager* manager = VirtualDirectoryManager::Instance(); Model* model = TargetModel(); status_t error = manager->ResolveDirectoryPaths(*model->NodeRef(), *model->EntryRef(), fDirectoryPaths); if (error != B_OK) return error; manager->GetDefinitionFileChangeTime(*model->NodeRef(), fFileChangeTime); return B_OK; }
void TFilePanel::OpenDirectory() { BObjectList<BPose>* list = PoseView()->SelectionList(); if (list->CountItems() != 1) return; Model* model = list->FirstItem()->TargetModel(); if (model->ResolveIfLink()->IsDirectory()) { BMessage message(B_REFS_RECEIVED); message.AddRef("refs", model->EntryRef()); PostMessage(&message); } }
ModelMenuItem * BSlowContextMenu::NewModelItem(Model *model, const BMessage *invokeMessage, const BMessenger &target, bool suppressFolderHierarchy, BContainerWindow *parentWindow, const BObjectList<BString> *typeslist, TrackingHookData *hook) { if (model->InitCheck() != B_OK) return NULL; entry_ref ref; bool container = false; if (model->IsSymLink()) { Model *newResolvedModel = NULL; Model *result = model->LinkTo(); if (!result) { newResolvedModel = new Model(model->EntryRef(), true, true); if (newResolvedModel->InitCheck() != B_OK) { // broken link, still can show though, bail delete newResolvedModel; newResolvedModel = NULL; } result = newResolvedModel; } if (result) { BModelOpener opener(result); // open the model, if it ain't open already PoseInfo poseInfo; ssize_t size = -1; if (result->Node()) size = result->Node()->ReadAttr(kAttrPoseInfo, B_RAW_TYPE, 0, &poseInfo, sizeof(poseInfo)); result->CloseNode(); ref = *result->EntryRef(); container = result->IsContainer(); } model->SetLinkTo(result); } else { ref = *model->EntryRef(); container = model->IsContainer(); } BMessage *message = new BMessage(*invokeMessage); message->AddRef("refs", model->EntryRef()); // Truncate the name if necessary BString truncatedString(model->Name()); be_plain_font->TruncateString(&truncatedString, B_TRUNCATE_END, BNavMenu::GetMaxMenuWidth()); ModelMenuItem *item = NULL; if (!container || suppressFolderHierarchy) { item = new ModelMenuItem(model, truncatedString.String(), message); if (invokeMessage->what != B_REFS_RECEIVED) item->SetEnabled(false); } else { BNavMenu *menu = new BNavMenu(truncatedString.String(), invokeMessage->what, target, parentWindow, typeslist); menu->SetNavDir(&ref); if (hook) menu->InitTrackingHook(hook->fTrackingHook, &(hook->fTarget), hook->fDragMessage); item = new ModelMenuItem(model, menu); item->SetMessage(message); } return item; }
status_t TTracker::OpenRef(const entry_ref *ref, const node_ref *nodeToClose, const node_ref *nodeToSelect, OpenSelector selector, const BMessage *messageToBundle) { Model *model = NULL; BEntry entry(ref, true); status_t result = entry.InitCheck(); bool brokenLinkWithSpecificHandler = false; BString brokenLinkPreferredApp; if (result != B_OK) { model = new Model(ref, false); if (model->IsSymLink() && !model->LinkTo()) { model->GetPreferredAppForBrokenSymLink(brokenLinkPreferredApp); if (brokenLinkPreferredApp.Length() && brokenLinkPreferredApp != kTrackerSignature) brokenLinkWithSpecificHandler = true; } if (!brokenLinkWithSpecificHandler) { delete model; (new BAlert("", "There was an error resolving the link.", "Cancel", 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); return result; } } else model = new Model(&entry); result = model->InitCheck(); if (result != B_OK) { delete model; return result; } bool openAsContainer = model->IsContainer(); if (openAsContainer && selector != kOpenWith) { // if folder or query has a preferred handler and it's not the // Tracker, open it by sending refs to the handling app // if we are responding to the final open of OpenWith, just // skip this and proceed to opening the container with Tracker model->OpenNode(); BNodeInfo nodeInfo(model->Node()); char preferredApp[B_MIME_TYPE_LENGTH]; if (nodeInfo.GetPreferredApp(preferredApp) == B_OK && strcasecmp(preferredApp, kTrackerSignature) != 0) openAsContainer = false; model->CloseNode(); } if (openAsContainer || selector == kRunOpenWithWindow) { // special case opening plain folders, queries or using open with OpenContainerWindow(model, 0, selector); // window adopts model if (nodeToClose) CloseParentWaitingForChildSoon(ref, nodeToClose); } else if (model->IsQueryTemplate()) { // query template - open new find window (new FindWindow(model->EntryRef()))->Show(); if (nodeToClose) CloseParentWaitingForChildSoon(ref, nodeToClose); } else { delete model; // run Launch in a separate thread // and close parent if successfull if (nodeToClose) Thread::Launch(new EntryAndNodeDoSoonWithMessageFunctor<TTracker, bool (TTracker::*)(const entry_ref *, const node_ref *, const BMessage *)>(&TTracker::LaunchAndCloseParentIfOK, this, ref, nodeToClose, messageToBundle)); else { BMessage refsReceived(B_REFS_RECEIVED); if (messageToBundle) { refsReceived = *messageToBundle; refsReceived.what = B_REFS_RECEIVED; } refsReceived.AddRef("refs", ref); if (brokenLinkWithSpecificHandler) // This cruft is to support a hacky workaround for double-clicking // broken refs for cifs; should get fixed in R5 LaunchBrokenLink(brokenLinkPreferredApp.String(), &refsReceived); else TrackerLaunch(&refsReceived, true); } } if (nodeToSelect) SelectChildInParentSoon(ref, nodeToSelect); return B_OK; }
void TTracker::ReadyToRun() { gStatusWindow = new BStatusWindow(); InitMimeTypes(); InstallDefaultTemplates(); InstallIndices(); InstallTemporaryBackgroundImages(); fTrashWatcher = new BTrashWatcher(); fTrashWatcher->Run(); fClipboardRefsWatcher = new BClipboardRefsWatcher(); fClipboardRefsWatcher->Run(); fTaskLoop = new StandAloneTaskLoop(true); // open desktop window BContainerWindow *deskWindow = NULL; BDirectory deskDir; if (FSGetDeskDir(&deskDir) == B_OK) { // create desktop BEntry entry; deskDir.GetEntry(&entry); Model *model = new Model(&entry, true); if (model->InitCheck() == B_OK) { AutoLock<WindowList> lock(&fWindowList); deskWindow = new BDeskWindow(&fWindowList); AutoLock<BWindow> windowLock(deskWindow); deskWindow->CreatePoseView(model); deskWindow->Init(); if (TrackerSettings().ShowDisksIcon()) { // create model for root of everything BEntry entry("/"); Model model(&entry); if (model.InitCheck() == B_OK) { // add the root icon to desktop window BMessage message; message.what = B_NODE_MONITOR; message.AddInt32("opcode", B_ENTRY_CREATED); message.AddInt32("device", model.NodeRef()->device); message.AddInt64("node", model.NodeRef()->node); message.AddInt64("directory", model.EntryRef()->directory); message.AddString("name", model.EntryRef()->name); deskWindow->PostMessage(&message, deskWindow->PoseView()); } } } else delete model; } // kick off building the mime type list for find panels, etc. fMimeTypeList = new MimeTypeList(); if (!BootedInSafeMode()) { // kick of transient query killer DeleteTransientQueriesTask::StartUpTransientQueryCleaner(); // the mount_server will have mounted the previous volumes already. _OpenPreviouslyOpenedWindows(); } }
void OpenWithMenu::DoneBuildingItemList() { // sort by app name fSupportingAppList->SortItems(SortByRelationAndName, this); // check if each app is unique bool isUnique = 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) { isUnique = 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 != NULL) { message->AddData("nodeRefsToClose", B_RAW_TYPE, window->TargetModel()->NodeRef(), sizeof(node_ref)); } BString result; if (isUnique) { // 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) AddSeparatorItem(); 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 != NULL) SetTargetForItems(target); else SetTargetForItems(fMessenger); if (CountItems() == 0) { BMenuItem* item = new BMenuItem(B_TRANSLATE("no supporting apps"), 0); item->SetEnabled(false); AddItem(item); } }
uint32 FSClipboardAddPoses(const node_ref *directory, PoseList *list, uint32 moveMode, bool clearClipboard) { uint32 refsAdded = 0; int32 listCount = list->CountItems(); if (listCount == 0 || !be_clipboard->Lock()) return 0; // update message to be send to all listeners BMessage updateMessage(kFSClipboardChanges); updateMessage.AddInt32("device", directory->device); updateMessage.AddInt64("directory", directory->node); updateMessage.AddBool("clearClipboard", clearClipboard); TClipboardNodeRef clipNode; clipNode.moveMode = moveMode; if (clearClipboard) be_clipboard->Clear(); BMessage *clip = be_clipboard->Data(); if (clip != NULL) { for (int32 index = 0; index < listCount; index++) { char refName[64], modeName[64]; BPose *pose = (BPose *)list->ItemAt(index); Model *model = pose->TargetModel(); const node_ref *node = model->NodeRef(); BEntry entry; model->GetEntry(&entry); if (model->IsVolume() || model->IsRoot() || FSIsTrashDir(&entry) || FSIsDeskDir(&entry)) continue; MakeRefName(refName, node); MakeModeNameFromRefName(modeName, refName); if (clearClipboard) { if (clip->AddInt32(modeName, (int32)moveMode) == B_OK) if (clip->AddRef(refName, model->EntryRef()) == B_OK) { pose->SetClipboardMode(moveMode); clipNode.node = *node; updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode, sizeof(TClipboardNodeRef), true, listCount); refsAdded++; } else clip->RemoveName(modeName); } else { if (clip->ReplaceInt32(modeName, (int32)moveMode) == B_OK) { // replace old mode if entry already exists in clipboard if (clip->ReplaceRef(refName, model->EntryRef()) == B_OK) { pose->SetClipboardMode(moveMode); clipNode.node = *node; updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode, sizeof(TClipboardNodeRef), true, listCount); refsAdded++; } else { clip->RemoveName(modeName); clipNode.node = *node; clipNode.moveMode = kDelete; // note removing node updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode, sizeof(TClipboardNodeRef), true, listCount); clipNode.moveMode = moveMode; // set it back to current value } } else { // add it if it doesn't exist if (clip->AddRef(refName, model->EntryRef()) == B_OK && clip->AddInt32(modeName, (int32)moveMode) == B_OK) { pose->SetClipboardMode(moveMode); clipNode.node = *node; updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode, sizeof(TClipboardNodeRef), true, listCount); refsAdded++; } else { clip->RemoveName(modeName); clip->RemoveName(refName); // here notifying delete isn't needed as node didn't // exist in clipboard } } } } be_clipboard->Commit(); } be_clipboard->Unlock(); BMessenger(kTrackerSignature).SendMessage(&updateMessage); // Tracker will notify all listeners return refsAdded; }
BMenuItem* BRecentItemsList::GetNextMenuItem(const BMessage* fileOpenInvokeMessage, const BMessage* containerOpenInvokeMessage, BHandler* target, entry_ref* currentItemRef) { entry_ref ref; if (GetNextRef(&ref) != B_OK) return NULL; Model model(&ref, true); if (model.InitCheck() != B_OK) return NULL; bool container = false; if (model.IsSymLink()) { Model* newResolvedModel = NULL; Model* result = model.LinkTo(); if (result == NULL) { newResolvedModel = new Model(model.EntryRef(), true, true); if (newResolvedModel->InitCheck() != B_OK) { // broken link, still can show though, bail delete newResolvedModel; result = NULL; } else result = newResolvedModel; } else { BModelOpener opener(result); // open the model, if it ain't open already PoseInfo poseInfo; BNode* resultNode = result->Node(); if (resultNode != NULL) { resultNode->ReadAttr(kAttrPoseInfo, B_RAW_TYPE, 0, &poseInfo, sizeof(poseInfo)); } result->CloseNode(); ref = *result->EntryRef(); container = result->IsContainer(); } model.SetLinkTo(result); } else { ref = *model.EntryRef(); container = model.IsContainer(); } // if user asked for it, return the current item ref if (currentItemRef != NULL) *currentItemRef = ref; BMessage* message; if (container && containerOpenInvokeMessage) message = new BMessage(*containerOpenInvokeMessage); else if (!container && fileOpenInvokeMessage) message = new BMessage(*fileOpenInvokeMessage); else message = new BMessage(B_REFS_RECEIVED); message->AddRef("refs", model.EntryRef()); // Truncate the name if necessary BString truncatedString(model.Name()); be_plain_font->TruncateString(&truncatedString, B_TRUNCATE_END, BNavMenu::GetMaxMenuWidth()); ModelMenuItem* item = NULL; if (!container || !fNavMenuFolders) item = new ModelMenuItem(&model, truncatedString.String(), message); else { // add another nav menu item if it's a directory BNavMenu* menu = new BNavMenu(truncatedString.String(), message->what, target, 0); menu->SetNavDir(&ref); item = new ModelMenuItem(&model, menu); item->SetMessage(message); } if (item != NULL && target != NULL) item->SetTarget(target); return item; }
ModelMenuItem * BNavMenu::NewModelItem(Model *model, const BMessage *invokeMessage, const BMessenger &target, bool suppressFolderHierarchy, BContainerWindow *parentWindow, const BObjectList<BString> *typeslist, TrackingHookData *hook) { if (model->InitCheck() != B_OK) return 0; entry_ref ref; bool container = false; if (model->IsSymLink()) { Model *newResolvedModel = 0; Model *result = model->LinkTo(); if (!result) { newResolvedModel = new Model(model->EntryRef(), true, true); if (newResolvedModel->InitCheck() != B_OK) { // broken link, still can show though, bail delete newResolvedModel; result = 0; } else result = newResolvedModel; } if (result) { BModelOpener opener(result); // open the model, if it ain't open already PoseInfo poseInfo; ssize_t size = -1; if (result->Node()) size = result->Node()->ReadAttr(kAttrPoseInfo, B_RAW_TYPE, 0, &poseInfo, sizeof(poseInfo)); result->CloseNode(); if (size == sizeof(poseInfo) && !BPoseView::PoseVisible(result, &poseInfo, false)) { // link target sez it doesn't want to be visible, // don't show the link PRINT(("not showing hidden item %s\n", model->Name())); delete newResolvedModel; return 0; } ref = *result->EntryRef(); container = result->IsContainer(); } model->SetLinkTo(result); } else { ref = *model->EntryRef(); container = model->IsContainer(); } BMessage *message = new BMessage(*invokeMessage); message->AddRef("refs", model->EntryRef()); // Truncate the name if necessary BString truncatedString; TruncString(be_plain_font, model->Name(), truncatedString, GetMaxMenuWidth()); ModelMenuItem *item = NULL; if (!container || suppressFolderHierarchy) { item = new ModelMenuItem(model, truncatedString.String(), message); if (invokeMessage->what != B_REFS_RECEIVED) item->SetEnabled(false); // the above is broken for FavoritesMenu::AddNextItem, which uses a // workaround - should fix this } else { BNavMenu *menu = new BNavMenu(truncatedString.String(), invokeMessage->what, target, parentWindow, typeslist); menu->SetNavDir(&ref); if (hook) menu->InitTrackingHook(hook->fTrackingHook, &(hook->fTarget), hook->fDragMessage); item = new ModelMenuItem(model, menu); item->SetMessage(message); } return item; }
TTracker::TTracker() : BApplication(kTrackerSignature), fMimeTypeList(NULL), fClipboardRefsWatcher(NULL), fTrashWatcher(NULL), fTaskLoop(NULL), fNodeMonitorCount(-1), fWatchingInterface(new WatchingInterface), fSettingsWindow(NULL) { BPathMonitor::SetWatchingInterface(fWatchingInterface); // set the cwd to /boot/home, anything that's launched // from Tracker will automatically inherit this BPath homePath; if (find_directory(B_USER_DIRECTORY, &homePath) == B_OK) chdir(homePath.Path()); // ask for a bunch more file descriptors so that nested copying works well struct rlimit rl; rl.rlim_cur = 512; rl.rlim_max = RLIM_SAVED_MAX; setrlimit(RLIMIT_NOFILE, &rl); fNodeMonitorCount = DEFAULT_MON_NUM; gLocalizedNamePreferred = BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); #ifdef CHECK_OPEN_MODEL_LEAKS InitOpenModelDumping(); #endif InitIconPreloader(); #ifdef LEAK_CHECKING SetNewLeakChecking(true); SetMallocLeakChecking(true); #endif // This is how often it should update the free space bar on the // volume icons SetPulseRate(1000000); gLaunchLooper = new LaunchLooper(); gLaunchLooper->Run(); // open desktop window BContainerWindow* deskWindow = NULL; BDirectory deskDir; if (FSGetDeskDir(&deskDir) == B_OK) { // create desktop BEntry entry; deskDir.GetEntry(&entry); Model* model = new Model(&entry, true); if (model->InitCheck() == B_OK) { AutoLock<WindowList> lock(&fWindowList); deskWindow = new BDeskWindow(&fWindowList); AutoLock<BWindow> windowLock(deskWindow); deskWindow->CreatePoseView(model); deskWindow->Init(); if (TrackerSettings().ShowDisksIcon()) { // create model for root of everything BEntry entry("/"); Model model(&entry); if (model.InitCheck() == B_OK) { // add the root icon to desktop window BMessage message; message.what = B_NODE_MONITOR; message.AddInt32("opcode", B_ENTRY_CREATED); message.AddInt32("device", model.NodeRef()->device); message.AddInt64("node", model.NodeRef()->node); message.AddInt64("directory", model.EntryRef()->directory); message.AddString("name", model.EntryRef()->name); deskWindow->PostMessage(&message, deskWindow->PoseView()); } } } else delete model; } }