Tracker: Check selection parent is read-only on query

If 0 items are selected, check the window's volume instead.

If 1 item is selected, check if the parent's volume is read-only.

If multiple items are selected, consider the entire selection to
be read-only if any item's parent directory in the selection is
on a read-only volume.

You aren't allowed to for example Cut a selection that has an
item on a read-only volume as the Cut operation would not be able
to succeed. However, if all items in the selection are not on a
read-only volume then you may Cut.

For non-query windows assume all selected item's are on the same
volume and only check the first item when multiple are selected.

Fixes #18661

Change-Id: Ib898e54b62558c66aad65d33afd080480e312565
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7120
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Reviewed-by: John Scipione <jscipione@gmail.com>
This commit is contained in:
John Scipione 2023-11-22 14:40:53 -05:00 committed by waddlesplash
parent 8497e56650
commit 501aa0f311
3 changed files with 37 additions and 9 deletions

View File

@ -1864,7 +1864,7 @@ BContainerWindow::SetCutItem(BMenu* menu)
item->SetEnabled(false);
} else {
item->SetEnabled(PoseView()->CountSelected() > 0
&& !PoseView()->TargetVolumeIsReadOnly());
&& !PoseView()->SelectedVolumeIsReadOnly());
}
}
@ -2710,7 +2710,7 @@ BContainerWindow::SetupMoveCopyMenus(const entry_ref* item_ref, BMenu* parent)
}
fMoveToItem->SetEnabled(PoseView()->CountSelected() > 0
&& !PoseView()->TargetVolumeIsReadOnly());
&& !PoseView()->SelectedVolumeIsReadOnly());
fCopyToItem->SetEnabled(PoseView()->CountSelected() > 0);
fCreateLinkItem->SetEnabled(PoseView()->CountSelected() > 0);
@ -2758,7 +2758,7 @@ BContainerWindow::ShowDropContextMenu(BPoint where, BPoseView* source)
break;
if (item->Command() == kMoveSelectionTo && source != NULL) {
item->SetEnabled(!source->TargetVolumeIsReadOnly()
item->SetEnabled(!source->SelectedVolumeIsReadOnly()
&& !PoseView()->TargetVolumeIsReadOnly());
} else
item->SetEnabled(!PoseView()->TargetVolumeIsReadOnly());

View File

@ -8865,9 +8865,38 @@ bool
BPoseView::SelectedVolumeIsReadOnly() const
{
BVolume volume;
BPose* firstPose = fSelectionList->FirstItem();
if (firstPose != NULL)
volume.SetTo(firstPose->TargetModel()->NodeRef()->device);
BEntry entry;
BNode parent;
node_ref nref;
int32 selectCount = fSelectionList->CountItems();
if (selectCount > 1 && TargetModel()->IsQuery()) {
// multiple items selected in query, consider the whole selection
// to be read-only if any item's volume is read-only
for (int32 i = 0; i < selectCount; i++) {
BPose* pose = fSelectionList->ItemAt(i);
if (pose == NULL || pose->TargetModel() == NULL)
continue;
entry.SetTo(pose->TargetModel()->EntryRef());
if (FSGetParentVirtualDirectoryAware(entry, parent) == B_OK) {
parent.GetNodeRef(&nref);
volume.SetTo(nref.device);
if (volume.InitCheck() == B_OK && volume.IsReadOnly())
return true;
}
}
} else if (selectCount > 0) {
// only check first item's volume, assume rest are the same
entry.SetTo(fSelectionList->FirstItem()->TargetModel()->EntryRef());
if (FSGetParentVirtualDirectoryAware(entry, parent) == B_OK) {
parent.GetNodeRef(&nref);
volume.SetTo(nref.device);
}
} else {
// no items selected, check target volume instead
volume.SetTo(TargetModel()->NodeRef()->device);
}
return volume.InitCheck() == B_OK && volume.IsReadOnly();
}
@ -8877,8 +8906,7 @@ bool
BPoseView::TargetVolumeIsReadOnly() const
{
Model* target = TargetModel();
BVolume volume;
volume.SetTo(target->NodeRef()->device);
BVolume volume(target->NodeRef()->device);
return target->IsQuery() || target->IsQueryTemplate()
|| target->IsVirtualDirectory()

View File

@ -456,7 +456,7 @@ BTextWidget::StartEdit(BRect bounds, BPoseView* view, BPose* pose)
textView->AddFilter(new BMessageFilter(B_KEY_DOWN, TextViewKeyDownFilter));
if (view->TargetVolumeIsReadOnly()) {
if (view->SelectedVolumeIsReadOnly()) {
textView->MakeEditable(false);
textView->MakeSelectable(true);
} else