bool BNavMenu::StartBuildingItemList() { BEntry entry; if (fNavDir.device < 0 || entry.SetTo(&fNavDir) != B_OK || !entry.Exists()) return false; fItemList = new BObjectList<BMenuItem>(50); fIteratingDesktop = false; BDirectory parent; status_t status = entry.GetParent(&parent); // if ref is the root item then build list of volume root dirs fFlags = uint8((fFlags & ~kVolumesOnly) | (status == B_ENTRY_NOT_FOUND ? kVolumesOnly : 0)); if (fFlags & kVolumesOnly) return true; Model startModel(&entry, true); if (startModel.InitCheck() != B_OK || !startModel.IsContainer()) return false; if (startModel.IsQuery()) fContainer = new QueryEntryListCollection(&startModel); else if (FSIsDeskDir(&entry)) { fIteratingDesktop = true; fContainer = DesktopPoseView::InitDesktopDirentIterator(0, startModel.EntryRef()); AddRootItemsIfNeeded(); } else if (FSIsTrashDir(&entry)) { // the trash window needs to display a union of all the // trash folders from all the mounted volumes BVolumeRoster volRoster; volRoster.Rewind(); BVolume volume; fContainer = new EntryIteratorList(); while (volRoster.GetNextVolume(&volume) == B_OK) { if (!volume.IsPersistent()) continue; BDirectory trashDir; if (FSGetTrashDir(&trashDir, volume.Device()) == B_OK) dynamic_cast<EntryIteratorList *>(fContainer)-> AddItem(new DirectoryEntryList(trashDir)); } } else fContainer = new DirectoryEntryList(*dynamic_cast<BDirectory *> (startModel.Node())); if (fContainer == NULL || fContainer->InitCheck() != B_OK) return false; fContainer->Rewind(); return true; }
void Model::FinishSettingUpType() { char mimeString[B_MIME_TYPE_LENGTH]; BEntry entry; // while we are reading the node, do a little // snooping to see if it even makes sense to look for a node-based // icon // This serves as a hint to the icon cache, allowing it to not hit the // disk again for models that do not have an icon defined by the node if (IsNodeOpen() && fBaseType != kLinkNode && !CheckNodeIconHintPrivate(fNode, dynamic_cast<TTracker *>(be_app) == NULL) && !HasVectorIconHint(fNode)) { // when checking for the node icon hint, if we are libtracker, only check // for small icons - checking for the large icons is a little more // work for the filesystem and this will speed up the test. // This makes node icons only work if there is a small and a large node // icon on a file - for libtracker that is not a problem though fIconFrom = kUnknownNotFromNode; } if (fBaseType != kDirectoryNode && fBaseType != kVolumeNode && fBaseType != kLinkNode && IsNodeOpen()) { BNodeInfo info(fNode); // check if a specific mime type is set if (info.GetType(mimeString) == B_OK) { // node has a specific mime type fMimeType = mimeString; if (strcmp(mimeString, B_QUERY_MIMETYPE) == 0) fBaseType = kQueryNode; else if (strcmp(mimeString, B_QUERY_TEMPLATE_MIMETYPE) == 0) fBaseType = kQueryTemplateNode; if (info.GetPreferredApp(mimeString) == B_OK) { if (fPreferredAppName) DeletePreferredAppVolumeNameLinkTo(); if (mimeString[0]) fPreferredAppName = strdup(mimeString); } } } switch (fBaseType) { case kDirectoryNode: entry.SetTo(&fEntryRef); if (entry.InitCheck() == B_OK) { if (FSIsTrashDir(&entry)) fBaseType = kTrashNode; else if (FSIsDeskDir(&entry)) fBaseType = kDesktopNode; } fMimeType = B_DIR_MIMETYPE; // should use a shared string here if (IsNodeOpen()) { BNodeInfo info(fNode); if (info.GetType(mimeString) == B_OK) fMimeType = mimeString; if (fIconFrom == kUnknownNotFromNode && WellKnowEntryList::Match(NodeRef()) > (directory_which)-1) // one of home, beos, system, boot, etc. fIconFrom = kTrackerSupplied; } break; case kVolumeNode: { if (NodeRef()->node == fEntryRef.directory && NodeRef()->device == fEntryRef.device) { // promote from volume to file system root fBaseType = kRootNode; fMimeType = B_ROOT_MIMETYPE; break; } // volumes have to have a B_VOLUME_MIMETYPE type fMimeType = B_VOLUME_MIMETYPE; if (fIconFrom == kUnknownNotFromNode) { if (WellKnowEntryList::Match(NodeRef()) > (directory_which)-1) fIconFrom = kTrackerSupplied; else fIconFrom = kVolume; } char name[B_FILE_NAME_LENGTH]; BVolume volume(NodeRef()->device); if (volume.InitCheck() == B_OK && volume.GetName(name) == B_OK) { if (fVolumeName) DeletePreferredAppVolumeNameLinkTo(); fVolumeName = strdup(name); } #if DEBUG else PRINT(("get volume name failed for %s\n", fEntryRef.name)); #endif break; } case kLinkNode: fMimeType = B_LINK_MIMETYPE; // should use a shared string here break; case kExecutableNode: if (IsNodeOpen()) { char signature[B_MIME_TYPE_LENGTH]; if (GetAppSignatureFromAttr(dynamic_cast<BFile *>(fNode), signature) == B_OK) { if (fPreferredAppName) DeletePreferredAppVolumeNameLinkTo(); if (signature[0]) fPreferredAppName = strdup(signature); } } if (!fMimeType.Length()) fMimeType = B_APP_MIME_TYPE; // should use a shared string here break; default: if (!fMimeType.Length()) fMimeType = B_FILE_MIMETYPE; break; } }
bool FSClipboardPaste(Model *model, uint32 linksMode) { if (!FSClipboardHasRefs()) return false; BMessenger tracker(kTrackerSignature); node_ref *destNodeRef = (node_ref *)model->NodeRef(); // these will be passed to the asynchronous copy/move process BObjectList<entry_ref> *moveList = new BObjectList<entry_ref>(0, true); BObjectList<entry_ref> *copyList = new BObjectList<entry_ref>(0, true); if ((be_clipboard->Lock())) { BMessage *clip = be_clipboard->Data(); if (clip != NULL) { char modeName[64]; uint32 moveMode = 0; BMessage *updateMessage = NULL; node_ref updateNodeRef; updateNodeRef.device = -1; char *refName; type_code type; int32 count; for (int32 index = 0; clip->GetInfo(B_REF_TYPE, index, #ifdef B_BEOS_VERSION_DANO (const char **) #endif &refName, &type, &count) == B_OK; index++) { entry_ref ref; if (clip->FindRef(refName, &ref) != B_OK) continue; // If the entry_ref's directory has changed, send previous notification // (if any), and start new one for the new directory if (updateNodeRef.device != ref.device || updateNodeRef.node != ref.directory) { if (updateMessage != NULL) { tracker.SendMessage(updateMessage); delete updateMessage; } updateNodeRef.device = ref.device; updateNodeRef.node = ref.directory; updateMessage = new BMessage(kFSClipboardChanges); updateMessage->AddInt32("device", updateNodeRef.device); updateMessage->AddInt64("directory", updateNodeRef.node); } // we need this data later on MakeModeNameFromRefName(modeName, refName); if (!linksMode && clip->FindInt32(modeName, (int32 *)&moveMode) != B_OK) continue; BEntry entry(&ref); uint32 newMoveMode = 0; bool sameDirectory = destNodeRef->device == ref.device && destNodeRef->node == ref.directory; if (!entry.Exists()) { // The entry doesn't exist anymore, so we'll remove // that entry from the clipboard as well clip->RemoveName(refName); clip->RemoveName(modeName); newMoveMode = kDelete; } else { // the entry does exist, so lets see what we will // do with it if (!sameDirectory) { if (linksMode || moveMode == kMoveSelectionTo) { // the linksMode uses the moveList as well moveList->AddItem(new entry_ref(ref)); } else if (moveMode == kCopySelectionTo) copyList->AddItem(new entry_ref(ref)); } // if the entry should have been removed from its directory, // we want to copy that entry next time, no matter if the // items don't have to be moved at all (source == target) if (moveMode == kMoveSelectionTo) newMoveMode = kCopySelectionTo; } // add the change to the update message (if necessary) if (newMoveMode) { clip->ReplaceInt32(modeName, kCopySelectionTo); TClipboardNodeRef clipNode; MakeNodeFromName(&clipNode.node, modeName); clipNode.moveMode = kDelete; updateMessage->AddData("tcnode", T_CLIPBOARD_NODE, &clipNode, sizeof(TClipboardNodeRef), true); } } be_clipboard->Commit(); // send notification for the last directory if (updateMessage != NULL) { tracker.SendMessage(updateMessage); delete updateMessage; } } be_clipboard->Unlock(); } bool okToMove = true; // can't copy/paste to root('/') directory if (model->IsRoot()) { (new BAlert("", kNoCopyToRootStr, "Cancel", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); okToMove = false; } BEntry entry; model->GetEntry(&entry); // can't copy items into the trash if (copyList->CountItems() > 0 && FSIsTrashDir(&entry)) { (new BAlert("", kNoCopyToTrashStr, "Cancel", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); okToMove = false; } if (!okToMove) { // there was some problem with our target, so we bail out here delete moveList; delete copyList; return false; } // asynchronous calls take over ownership of the objects passed to it if (moveList->CountItems() > 0) FSMoveToFolder(moveList, new BEntry(entry), linksMode ? linksMode : kMoveSelectionTo); else delete moveList; if (copyList->CountItems() > 0) FSMoveToFolder(copyList, new BEntry(entry), kCopySelectionTo); else delete copyList; return true; }
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; }