void BDirMenu::AddItemToDirMenu(const BEntry* entry, BWindow* originatingWindow, bool atEnd, bool addShortcuts, bool navMenuEntries) { Model model(entry); if (model.InitCheck() != B_OK) return; BMessage* message = new BMessage(fCommand); message->AddRef(fEntryName.String(), model.EntryRef()); // add reference to the container windows model so that we can // close the window if BContainerWindow* window = originatingWindow ? dynamic_cast<BContainerWindow*>(originatingWindow) : 0; if (window) message->AddData("nodeRefsToClose", B_RAW_TYPE, window->TargetModel()->NodeRef(), sizeof (node_ref)); ModelMenuItem* item; if (navMenuEntries) { BNavMenu* subMenu = new BNavMenu(model.Name(), B_REFS_RECEIVED, fTarget, window); entry_ref ref; entry->GetRef(&ref); subMenu->SetNavDir(&ref); item = new ModelMenuItem(&model, subMenu); item->SetLabel(model.Name()); item->SetMessage(message); } else { item = new ModelMenuItem(&model, model.Name(), message); } if (addShortcuts) { if (model.IsDesktop()) item->SetShortcut('D', B_COMMAND_KEY); else if (FSIsHomeDir(entry)) item->SetShortcut('H', B_COMMAND_KEY); } if (atEnd) AddItem(item); else AddItem(item, 0); item->SetTarget(fTarget); if (fMenuBar) { ModelMenuItem* menu = dynamic_cast<ModelMenuItem*>(fMenuBar->ItemAt(0)); if (menu) { ThrowOnError(menu->SetEntry(entry)); item->SetMarked(true); } } }
void TFilePanel::SwitchDirMenuTo(const entry_ref* ref) { BEntry entry(ref); for (int32 index = fDirMenu->CountItems() - 1; index >= 0; index--) delete fDirMenu->RemoveItem(index); fDirMenuField->MenuBar()->RemoveItem((int32)0); fDirMenu->Populate(&entry, 0, true, true, false, true); ModelMenuItem* item = dynamic_cast<ModelMenuItem*>( fDirMenuField->MenuBar()->ItemAt(0)); ASSERT(item != NULL); if (item != NULL) item->SetEntry(&entry); }
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 BNavMenu::AddNavDir(const Model *model, uint32 what, BHandler *target, bool populateSubmenu) { BMessage *message = new BMessage((uint32)what); message->AddRef("refs", model->EntryRef()); ModelMenuItem *item = NULL; if (populateSubmenu) { BNavMenu *navMenu = new BNavMenu(model->Name(), what, target); navMenu->SetNavDir(model->EntryRef()); navMenu->InitTrackingHook(fTrackingHook.fTrackingHook, &(fTrackingHook.fTarget), fTrackingHook.fDragMessage); item = new ModelMenuItem(model, navMenu); item->SetMessage(message); } else item = new ModelMenuItem(model, model->Name(), message); AddItem(item); }
void SpringLoadedFolderSetMenuStates(const BMenu* menu, const BObjectList<BString>* typeslist) { if (!menu || !typeslist || typeslist->IsEmpty()) return; // if a types list exists // iterate through the list and see if each item // can support any item in the list // set the enabled state of the item int32 count = menu->CountItems(); for (int32 index = 0 ; index < count ; index++) { ModelMenuItem* item = dynamic_cast<ModelMenuItem*>(menu->ItemAt(index)); if (!item) continue; const Model* model = item->TargetModel(); if (!model) continue; if (model->IsSymLink()) { // find out what the model is, resolve if symlink BEntry entry(model->EntryRef(), true); if (entry.InitCheck() == B_OK) { if (entry.IsDirectory()) { // folder? always keep enabled item->SetEnabled(true); } else { // other, check its support Model resolvedModel(&entry); int32 supported = resolvedModel.SupportsMimeType(NULL, typeslist); item->SetEnabled(supported != kDoesNotSupportType); } } else // bad entry ref (bad symlink?), disable item->SetEnabled(false); } else if (model->IsDirectory() || model->IsRoot() || model->IsVolume()) // always enabled if a container item->SetEnabled(true); else if (model->IsFile() || model->IsExecutable()) { int32 supported = model->SupportsMimeType(NULL, typeslist); item->SetEnabled(supported != kDoesNotSupportType); } else item->SetEnabled(false); } }
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; }
void BDirMenu::Populate(const BEntry* startEntry, BWindow* originatingWindow, bool includeStartEntry, bool select, bool reverse, bool addShortcuts, bool navMenuEntries) { try { if (!startEntry) throw (status_t)B_ERROR; Model model(startEntry); ThrowOnInitCheckError(&model); ModelMenuItem* menu = new ModelMenuItem(&model, this, true, true); if (fMenuBar) fMenuBar->AddItem(menu); BEntry entry(*startEntry); bool showDesktop, showDisksIcon; { TrackerSettings settings; showDesktop = settings.DesktopFilePanelRoot(); showDisksIcon = settings.ShowDisksIcon(); } // might start one level above startEntry if (!includeStartEntry) { BDirectory parent; BDirectory dir(&entry); if (!showDesktop && dir.InitCheck() == B_OK && dir.IsRootDirectory()) { // if we're at the root directory skip "mnt" and // go straight to "/" parent.SetTo("/"); } else entry.GetParent(&parent); parent.GetEntry(&entry); } BDirectory desktopDir; FSGetDeskDir(&desktopDir); BEntry desktopEntry; desktopDir.GetEntry(&desktopEntry); for (;;) { BNode node(&entry); ThrowOnInitCheckError(&node); PoseInfo info; ReadAttrResult result = ReadAttr(&node, kAttrPoseInfo, kAttrPoseInfoForeign, B_RAW_TYPE, 0, &info, sizeof(PoseInfo), &PoseInfo::EndianSwap); BDirectory parent; entry.GetParent(&parent); bool hitRoot = false; BDirectory dir(&entry); if (!showDesktop && dir.InitCheck() == B_OK && dir.IsRootDirectory()) { // if we're at the root directory skip "mnt" and // go straight to "/" hitRoot = true; parent.SetTo("/"); } if (showDesktop) { BEntry root("/"); // warp from "/" to Desktop properly if (entry == root) { if (showDisksIcon) AddDisksIconToMenu(reverse); entry = desktopEntry; } if (entry == desktopEntry) hitRoot = true; } if (result == kReadAttrFailed || !info.fInvisible || (showDesktop && desktopEntry == entry)) { AddItemToDirMenu(&entry, originatingWindow, reverse, addShortcuts, navMenuEntries); } if (hitRoot) { if (!showDesktop && showDisksIcon && *startEntry != "/") AddDisksIconToMenu(reverse); break; } parent.GetEntry(&entry); } // select last item in menu if (!select) return; ModelMenuItem* item = dynamic_cast<ModelMenuItem*>(ItemAt(CountItems() - 1)); if (item) { item->SetMarked(true); if (menu) { entry.SetTo(item->TargetModel()->EntryRef()); ThrowOnError(menu->SetEntry(&entry)); } } } catch (status_t err) { PRINT(("BDirMenu::Populate: caught error %s\n", strerror(err))); if (!CountItems()) { BString error; error << "Error [" << strerror(err) << "] populating menu"; AddItem(new BMenuItem(error.String(), 0)); } } }
bool TRecentsMenu::AddRecents(int32 count) { if (fItemIndex == 0) { fRecentList.MakeEmpty(); BRoster roster; switch (fWhich) { case kRecentDocuments: roster.GetRecentDocuments(&fRecentList, count); break; case kRecentApplications: roster.GetRecentApps(&fRecentList, count); break; case kRecentAppDocuments: roster.GetRecentDocuments(&fRecentList, count, NULL, fSignature); break; case kRecentFolders: roster.GetRecentFolders(&fRecentList, count); break; default: return false; } } for (;;) { entry_ref ref; if (fRecentList.FindRef("refs", fItemIndex++, &ref) != B_OK) break; if (ref.name && strlen(ref.name) > 0) { Model model(&ref, true); if (fWhich != kRecentApplications) { BMessage* message = new BMessage(B_REFS_RECEIVED); if (fWhich == kRecentAppDocuments) { // add application as handler message->AddRef("handler", fAppRef); } ModelMenuItem* item = BNavMenu::NewModelItem(&model, message, Target(), false, NULL, TypesList()); if (item) AddItem(item); } else { // The application items expand to a list of recent documents // for that application - so they must be handled extra BFile file(&ref, B_READ_ONLY); char signature[B_MIME_TYPE_LENGTH]; BAppFileInfo appInfo(&file); if (appInfo.InitCheck() != B_OK || appInfo.GetSignature(signature) != B_OK) continue; ModelMenuItem* item = NULL; BMessage doc; be_roster->GetRecentDocuments(&doc, 1, NULL, signature); // ToDo: check if the documents do exist at all to // avoid the creation of the submenu. if (doc.CountNames(B_REF_TYPE) > 0) { // create recents menu that will contain the recent docs of // this app TRecentsMenu* docs = new TRecentsMenu(model.Name(), fBarView, kRecentAppDocuments, signature, &ref); docs->SetTypesList(TypesList()); docs->SetTarget(Target()); item = new ModelMenuItem(&model, docs); } else item = new ModelMenuItem(&model, model.Name(), NULL); if (item) { // add refs-message so that the recent app can be launched BMessage* msg = new BMessage(B_REFS_RECEIVED); msg->AddRef("refs", &ref); item->SetMessage(msg); item->SetTarget(Target()); AddItem(item); } } // return true so that we know to reenter this list return true; } } // return false if we are done with this list return false; }
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); } }
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; }