1 /*
2 Open Tracker License
3
4 Terms and Conditions
5
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34
35
36 #include "QueryPoseView.h"
37
38 #include <new>
39
40 #include <Catalog.h>
41 #include <Debug.h>
42 #include <Locale.h>
43 #include <NodeMonitor.h>
44 #include <Query.h>
45 #include <Volume.h>
46 #include <VolumeRoster.h>
47 #include <Window.h>
48
49 #include "Attributes.h"
50 #include "AttributeStream.h"
51 #include "AutoLock.h"
52 #include "Commands.h"
53 #include "FindPanel.h"
54 #include "FSUtils.h"
55 #include "MimeTypeList.h"
56 #include "MimeTypes.h"
57 #include "Tracker.h"
58
59 #include <fs_attr.h>
60
61
62 using std::nothrow;
63
64
65 #undef B_TRANSLATION_CONTEXT
66 #define B_TRANSLATION_CONTEXT "QueryPoseView"
67
68
69 // Currently filtering out Trash doesn't node monitor too well - if you
70 // remove an item from the Trash, it doesn't show up in the query result
71 // To do this properly, we would have to node monitor everything BQuery
72 // returns and after a node monitor re-chech if it should be part of
73 // query results and add/remove appropriately. Right now only moving to
74 // Trash is supported
75
76
77 // #pragma mark - BQueryPoseView
78
79
BQueryPoseView(Model * model)80 BQueryPoseView::BQueryPoseView(Model* model)
81 :
82 BPoseView(model, kListMode),
83 fRefFilter(NULL),
84 fQueryList(NULL),
85 fQueryListContainer(NULL),
86 fCreateOldPoseList(false)
87 {
88 }
89
90
~BQueryPoseView()91 BQueryPoseView::~BQueryPoseView()
92 {
93 delete fQueryListContainer;
94 }
95
96
97 bool
FolderFilterFunction(const entry_ref * directory,const entry_ref * model)98 FolderFilterFunction(const entry_ref* directory, const entry_ref* model)
99 {
100 if (directory == NULL || model == NULL)
101 return false;
102
103 BPath directoryPath(directory);
104 BPath modelPath(model);
105
106 if (directoryPath.InitCheck() != B_OK || modelPath.InitCheck() != B_OK)
107 return false;
108
109 char* requiredDirectoryPath = const_cast<char*>(directoryPath.Path());
110 strcat(requiredDirectoryPath, "/");
111 // only supports searching completely in the directories as well as subdirectories for now.
112 return strncmp(requiredDirectoryPath, modelPath.Path(), strlen(requiredDirectoryPath)) == 0;
113 }
114
115
116 bool
PassThroughDirectoryFilters(const entry_ref * ref) const117 QueryRefFilter::PassThroughDirectoryFilters(const entry_ref* ref) const
118 {
119 int32 count = fDirectoryFilters.CountItems();
120 bool passed = count == 0;
121 // in this context, even if the model passes through a single filter, it is considered
122 // as the folder selections are combined with OR! and not AND!
123
124 for (int32 i = 0; i < count; i++) {
125 entry_ref* filterDirectory = fDirectoryFilters.ItemAt(i);
126 if (FolderFilterFunction(filterDirectory, ref)) {
127 passed = true;
128 break;
129 }
130 }
131
132 return passed;
133 }
134
135
136 void
MessageReceived(BMessage * message)137 BQueryPoseView::MessageReceived(BMessage* message)
138 {
139 switch (message->what) {
140 case kFSClipboardChanges:
141 {
142 // poses have always to be updated for the query view
143 UpdatePosesClipboardModeFromClipboard(message);
144 break;
145 }
146
147 default:
148 _inherited::MessageReceived(message);
149 break;
150 }
151 }
152
153
154 void
EditQueries()155 BQueryPoseView::EditQueries()
156 {
157 BMessage message(kEditQuery);
158 message.AddRef("refs", TargetModel()->EntryRef());
159 BMessenger(kTrackerSignature, -1, 0).SendMessage(&message);
160 }
161
162
163 void
SetupDefaultColumnsIfNeeded()164 BQueryPoseView::SetupDefaultColumnsIfNeeded()
165 {
166 // in case there were errors getting some columns
167 if (CountColumns() != 0)
168 return;
169
170 AddColumn(new BColumn(B_TRANSLATE("Name"), 145,
171 B_ALIGN_LEFT, kAttrStatName, B_STRING_TYPE, true, true));
172 AddColumn(new BColumn(B_TRANSLATE("Location"), 225,
173 B_ALIGN_LEFT, kAttrPath, B_STRING_TYPE, true, false));
174 AddColumn(new BColumn(B_TRANSLATE("Size"), 80,
175 B_ALIGN_RIGHT, kAttrStatSize, B_OFF_T_TYPE, true, false));
176 AddColumn(new BColumn(B_TRANSLATE("Modified"), 150,
177 B_ALIGN_LEFT, kAttrStatModified, B_TIME_TYPE, true, false));
178 }
179
180
181 void
RestoreState(AttributeStreamNode * node)182 BQueryPoseView::RestoreState(AttributeStreamNode* node)
183 {
184 _inherited::RestoreState(node);
185 fViewState->SetViewMode(kListMode);
186 }
187
188
189 void
RestoreState(const BMessage & message)190 BQueryPoseView::RestoreState(const BMessage &message)
191 {
192 _inherited::RestoreState(message);
193 fViewState->SetViewMode(kListMode);
194 }
195
196
197 void
SavePoseLocations(BRect *)198 BQueryPoseView::SavePoseLocations(BRect*)
199 {
200 }
201
202
203 void
SetViewMode(uint32)204 BQueryPoseView::SetViewMode(uint32)
205 {
206 }
207
208
209 void
OpenParent()210 BQueryPoseView::OpenParent()
211 {
212 }
213
214
215 void
Refresh()216 BQueryPoseView::Refresh()
217 {
218 PRINT(("refreshing dynamic date query\n"));
219
220 // cause the old AddPosesTask to die
221 fAddPosesThreads.clear();
222 delete fQueryListContainer;
223 fQueryListContainer = NULL;
224
225 fCreateOldPoseList = true;
226 AddPoses(TargetModel());
227 TargetModel()->CloseNode();
228
229 ResetOrigin();
230 ResetPosePlacementHint();
231 }
232
233
234 void
AddPosesCompleted()235 BQueryPoseView::AddPosesCompleted()
236 {
237 ASSERT(Window()->IsLocked());
238
239 PoseList* oldPoseList = fQueryListContainer->OldPoseList();
240 if (oldPoseList != NULL) {
241 int32 count = oldPoseList->CountItems();
242 for (int32 index = count - 1; index >= 0; index--) {
243 BPose* pose = oldPoseList->ItemAt(index);
244 DeletePose(pose->TargetModel()->NodeRef());
245 }
246 fQueryListContainer->ClearOldPoseList();
247 }
248
249 _inherited::AddPosesCompleted();
250 }
251
252
253 // When using dynamic dates, such as "today", need to refresh the query
254 // window every now and then
255
256 EntryListBase*
InitDirentIterator(const entry_ref * ref)257 BQueryPoseView::InitDirentIterator(const entry_ref* ref)
258 {
259 BEntry entry(ref);
260 if (entry.InitCheck() != B_OK)
261 return NULL;
262
263 Model sourceModel(&entry, true);
264 if (sourceModel.InitCheck() != B_OK)
265 return NULL;
266
267 ASSERT(sourceModel.IsQuery());
268
269 // old pose list is used for finding poses that no longer match a
270 // dynamic date query during a Refresh call
271 PoseList* oldPoseList = NULL;
272 if (fCreateOldPoseList) {
273 oldPoseList = new PoseList(10, false);
274 oldPoseList->AddList(fPoseList);
275 }
276
277 fQueryListContainer = new QueryEntryListCollection(&sourceModel, this,
278 oldPoseList);
279 fCreateOldPoseList = false;
280
281 if (fQueryListContainer->InitCheck() != B_OK) {
282 delete fQueryListContainer;
283 fQueryListContainer = NULL;
284 return NULL;
285 }
286
287 TTracker::WatchNode(sourceModel.NodeRef(), B_WATCH_NAME | B_WATCH_STAT
288 | B_WATCH_ATTR, this);
289
290 fQueryList = fQueryListContainer->QueryList();
291
292 if (fQueryListContainer->DynamicDateQuery()) {
293 // calculate the time to trigger the query refresh - next midnight
294
295 time_t now = time(0);
296
297 time_t nextMidnight = now + 60 * 60 * 24;
298 // move ahead by a day
299 tm timeData;
300 localtime_r(&nextMidnight, &timeData);
301 timeData.tm_sec = 0;
302 timeData.tm_min = 0;
303 timeData.tm_hour = 0;
304 nextMidnight = mktime(&timeData);
305
306 time_t nextHour = now + 60 * 60;
307 // move ahead by a hour
308 localtime_r(&nextHour, &timeData);
309 timeData.tm_sec = 0;
310 timeData.tm_min = 0;
311 nextHour = mktime(&timeData);
312
313 PRINT(("%" B_PRIdTIME " minutes, %" B_PRIdTIME " seconds till next hour\n",
314 (nextHour - now) / 60, (nextHour - now) % 60));
315
316 time_t nextMinute = now + 60;
317 // move ahead by a minute
318 localtime_r(&nextMinute, &timeData);
319 timeData.tm_sec = 0;
320 nextMinute = mktime(&timeData);
321
322 PRINT(("%" B_PRIdTIME " seconds till next minute\n", nextMinute - now));
323
324 bigtime_t delta;
325 if (fQueryListContainer->DynamicDateRefreshEveryMinute())
326 delta = nextMinute - now;
327 else if (fQueryListContainer->DynamicDateRefreshEveryHour())
328 delta = nextHour - now;
329 else
330 delta = nextMidnight - now;
331
332 #if DEBUG
333 int32 secondsTillMidnight = (nextMidnight - now);
334 int32 minutesTillMidnight = secondsTillMidnight/60;
335 secondsTillMidnight %= 60;
336 int32 hoursTillMidnight = minutesTillMidnight/60;
337 minutesTillMidnight %= 60;
338
339 PRINT(("%" B_PRId32 " hours, %" B_PRId32 " minutes, %" B_PRId32
340 " seconds till midnight\n", hoursTillMidnight, minutesTillMidnight,
341 secondsTillMidnight));
342
343 int32 refreshInSeconds = delta % 60;
344 int32 refreshInMinutes = delta / 60;
345 int32 refreshInHours = refreshInMinutes / 60;
346 refreshInMinutes %= 60;
347
348 PRINT(("next refresh in %" B_PRId32 " hours, %" B_PRId32 "minutes, %"
349 B_PRId32 " seconds\n", refreshInHours, refreshInMinutes,
350 refreshInSeconds));
351 #endif
352
353 // bump up to microseconds
354 delta *= 1000000;
355
356 TTracker* tracker = dynamic_cast<TTracker*>(be_app);
357 ThrowOnAssert(tracker != NULL);
358
359 tracker->MainTaskLoop()->RunLater(
360 NewLockingMemberFunctionObject(&BQueryPoseView::Refresh, this),
361 delta);
362 }
363
364 QueryRefFilter* filter = new QueryRefFilter(fQueryListContainer->ShowResultsFromTrash());
365 TargetModel()->OpenNode();
366 filter->LoadDirectoryFiltersFromFile(TargetModel()->Node());
367 TargetModel()->CloseNode();
368 SetRefFilter(filter);
369
370 return fQueryListContainer->Clone();
371 }
372
373
374 uint32
WatchNewNodeMask()375 BQueryPoseView::WatchNewNodeMask()
376 {
377 return B_WATCH_NAME | B_WATCH_STAT | B_WATCH_ATTR;
378 }
379
380
381 const char*
SearchForType() const382 BQueryPoseView::SearchForType() const
383 {
384 if (!fSearchForMimeType.Length()) {
385 BModelOpener opener(TargetModel());
386 BString buffer;
387 attr_info attrInfo;
388
389 // read the type of files we are looking for
390 status_t status
391 = TargetModel()->Node()->GetAttrInfo(kAttrQueryInitialMime,
392 &attrInfo);
393 if (status == B_OK) {
394 TargetModel()->Node()->ReadAttrString(kAttrQueryInitialMime,
395 &buffer);
396 }
397
398 TTracker* tracker = dynamic_cast<TTracker*>(be_app);
399 if (tracker != NULL && buffer.Length() > 0) {
400 const ShortMimeInfo* info = tracker->MimeTypes()->FindMimeType(
401 buffer.String());
402 if (info != NULL)
403 fSearchForMimeType = info->InternalName();
404 }
405
406 if (!fSearchForMimeType.Length())
407 fSearchForMimeType = B_FILE_MIMETYPE;
408 }
409
410 return fSearchForMimeType.String();
411 }
412
413
414 bool
ActiveOnDevice(dev_t device) const415 BQueryPoseView::ActiveOnDevice(dev_t device) const
416 {
417 int32 count = fQueryList->CountItems();
418 for (int32 index = 0; index < count; index++) {
419 if (fQueryList->ItemAt(index)->TargetDevice() == device)
420 return true;
421 }
422
423 return false;
424 }
425
426
427 // #pragma mark - QueryRefFilter
428
429
QueryRefFilter(bool showResultsFromTrash)430 QueryRefFilter::QueryRefFilter(bool showResultsFromTrash)
431 :
432 fShowResultsFromTrash(showResultsFromTrash)
433 {
434 }
435
436
~QueryRefFilter()437 QueryRefFilter::~QueryRefFilter()
438 {
439 int32 count = fDirectoryFilters.CountItems();
440 for (int32 i = 0; i < count; i++)
441 delete fDirectoryFilters.RemoveItemAt(0);
442 }
443
444
445 status_t
LoadDirectoryFiltersFromFile(const BNode * node)446 QueryRefFilter::LoadDirectoryFiltersFromFile(const BNode* node)
447 {
448 // params checking
449 if (node == NULL || node->InitCheck() != B_OK)
450 return B_BAD_VALUE;
451
452 struct attr_info info;
453 status_t error = node->GetAttrInfo("_trk/directories", &info);
454 if (error != B_OK)
455 return error;
456
457 BString bufferString;
458 char* buffer = bufferString.LockBuffer(info.size);
459 if (node->ReadAttr("_trk/directories", B_MESSAGE_TYPE, 0, buffer, info.size) != info.size)
460 return B_ERROR;
461
462 BMessage message;
463 error = message.Unflatten(buffer);
464 if (error != B_OK)
465 return error;
466
467 int32 count;
468 if ((error = message.GetInfo("refs", NULL, &count)) != B_OK)
469 return error;
470
471 for (int32 i = 0; i < count; i++) {
472 entry_ref ref;
473 if ((error = message.FindRef("refs", i, &ref)) != B_OK)
474 continue;
475
476 AddDirectoryFilter(&ref);
477 }
478
479 return B_OK;
480 }
481
482
483 status_t
AddDirectoryFilter(const entry_ref * ref)484 QueryRefFilter::AddDirectoryFilter(const entry_ref* ref)
485 {
486 if (ref == NULL)
487 return B_BAD_VALUE;
488
489 // checking for duplicates
490 int32 count = fDirectoryFilters.CountItems();
491 for (int32 i = 0; i < count; i++) {
492 entry_ref* item = fDirectoryFilters.ItemAt(i);
493 if (ref != NULL && item != NULL && *item == *ref)
494 return B_CANCELED;
495 }
496
497 BEntry entry(ref, true);
498 if (entry.InitCheck() != B_OK || !entry.Exists() || !entry.IsDirectory())
499 return B_ERROR;
500
501 entry_ref symlinkTraversedRef;
502 entry.GetRef(&symlinkTraversedRef);
503
504 fDirectoryFilters.AddItem(new entry_ref(symlinkTraversedRef));
505 return B_OK;
506 }
507
508
509 bool
Filter(const entry_ref * ref,BNode * node,stat_beos * st,const char * filetype)510 QueryRefFilter::Filter(const entry_ref* ref, BNode* node, stat_beos* st,
511 const char* filetype)
512 {
513 TTracker* tracker = dynamic_cast<TTracker*>(be_app);
514 return !(!fShowResultsFromTrash && tracker != NULL && tracker->InTrashNode(ref))
515 && PassThroughDirectoryFilters(ref);
516 }
517
518
519 // #pragma mark - QueryEntryListCollection
520
521
QueryEntryListCollection(Model * model,BHandler * target,PoseList * oldPoseList)522 QueryEntryListCollection::QueryEntryListCollection(Model* model,
523 BHandler* target, PoseList* oldPoseList)
524 :
525 fQueryListRep(new QueryListRep(new BObjectList<BQuery>(5, true)))
526 {
527 Rewind();
528 attr_info info;
529 BQuery query;
530
531 BNode* modelNode = model->Node();
532 if (modelNode == NULL) {
533 fStatus = B_ERROR;
534 return;
535 }
536
537 // read the actual query string
538 fStatus = modelNode->GetAttrInfo(kAttrQueryString, &info);
539 if (fStatus != B_OK)
540 return;
541
542 BString buffer;
543 if (modelNode->ReadAttr(kAttrQueryString, B_STRING_TYPE, 0,
544 buffer.LockBuffer((int32)info.size),
545 (size_t)info.size) != info.size) {
546 fStatus = B_ERROR;
547 return;
548 }
549
550 buffer.UnlockBuffer();
551
552 // read the extra options
553 MoreOptionsStruct saveMoreOptions;
554 if (ReadAttr(modelNode, kAttrQueryMoreOptions,
555 kAttrQueryMoreOptionsForeign, B_RAW_TYPE, 0, &saveMoreOptions,
556 sizeof(MoreOptionsStruct),
557 &MoreOptionsStruct::EndianSwap) != kReadAttrFailed) {
558 fQueryListRep->fShowResultsFromTrash = saveMoreOptions.searchTrash;
559 }
560
561 fStatus = query.SetPredicate(buffer.String());
562
563 fQueryListRep->fOldPoseList = oldPoseList;
564 fQueryListRep->fDynamicDateQuery = false;
565
566 fQueryListRep->fRefreshEveryHour = false;
567 fQueryListRep->fRefreshEveryMinute = false;
568
569 if (modelNode->ReadAttr(kAttrDynamicDateQuery, B_BOOL_TYPE, 0,
570 &fQueryListRep->fDynamicDateQuery,
571 sizeof(bool)) != sizeof(bool)) {
572 fQueryListRep->fDynamicDateQuery = false;
573 }
574
575 if (fQueryListRep->fDynamicDateQuery) {
576 // only refresh every minute on debug builds
577 fQueryListRep->fRefreshEveryMinute = buffer.IFindFirst("second") != -1
578 || buffer.IFindFirst("minute") != -1;
579 fQueryListRep->fRefreshEveryHour = fQueryListRep->fRefreshEveryMinute
580 || buffer.IFindFirst("hour") != -1;
581
582 #if !DEBUG
583 // don't refresh every minute unless we are running debug build
584 fQueryListRep->fRefreshEveryMinute = false;
585 #endif
586 }
587
588 if (fStatus != B_OK)
589 return;
590
591 bool searchAllVolumes = true;
592 status_t result = B_OK;
593
594 // get volumes to perform query on
595 if (modelNode->GetAttrInfo(kAttrQueryVolume, &info) == B_OK) {
596 char* buffer = NULL;
597
598 if ((buffer = (char*)malloc((size_t)info.size)) != NULL
599 && modelNode->ReadAttr(kAttrQueryVolume, B_MESSAGE_TYPE, 0,
600 buffer, (size_t)info.size) == info.size) {
601 BMessage message;
602 if (message.Unflatten(buffer) == B_OK) {
603 for (int32 index = 0; ;index++) {
604 ASSERT(index < 100);
605 BVolume volume;
606 // match a volume with the info embedded in
607 // the message
608 result = MatchArchivedVolume(&volume, &message, index);
609 if (result == B_OK) {
610 // start the query on this volume
611 result = FetchOneQuery(&query, target,
612 fQueryListRep->fQueryList, &volume);
613 if (result != B_OK)
614 continue;
615
616 searchAllVolumes = false;
617 } else if (result != B_DEV_BAD_DRIVE_NUM) {
618 // if B_DEV_BAD_DRIVE_NUM, the volume just isn't
619 // mounted this time around, keep looking for more
620 // if other error, bail
621 break;
622 }
623 }
624 }
625 }
626
627 free(buffer);
628 }
629
630 if (searchAllVolumes) {
631 // no specific volumes embedded in query, search everything
632 BVolumeRoster roster;
633 BVolume volume;
634
635 roster.Rewind();
636 while (roster.GetNextVolume(&volume) == B_OK)
637 if (volume.IsPersistent() && volume.KnowsQuery()) {
638 result = FetchOneQuery(&query, target,
639 fQueryListRep->fQueryList, &volume);
640 if (result != B_OK)
641 continue;
642 }
643 }
644
645 fStatus = B_OK;
646
647 return;
648 }
649
650
651 status_t
FetchOneQuery(const BQuery * copyThis,BHandler * target,BObjectList<BQuery> * list,BVolume * volume)652 QueryEntryListCollection::FetchOneQuery(const BQuery* copyThis,
653 BHandler* target, BObjectList<BQuery>* list, BVolume* volume)
654 {
655 BQuery* query = new (nothrow) BQuery;
656 if (query == NULL)
657 return B_NO_MEMORY;
658
659 // have to fake a copy constructor here because BQuery doesn't have
660 // a copy constructor
661 BString buffer;
662 const_cast<BQuery*>(copyThis)->GetPredicate(&buffer);
663 query->SetPredicate(buffer.String());
664
665 query->SetTarget(BMessenger(target));
666 query->SetVolume(volume);
667
668 status_t result = query->Fetch();
669 if (result != B_OK) {
670 PRINT(("fetch error %s\n", strerror(result)));
671 delete query;
672 return result;
673 }
674
675 list->AddItem(query);
676
677 return B_OK;
678 }
679
680
~QueryEntryListCollection()681 QueryEntryListCollection::~QueryEntryListCollection()
682 {
683 if (fQueryListRep->CloseQueryList())
684 delete fQueryListRep;
685 }
686
687
688 QueryEntryListCollection*
Clone()689 QueryEntryListCollection::Clone()
690 {
691 fQueryListRep->OpenQueryList();
692 return new QueryEntryListCollection(*this);
693 }
694
695
696 // #pragma mark - QueryEntryListCollection
697
698
QueryEntryListCollection(const QueryEntryListCollection & cloneThis)699 QueryEntryListCollection::QueryEntryListCollection(
700 const QueryEntryListCollection &cloneThis)
701 :
702 EntryListBase(),
703 fQueryListRep(cloneThis.fQueryListRep)
704 {
705 // only to be used by the Clone routine
706 }
707
708
709 void
ClearOldPoseList()710 QueryEntryListCollection::ClearOldPoseList()
711 {
712 delete fQueryListRep->fOldPoseList;
713 fQueryListRep->fOldPoseList = NULL;
714 }
715
716
717 status_t
GetNextEntry(BEntry * entry,bool traverse)718 QueryEntryListCollection::GetNextEntry(BEntry* entry, bool traverse)
719 {
720 status_t result = B_ERROR;
721
722 for (int32 count = fQueryListRep->fQueryList->CountItems();
723 fQueryListRep->fQueryListIndex < count;
724 fQueryListRep->fQueryListIndex++) {
725 result = fQueryListRep->fQueryList->
726 ItemAt(fQueryListRep->fQueryListIndex)->
727 GetNextEntry(entry, traverse);
728 if (result == B_OK)
729 break;
730 }
731
732 return result;
733 }
734
735
736 int32
GetNextDirents(struct dirent * buffer,size_t length,int32 count)737 QueryEntryListCollection::GetNextDirents(struct dirent* buffer, size_t length,
738 int32 count)
739 {
740 int32 result = 0;
741
742 for (int32 queryCount = fQueryListRep->fQueryList->CountItems();
743 fQueryListRep->fQueryListIndex < queryCount;
744 fQueryListRep->fQueryListIndex++) {
745 result = fQueryListRep->fQueryList->
746 ItemAt(fQueryListRep->fQueryListIndex)->
747 GetNextDirents(buffer, length, count);
748 if (result > 0)
749 break;
750 }
751
752 return result;
753 }
754
755
756 status_t
GetNextRef(entry_ref * ref)757 QueryEntryListCollection::GetNextRef(entry_ref* ref)
758 {
759 status_t result = B_ERROR;
760
761 for (int32 count = fQueryListRep->fQueryList->CountItems();
762 fQueryListRep->fQueryListIndex < count;
763 fQueryListRep->fQueryListIndex++) {
764
765 result = fQueryListRep->fQueryList->
766 ItemAt(fQueryListRep->fQueryListIndex)->GetNextRef(ref);
767 if (result == B_OK)
768 break;
769 }
770
771 return result;
772 }
773
774
775 status_t
Rewind()776 QueryEntryListCollection::Rewind()
777 {
778 fQueryListRep->fQueryListIndex = 0;
779
780 return B_OK;
781 }
782
783
784 int32
CountEntries()785 QueryEntryListCollection::CountEntries()
786 {
787 return 0;
788 }
789
790
791 bool
ShowResultsFromTrash() const792 QueryEntryListCollection::ShowResultsFromTrash() const
793 {
794 return fQueryListRep->fShowResultsFromTrash;
795 }
796
797
798 bool
DynamicDateQuery() const799 QueryEntryListCollection::DynamicDateQuery() const
800 {
801 return fQueryListRep->fDynamicDateQuery;
802 }
803
804
805 bool
DynamicDateRefreshEveryHour() const806 QueryEntryListCollection::DynamicDateRefreshEveryHour() const
807 {
808 return fQueryListRep->fRefreshEveryHour;
809 }
810
811
812 bool
DynamicDateRefreshEveryMinute() const813 QueryEntryListCollection::DynamicDateRefreshEveryMinute() const
814 {
815 return fQueryListRep->fRefreshEveryMinute;
816 }
817