Tracker: Cancel type-ahead filtering on esc

Otherwise esc closes the file panel.

Differentiate between type-ahead and ref filtering in pose view
which is why this was not working in e.g. Expander a ref filter
was set so filtering was also set. We only want to cancel
type-ahead filtering on esc, not ref filtering.

Refer to 'ref filtering' as simply filtering e.g. IsFiltering()
and refer to type-ahead filtering explicity when that is meant.
Rename methods and variables to make it clear whether we're
referring to ref filtering or type-ahead filtering.

If we are ref filtering fill out the filtered pose list again
after stopping type-ahead filtering so that we don't get an empty
file panel in e.g. Expander on esc.

Fixes #13151

Change-Id: I96faf98c3b68d3bcb3d3892c3511ae2449c2f8a4
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8689
Reviewed-by: waddlesplash <[email protected]>
Haiku-Format: Haiku-format Bot <[email protected]>
This commit is contained in:
John Scipione
2024-12-18 18:55:05 +00:00
committed by waddlesplash
parent c95edc2ba1
commit 10b1abbfde
3 changed files with 106 additions and 108 deletions
+1 -1
View File
@@ -150,7 +150,7 @@ key_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter)
if (modifiers == 0 && key == B_ESCAPE) {
if (view->ActivePose() != NULL)
view->CommitActivePose(false);
else if (view->IsFiltering())
else if (view->IsTypeAheadFiltering())
looper->PostMessage(B_CANCEL, *handler);
else
looper->PostMessage(kCancelButton);
+94 -99
View File
@@ -269,7 +269,7 @@ BPoseView::BPoseView(Model* model, uint32 viewMode)
fIsWatchingDateFormatChange(false),
fHasPosesInClipboard(false),
fCursorCheck(false),
fFiltering(false),
fTypeAheadFiltering(false),
fFilterStrings(4, true),
fLastFilterStringCount(1),
fLastFilterStringLength(0),
@@ -1152,7 +1152,7 @@ BPoseView::CommitActivePose(bool saveChanges)
BPose* activePose = ActivePose();
if (activePose != NULL) {
int32 index = fPoseList->IndexOf(ActivePose());
if (fFiltering)
if (IsFiltering())
index = fFilteredPoseList->IndexOf(ActivePose());
BPoint loc(0, index * fListElemHeight);
@@ -1162,7 +1162,7 @@ BPoseView::CommitActivePose(bool saveChanges)
activePose->Commit(saveChanges, loc, this, index);
BPose* pose = fActivePose;
fActivePose = NULL;
if (fFiltering && !FilterPose(pose))
if (IsFiltering() && !FilterPose(pose))
RemoveFilteredPose(pose, index);
}
}
@@ -1951,10 +1951,10 @@ BPoseView::CreatePoses(Model** models, PoseInfo* poseInfoArray, int32 count,
switch (ViewMode()) {
case kListMode:
{
AddPoseToList(fPoseList, !fFiltering, insertionSort, pose,
viewBounds, listViewScrollBy, forceDraw, &poseIndex);
AddPoseToList(fPoseList, !IsFiltering(), insertionSort, pose, viewBounds,
listViewScrollBy, forceDraw, &poseIndex);
if (fFiltering && FilterPose(pose)) {
if (IsFiltering() && FilterPose(pose)) {
AddPoseToList(fFilteredPoseList, true, insertionSort, pose,
viewBounds, listViewScrollBy, forceDraw, &poseIndex);
}
@@ -2040,14 +2040,13 @@ BPoseView::ShouldShowPose(const Model* model, const PoseInfo* poseInfo)
return false;
// check filter before adding item
if (!fRefFilter)
if (!IsFiltering())
return true;
struct stat_beos stat;
convert_to_stat_beos(model->StatBuf(), &stat);
return fRefFilter->Filter(model->EntryRef(), model->Node(), &stat,
model->MimeType());
return fRefFilter->Filter(model->EntryRef(), model->Node(), &stat, model->MimeType());
}
@@ -2335,8 +2334,8 @@ BPoseView::MessageReceived(BMessage* message)
case B_CANCEL:
if (FSClipboardHasRefs())
FSClipboardClear();
else if (fFiltering)
StopFiltering();
if (IsTypeAheadFiltering())
StopTypeAheadFiltering();
break;
case kCancelSelectionToClipboard:
@@ -2448,8 +2447,7 @@ BPoseView::MessageReceived(BMessage* message)
BPose* pose = fSelectionList->FirstItem();
if (pose != NULL) {
BPoint where(0,
CurrentPoseList()->IndexOf(pose) * fListElemHeight);
BPoint where(0, CurrentPoseList()->IndexOf(pose) * fListElemHeight);
pose->EditFirstWidget(where, this);
}
break;
@@ -2678,14 +2676,12 @@ BPoseView::MessageReceived(BMessage* message)
case kTypeAheadFilteringChanged:
{
TrackerSettings settings;
bool typeAheadFiltering;
if (message->FindBool("TypeAheadFiltering",
&typeAheadFiltering) == B_OK) {
settings.SetTypeAheadFiltering(typeAheadFiltering);
bool typeAheadFilter;
if (message->FindBool("TypeAheadFiltering", &typeAheadFilter) == B_OK) {
settings.SetTypeAheadFiltering(typeAheadFilter);
if (IsTypeAheadFiltering() && !typeAheadFilter)
StopTypeAheadFiltering();
}
if (fFiltering && !typeAheadFiltering)
StopFiltering();
break;
}
}
@@ -2762,13 +2758,13 @@ BPoseView::RemoveColumn(BColumn* columnToRemove, bool runAlert)
fStateNeedsSaving = true;
if (fFiltering) {
if (IsFiltering()) {
// the column we removed might just be the one that was used to filter
int32 poseCount = fFilteredPoseList->CountItems();
for (int32 i = poseCount - 1; i >= 0; i--) {
BPose* pose = fFilteredPoseList->ItemAt(i);
for (int32 index = poseCount - 1; index >= 0; index--) {
BPose* pose = fFilteredPoseList->ItemAt(index);
if (!FilterPose(pose))
RemoveFilteredPose(pose, i);
RemoveFilteredPose(pose, index);
}
}
@@ -2839,11 +2835,9 @@ BPoseView::AddColumn(BColumn* newColumn, const BColumn* after)
fStateNeedsSaving = true;
if (fFiltering) {
if (IsFiltering()) {
// the column we added might just add new poses to be showed
fFilteredPoseList->MakeEmpty();
fFiltering = false;
StartFiltering();
RebuildFilteringPoseList();
}
return true;
@@ -3084,8 +3078,8 @@ BPoseView::SetViewMode(uint32 newMode)
// toggle view layout between listmode and non-listmode, if necessary
BContainerWindow* window = ContainerWindow();
if (oldMode == kListMode) {
if (fFiltering)
ClearFilter();
if (IsTypeAheadFiltering())
ClearTypeAheadFiltering();
if (window != NULL)
window->HideAttributesMenu();
@@ -3289,7 +3283,7 @@ BPoseView::UpdatePosesClipboardModeFromClipboard(BMessage* clipboardReport)
if (!fullInvalidateNeeded) {
if (ViewMode() == kListMode) {
if (fFiltering)
if (IsFiltering())
pose = fFilteredPoseList->FindPose(&clipNode->node, &foundNodeIndex);
if (pose != NULL) {
@@ -3447,7 +3441,7 @@ BPoseView::NewFolder(const BMessage* message)
BPose* pose = EntryCreated(targetModel->NodeRef(), &nodeRef, ref.name,
&index);
if (fFiltering) {
if (IsFiltering()) {
if (fFilteredPoseList->FindPose(&nodeRef, &index) == NULL) {
float scrollBy = 0;
BRect bounds = Bounds();
@@ -5659,7 +5653,7 @@ BPoseView::EntryMoved(const BMessage* message)
BPose* pose = fPoseList->FindPose(&itemNode, &index);
int32 poseListIndex = index;
bool visible = true;
if (fFiltering)
if (IsFiltering())
visible = fFilteredPoseList->FindPose(&itemNode, &index) != NULL;
if (pose != NULL) {
@@ -5683,7 +5677,7 @@ BPoseView::EntryMoved(const BMessage* message)
pose->UpdateAllWidgets(index, loc, this);
poseModel->CloseNode();
_CheckPoseSortOrder(fPoseList, pose, poseListIndex);
if (fFiltering) {
if (IsFiltering()) {
if (!visible && FilterPose(pose)) {
BRect bounds = Bounds();
float scrollBy = 0;
@@ -5854,7 +5848,7 @@ BPoseView::AttributeChanged(const BMessage* message)
&index) != NULL;
int32 poseListIndex = index;
if (fFiltering)
if (IsFiltering())
visible = fFilteredPoseList->FindPose(poseModel->NodeRef(), &index) != NULL;
BPoint loc(0, index * fListElemHeight);
@@ -5871,7 +5865,7 @@ BPoseView::AttributeChanged(const BMessage* message)
visible);
}
poseModel->CloseNode();
if (fFiltering) {
if (IsFiltering()) {
if (!visible && FilterPose(pose)) {
visible = true;
float scrollBy = 0;
@@ -5890,7 +5884,7 @@ BPoseView::AttributeChanged(const BMessage* message)
uint32 attrHash = AttrHashString(attrName, info.type);
if (attrHash == PrimarySort() || attrHash == SecondarySort()) {
_CheckPoseSortOrder(fPoseList, pose, poseListIndex);
if (fFiltering && visible)
if (IsFiltering() && visible)
_CheckPoseSortOrder(fFilteredPoseList, pose, index);
}
} else {
@@ -5904,7 +5898,7 @@ BPoseView::AttributeChanged(const BMessage* message)
|| sAttrColumnMap[i].attrHash == SecondarySort()) {
if ((fields & sAttrColumnMap[i].fieldMask) != 0) {
_CheckPoseSortOrder(fPoseList, pose, poseListIndex);
if (fFiltering && visible)
if (IsFiltering() && visible)
_CheckPoseSortOrder(fFilteredPoseList, pose, index);
break;
}
@@ -6611,13 +6605,15 @@ BPoseView::KeyDown(const char* bytes, int32 count)
}
case B_RETURN:
if (fFiltering && CountSelected() == 0)
if (IsFiltering() && CountSelected() == 0)
SelectPose(fFilteredPoseList->FirstItem(), 0);
OpenSelection();
if (fFiltering && (modifiers() & B_SHIFT_KEY) != 0)
StopFiltering();
if (IsTypeAheadFiltering() && (modifiers() & B_SHIFT_KEY) != 0) {
// Discard type-ahead filtering by opening a pose with Shift+Return.
StopTypeAheadFiltering();
}
break;
@@ -6716,7 +6712,7 @@ BPoseView::KeyDown(const char* bytes, int32 count)
case B_BACKSPACE:
{
if (fFiltering) {
if (IsTypeAheadFiltering()) {
BString* lastString = fFilterStrings.LastItem();
if (lastString->Length() == 0) {
int32 stringCount = fFilterStrings.CountItems();
@@ -6728,7 +6724,7 @@ BPoseView::KeyDown(const char* bytes, int32 count)
lastString->TruncateChars(lastString->CountChars() - 1);
fCountView->RemoveFilterCharacter();
FilterChanged();
TypeAheadFilteringChanged();
break;
}
@@ -6782,7 +6778,7 @@ BPoseView::KeyDown(const char* bytes, int32 count)
fFilterStrings.LastItem()->AppendChars(bytes, 1);
fCountView->AddFilterCharacter(bytes);
FilterChanged();
TypeAheadFilteringChanged();
break;
}
@@ -8034,7 +8030,7 @@ BPoseView::DeletePose(const node_ref* itemNode, BPose* pose, int32 index)
fPoseList->RemoveItemAt(index);
bool visible = true;
if (fFiltering) {
if (IsFiltering()) {
if (fFilteredPoseList->FindPose(itemNode, &index) != NULL)
fFilteredPoseList->RemoveItemAt(index);
else
@@ -8355,7 +8351,7 @@ BPoseView::ClearPoses()
{
CommitActivePose();
SavePoseLocations();
ClearFilter();
ClearTypeAheadFiltering();
// clear all pose lists
fPoseList->MakeEmpty();
@@ -8495,10 +8491,8 @@ BPoseView::Refresh()
AddPoses(TargetModel());
TargetModel()->CloseNode();
if (fRefFilter != NULL) {
fFiltering = false;
StartFiltering();
}
if (IsFiltering())
RebuildFilteringPoseList();
Invalidate();
ResetOrigin();
@@ -9339,7 +9333,7 @@ BPoseView::_CheckPoseSortOrder(PoseList* poseList, BPose* pose, int32 oldIndex)
return;
}
if (fFiltering && poseList != fFilteredPoseList) {
if (IsFiltering() && poseList != fFilteredPoseList) {
poseList->AddItem(pose, newIndex);
return;
}
@@ -9571,7 +9565,7 @@ BPoseView::SortPoses()
PoseList::Private(fPoseList).AsBList()->Items());
std::stable_sort(poses, &poses[fPoseList->CountItems()],
PoseComparator(this));
if (fFiltering) {
if (IsFiltering()) {
poses = reinterpret_cast<BPose**>(
PoseList::Private(fFilteredPoseList).AsBList()->Items());
std::stable_sort(poses, &poses[fFilteredPoseList->CountItems()],
@@ -10352,7 +10346,7 @@ BPoseView::RemoveFilteredPose(BPose* pose, int32 index)
void
BPoseView::FilterChanged()
BPoseView::TypeAheadFilteringChanged()
{
if (ViewMode() != kListMode)
return;
@@ -10360,25 +10354,21 @@ BPoseView::FilterChanged()
int32 stringCount = fFilterStrings.CountItems();
int32 length = fFilterStrings.LastItem()->CountChars();
if (!fFiltering && (length > 0 || fRefFilter != NULL)) {
StartFiltering();
} else if (fFiltering && stringCount == 1 && length == 0 && fRefFilter == NULL) {
ClearFilter();
if (!IsTypeAheadFiltering() && length > 0) {
StartTypeAheadFiltering();
} else if (IsTypeAheadFiltering() && stringCount == 1 && length == 0) {
ClearTypeAheadFiltering();
} else if (fLastFilterStringCount > stringCount
|| (fLastFilterStringCount == stringCount && fLastFilterStringLength > length)) {
// something was removed, need to start over
RebuildFilteringPoseList();
Invalidate();
} else {
if (fLastFilterStringCount > stringCount
|| (fLastFilterStringCount == stringCount && fLastFilterStringLength > length)
|| fRefFilter != NULL) {
// something was removed, need to start over
fFilteredPoseList->MakeEmpty();
fFiltering = false;
StartFiltering();
} else {
int32 poseCount = fFilteredPoseList->CountItems();
for (int32 i = poseCount - 1; i >= 0; i--) {
BPose* pose = fFilteredPoseList->ItemAt(i);
if (!FilterPose(pose))
RemoveFilteredPose(pose, i);
}
int32 poseCount = fFilteredPoseList->CountItems();
for (int32 index = poseCount - 1; index >= 0; index--) {
BPose* pose = fFilteredPoseList->ItemAt(index);
if (!FilterPose(pose))
RemoveFilteredPose(pose, index);
}
}
@@ -10410,10 +10400,10 @@ BPoseView::UpdateAfterFilterChange()
bool
BPoseView::FilterPose(BPose* pose)
{
if (!fFiltering || pose == NULL)
if (pose == NULL || !(IsFiltering() || IsTypeAheadFiltering()))
return false;
if (fRefFilter != NULL) {
if (IsFiltering()) {
PoseInfo poseInfo;
ReadPoseInfo(pose->TargetModel(), &poseInfo);
if (pose->TargetModel()->OpenNode() != B_OK)
@@ -10457,46 +10447,34 @@ BPoseView::FilterPose(BPose* pose)
void
BPoseView::StartFiltering()
BPoseView::StartTypeAheadFiltering()
{
if (fFiltering)
if (fTypeAheadFiltering)
return;
fFiltering = true;
int32 poseCount = fPoseList->CountItems();
for (int32 i = 0; i < poseCount; i++) {
BPose* pose = fPoseList->ItemAt(i);
if (FilterPose(pose))
fFilteredPoseList->AddItem(pose);
else
EnsurePoseUnselected(pose);
}
fTypeAheadFiltering = true;
RebuildFilteringPoseList();
Invalidate();
}
bool
BPoseView::IsFiltering() const
{
return fFiltering;
}
void
BPoseView::StopFiltering()
BPoseView::StopTypeAheadFiltering()
{
ClearFilter();
ClearTypeAheadFiltering();
UpdateAfterFilterChange();
}
void
BPoseView::ClearFilter()
BPoseView::ClearTypeAheadFiltering()
{
if (!fFiltering)
if (!fTypeAheadFiltering)
return;
fTypeAheadFiltering = false;
fCountView->CancelFilter();
int32 stringCount = fFilterStrings.CountItems();
@@ -10507,15 +10485,32 @@ BPoseView::ClearFilter()
fLastFilterStringCount = 1;
fLastFilterStringLength = 0;
if (fRefFilter == NULL)
fFiltering = false;
fFilteredPoseList->MakeEmpty();
if (IsFiltering())
RebuildFilteringPoseList();
Invalidate();
}
void
BPoseView::RebuildFilteringPoseList()
{
fFilteredPoseList->MakeEmpty();
int32 poseCount = fPoseList->CountItems();
for (int32 index = 0; index < poseCount; index++) {
BPose* pose = fPoseList->ItemAt(index);
if (pose == NULL)
continue;
if (FilterPose(pose))
fFilteredPoseList->AddItem(pose);
else
EnsurePoseUnselected(pose);
}
}
void
BPoseView::ExcludeTrashFromSelection()
{
+11 -8
View File
@@ -412,7 +412,8 @@ public:
void StopWatchDateFormatChange();
// type ahead filtering
bool IsFiltering() const;
bool IsFiltering() const { return fRefFilter != NULL; };
bool IsTypeAheadFiltering() const { return fTypeAheadFiltering; };
void UpdateDateColumns(BMessage*);
virtual void AdaptToVolumeChange(BMessage*);
@@ -655,12 +656,14 @@ protected:
// typeahead filtering
void EnsurePoseUnselected(BPose* pose);
void RemoveFilteredPose(BPose* pose, int32 index);
void FilterChanged();
void TypeAheadFilteringChanged();
void UpdateAfterFilterChange();
bool FilterPose(BPose* pose);
void StartFiltering();
void StopFiltering();
void ClearFilter();
void StartTypeAheadFiltering();
void StopTypeAheadFiltering();
void ClearTypeAheadFiltering();
void RebuildFilteringPoseList();
PoseList* CurrentPoseList() const;
// misc
@@ -805,7 +808,7 @@ private:
bool fIsWatchingDateFormatChange : 1;
bool fHasPosesInClipboard : 1;
bool fCursorCheck : 1;
bool fFiltering : 1;
bool fTypeAheadFiltering : 1;
BObjectList<BString> fFilterStrings;
int32 fLastFilterStringCount;
@@ -1232,7 +1235,7 @@ BPoseView::SetRefFilter(BRefFilter* filter)
{
fRefFilter = filter;
if (filter != NULL)
FilterChanged();
RebuildFilteringPoseList();
}
@@ -1281,7 +1284,7 @@ BPoseView::SetHasPosesInClipboard(bool hasPoses)
inline PoseList*
BPoseView::CurrentPoseList() const
{
return fFiltering ? fFilteredPoseList : fPoseList;
return (IsFiltering() || IsTypeAheadFiltering()) ? fFilteredPoseList : fPoseList;
}