Author: axeld Date: 2010-11-09 00:06:36 +0100 (Tue, 09 Nov 2010) New Revision: 39364 Changeset: http://dev.haiku-os.org/changeset/39364 Ticket: http://dev.haiku-os.org/ticket/6778 Ticket: http://dev.haiku-os.org/ticket/6797 Added: haiku/trunk/src/apps/showimage/ImageCache.cpp haiku/trunk/src/apps/showimage/ImageCache.h Modified: haiku/trunk/src/apps/showimage/ImageFileNavigator.cpp haiku/trunk/src/apps/showimage/ImageFileNavigator.h haiku/trunk/src/apps/showimage/Jamfile haiku/trunk/src/apps/showimage/ShowImageStatusView.cpp haiku/trunk/src/apps/showimage/ShowImageStatusView.h haiku/trunk/src/apps/showimage/ShowImageView.cpp haiku/trunk/src/apps/showimage/ShowImageWindow.cpp haiku/trunk/src/apps/showimage/ShowImageWindow.h Log: * The ImageFileNavigator is now only for navigation, it doesn't load any images anymore. * Moved the new ImageCache into its own source file. * The cache is now used within ShowImage. There is no read-ahead caching being done yet, though, but you can quickly return to previous images, and you can also skip images faster than before. * Improved separation between the ShowImageStatusView and the rest; ShowImageWindow no longer has a getter for the image view. * The status view is now using the private BDirMenu which implements enhancement ticket #6778. * Made a few more methods private/protected in ShowImageWindow. * Fixed bug #6797. * The bitmap is currently only owned by the ImageCache, but we need to have a separate referenceable object owning it. Added a TODO comment for this. * The ProgressWindow is currently not being used anymore, added a TODO comment for this as well. Added: haiku/trunk/src/apps/showimage/ImageCache.cpp =================================================================== --- haiku/trunk/src/apps/showimage/ImageCache.cpp (rev 0) +++ haiku/trunk/src/apps/showimage/ImageCache.cpp 2010-11-08 23:06:36 UTC (rev 39364) @@ -0,0 +1,300 @@ +/* + * Copyright 2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include "ImageCache.h" + +#include <new> + +#include <Autolock.h> +#include <Bitmap.h> +#include <BitmapStream.h> +#include <Debug.h> +#include <File.h> +#include <Messenger.h> +#include <TranslatorRoster.h> + +#include <AutoDeleter.h> + +#include "ShowImageConstants.h" + + +struct QueueEntry { + entry_ref ref; + int32 page; + status_t status; + std::set<BMessenger> listeners; +}; + + +/*static*/ ImageCache ImageCache::sCache; + + +// #pragma mark - + + +ImageCache::ImageCache() + : + fLocker("image cache"), + fThreadCount(0), + fBytes(0) +{ + system_info info; + get_system_info(&info); + + fMaxThreadCount = (info.cpu_count + 1) / 2; + fMaxBytes = info.max_pages * B_PAGE_SIZE / 8; + fMaxEntries = 10; +} + + +ImageCache::~ImageCache() +{ + // TODO: delete CacheEntries, and QueueEntries +} + + +status_t +ImageCache::RetrieveImage(const entry_ref& ref, int32 page, + const BMessenger* target) +{ + BAutolock locker(fLocker); + + CacheMap::iterator find = fCacheMap.find(std::make_pair(ref, page)); + if (find != fCacheMap.end()) { + CacheEntry* entry = find->second; + + // Requeue cache entry to the end of the by-age list + fCacheEntriesByAge.Remove(entry); + fCacheEntriesByAge.Add(entry); + + // Notify target, if any + _NotifyTarget(entry, target); + return B_OK; + } + + QueueMap::iterator findQueue = fQueueMap.find(std::make_pair(ref, page)); + QueueEntry* entry; + + if (findQueue == fQueueMap.end()) { + // Push new entry to the queue + entry = new(std::nothrow) QueueEntry(); + if (entry == NULL) + return B_NO_MEMORY; + + entry->ref = ref; + entry->page = page; + + if (fThreadCount < fMaxThreadCount) { + // start a new worker thread to load the image + thread_id thread = spawn_thread(&ImageCache::_QueueWorkerThread, + "image loader", B_LOW_PRIORITY, this); + if (thread >= B_OK) { + atomic_add(&fThreadCount, 1); + resume_thread(thread); + } else if (fThreadCount == 0) { + delete entry; + return thread; + } + } + + fQueueMap.insert(std::make_pair( + std::make_pair(entry->ref, entry->page), entry)); + fQueue.push_front(entry); + } else + entry = findQueue->second; + + if (target != NULL) { + // Attach target as listener + entry->listeners.insert(*target); + } + + return B_OK; +} + + +/*static*/ status_t +ImageCache::_QueueWorkerThread(void* _self) +{ + ImageCache* self = (ImageCache*)_self; + + // get next queue entry + while (true) { + self->fLocker.Lock(); + if (self->fQueue.empty()) { + self->fLocker.Unlock(); + break; + } + + QueueEntry* entry = *self->fQueue.begin(); + self->fQueue.pop_front(); + self->fLocker.Unlock(); + + if (entry == NULL) + break; + + CacheEntry* cacheEntry = NULL; + entry->status = self->_RetrieveImage(entry, &cacheEntry); + + self->fLocker.Lock(); + self->fQueueMap.erase(std::make_pair(entry->ref, entry->page)); + self->fLocker.Unlock(); + + self->_NotifyListeners(cacheEntry, entry); + delete entry; + } + + atomic_add(&self->fThreadCount, -1); + return B_OK; +} + + +status_t +ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry) +{ + CacheEntry* entry = new(std::nothrow) CacheEntry(); + if (entry == NULL) + return B_NO_MEMORY; + + ObjectDeleter<CacheEntry> deleter(entry); + + BTranslatorRoster* roster = BTranslatorRoster::Default(); + if (roster == NULL) + return B_ERROR; + + BFile file; + status_t status = file.SetTo(&queueEntry->ref, B_READ_ONLY); + if (status != B_OK) + return status; + + translator_info info; + memset(&info, 0, sizeof(translator_info)); + BMessage ioExtension; + + if (queueEntry->page != 0 + && ioExtension.AddInt32("/documentIndex", queueEntry->page) != B_OK) + return B_NO_MEMORY; + +// TODO: rethink this! +#if 0 + if (fProgressWindow != NULL) { + BMessage progress(kMsgProgressStatusUpdate); + if (ioExtension.AddMessenger("/progressMonitor", + fProgressWindow) == B_OK + && ioExtension.AddMessage("/progressMessage", &progress) == B_OK) + fProgressWindow->Start(); + } +#endif + + // Translate image data and create a new ShowImage window + + BBitmapStream outstream; + + status = roster->Identify(&file, &ioExtension, &info, 0, NULL, + B_TRANSLATOR_BITMAP); + if (status == B_OK) { + status = roster->Translate(&file, &info, &ioExtension, &outstream, + B_TRANSLATOR_BITMAP); + } + +#if 0 + if (fProgressWindow != NULL) + fProgressWindow->Stop(); +#endif + + if (status != B_OK) + return status; + + BBitmap* bitmap; + if (outstream.DetachBitmap(&bitmap) != B_OK) + return B_ERROR; + + entry->ref = queueEntry->ref; + entry->page = queueEntry->page; + entry->bitmap = bitmap; + entry->type = info.name; + entry->mimeType = info.MIME; + + // get the number of documents (pages) if it has been supplied + int32 documentCount = 0; + if (ioExtension.FindInt32("/documentCount", &documentCount) == B_OK + && documentCount > 0) + entry->pageCount = documentCount; + else + entry->pageCount = 1; + + deleter.Detach(); + *_entry = entry; + + BAutolock locker(fLocker); + + fCacheMap.insert(std::make_pair( + std::make_pair(entry->ref, entry->page), entry)); + fCacheEntriesByAge.Add(entry); + + fBytes += bitmap->BitsLength(); + + while (fBytes > fMaxBytes || fCacheMap.size() > fMaxEntries) { + if (fCacheMap.size() <= 2) + break; + + // Remove the oldest entry + entry = fCacheEntriesByAge.RemoveHead(); + fBytes -= entry->bitmap->BitsLength(); + fCacheMap.erase(std::make_pair(entry->ref, entry->page)); + delete entry; + } + + return B_OK; +} + + +void +ImageCache::_NotifyListeners(CacheEntry* entry, QueueEntry* queueEntry) +{ + ASSERT(fLocker.IsLocked()); + + if (queueEntry->listeners.empty()) + return; + + BMessage notification(kMsgImageLoaded); + _BuildNotification(entry, notification); + + if (queueEntry->status != B_OK) + notification.AddInt32("error", queueEntry->status); + + std::set<BMessenger>::iterator iterator = queueEntry->listeners.begin(); + for (; iterator != queueEntry->listeners.end(); iterator++) { + iterator->SendMessage(¬ification); + } +} + + +void +ImageCache::_NotifyTarget(CacheEntry* entry, const BMessenger* target) +{ + if (target == NULL) + return; + + BMessage notification(kMsgImageLoaded); + _BuildNotification(entry, notification); + + target->SendMessage(¬ification); +} + + +void +ImageCache::_BuildNotification(CacheEntry* entry, BMessage& message) +{ + if (entry == NULL) + return; + + message.AddString("type", entry->type); + message.AddString("mime", entry->mimeType); + message.AddRef("ref", &entry->ref); + message.AddInt32("page", entry->page); + message.AddInt32("pageCount", entry->pageCount); + message.AddPointer("bitmap", (void*)entry->bitmap); +} Added: haiku/trunk/src/apps/showimage/ImageCache.h =================================================================== --- haiku/trunk/src/apps/showimage/ImageCache.h (rev 0) +++ haiku/trunk/src/apps/showimage/ImageCache.h 2010-11-08 23:06:36 UTC (rev 39364) @@ -0,0 +1,85 @@ +/* + * Copyright 2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + */ +#ifndef IMAGE_CACHE_H +#define IMAGE_CACHE_H + + +#include <deque> +#include <map> +#include <set> + +#include <Entry.h> +#include <Locker.h> +#include <String.h> + +#include <kernel/util/DoublyLinkedList.h> + + +class BBitmap; +class BMessage; +class BMessenger; +struct QueueEntry; + + +enum { + kMsgImageLoaded = 'ifnL' +}; + + +struct CacheEntry : DoublyLinkedListLinkImpl<CacheEntry> { + entry_ref ref; + int32 page; + int32 pageCount; + BBitmap* bitmap; + BString type; + BString mimeType; +}; + + +class ImageCache { +public: + static ImageCache& Default() { return sCache; } + + status_t RetrieveImage(const entry_ref& ref, int32 page, + const BMessenger* target); + +private: + ImageCache(); + virtual ~ImageCache(); + + static status_t _QueueWorkerThread(void* self); + + status_t _RetrieveImage(QueueEntry* entry, + CacheEntry** _entry); + void _NotifyListeners(CacheEntry* entry, + QueueEntry* queueEntry); + void _NotifyTarget(CacheEntry* entry, + const BMessenger* target); + void _BuildNotification(CacheEntry* entry, + BMessage& message); + +private: + typedef std::pair<entry_ref, int32> ImageSelector; + typedef std::map<ImageSelector, CacheEntry*> CacheMap; + typedef std::map<ImageSelector, QueueEntry*> QueueMap; + typedef std::deque<QueueEntry*> QueueDeque; + typedef DoublyLinkedList<CacheEntry> CacheList; + + BLocker fLocker; + CacheMap fCacheMap; + CacheList fCacheEntriesByAge; + QueueMap fQueueMap; + QueueDeque fQueue; + vint32 fThreadCount; + int32 fMaxThreadCount; + uint64 fBytes; + uint64 fMaxBytes; + size_t fMaxEntries; + + static ImageCache sCache; +}; + + +#endif // IMAGE_CACHE_H Modified: haiku/trunk/src/apps/showimage/ImageFileNavigator.cpp =================================================================== --- haiku/trunk/src/apps/showimage/ImageFileNavigator.cpp 2010-11-08 21:53:24 UTC (rev 39363) +++ haiku/trunk/src/apps/showimage/ImageFileNavigator.cpp 2010-11-08 23:06:36 UTC (rev 39364) @@ -18,26 +18,20 @@ #include "ImageFileNavigator.h" -#include <deque> -#include <map> #include <new> -#include <set> #include <stdio.h> -#include <Bitmap.h> #include <BitmapStream.h> #include <Directory.h> #include <Entry.h> #include <File.h> -#include <Locker.h> +//#include <Locker.h> #include <ObjectList.h> -#include <Path.h> +//#include <Path.h> #include <TranslatorRoster.h> -#include <AutoDeleter.h> #include <tracker_private.h> -#include <kernel/util/DoublyLinkedList.h> #include "ProgressWindow.h" #include "ShowImageConstants.h" @@ -320,254 +314,10 @@ // #pragma mark - -struct CacheEntry : DoublyLinkedListLinkImpl<CacheEntry> { - entry_ref ref; - int32 page; - int32 pageCount; - BBitmap* bitmap; - BString type; - BString mimeType; -}; - - -struct QueueEntry { - entry_ref ref; - int32 page; - std::set<BMessenger> listeners; -}; - - -class ImageCache { -public: - ImageCache(); - virtual ~ImageCache(); - - void RetrieveImage(const entry_ref& ref, - const BMessenger* target); - -private: - static status_t _QueueWorkerThread(void* self); - - status_t _RetrieveImage(QueueEntry* entry, - BMessage& message); - void _NotifyListeners(QueueEntry* entry, - BMessage& message); - -private: - typedef std::pair<entry_ref, int32> ImageSelector; - typedef std::map<ImageSelector, CacheEntry*> CacheMap; - typedef std::map<ImageSelector, QueueEntry*> QueueMap; - typedef std::deque<QueueEntry*> QueueDeque; - typedef DoublyLinkedList<CacheEntry> CacheList; - - BLocker fCacheLocker; - CacheMap fCacheMap; - CacheList fCacheEntriesByAge; - BLocker fQueueLocker; - QueueMap fQueueMap; - QueueDeque fQueue; - vint32 fThreadCount; - int32 fMaxThreadCount; - uint64 fBytes; - uint64 fMaxBytes; - size_t fMaxEntries; -}; - - -ImageCache::ImageCache() +ImageFileNavigator::ImageFileNavigator(const entry_ref& ref, + const BMessenger& trackerMessenger) : - fCacheLocker("image cache"), - fQueueLocker("image queue"), - fThreadCount(0), - fBytes(0) -{ - system_info info; - get_system_info(&info); - - fMaxThreadCount = (info.cpu_count + 1) / 2; - fMaxBytes = info.max_pages * B_PAGE_SIZE / 8; - fMaxEntries = 10; -} - - -ImageCache::~ImageCache() -{ - // TODO: delete CacheEntries, and QueueEntries -} - - -void -ImageCache::RetrieveImage(const entry_ref& ref, const BMessenger* target) -{ - // TODO! -} - - -/*static*/ status_t -ImageCache::_QueueWorkerThread(void* _self) -{ - ImageCache* self = (ImageCache*)_self; - - // get next queue entry - while (true) { - self->fQueueLocker.Lock(); - if (self->fQueue.empty()) { - self->fQueueLocker.Unlock(); - break; - } - - QueueEntry* entry = *self->fQueue.begin(); - self->fQueue.pop_front(); - self->fQueueLocker.Unlock(); - - if (entry == NULL) - break; - - BMessage notification(kMsgImageLoaded); - status_t status = self->_RetrieveImage(entry, notification); - if (status != B_OK) - notification.AddInt32("error", status); - - self->fQueueLocker.Lock(); - self->fQueueMap.erase(std::make_pair(entry->ref, entry->page)); - self->fQueueLocker.Unlock(); - - self->_NotifyListeners(entry, notification); - delete entry; - } - - atomic_add(&self->fThreadCount, -1); - return B_OK; -} - - -status_t -ImageCache::_RetrieveImage(QueueEntry* queueEntry, BMessage& message) -{ - CacheEntry* entry = new(std::nothrow) CacheEntry(); - if (entry == NULL) - return B_NO_MEMORY; - - ObjectDeleter<CacheEntry> deleter(entry); - - BTranslatorRoster* roster = BTranslatorRoster::Default(); - if (roster == NULL) - return B_ERROR; - - if (!entry_ref_is_file(queueEntry->ref)) - return B_IS_A_DIRECTORY; - - BFile file; - status_t status = file.SetTo(&queueEntry->ref, B_READ_ONLY); - if (status != B_OK) - return status; - - translator_info info; - memset(&info, 0, sizeof(translator_info)); - BMessage ioExtension; - - if (queueEntry->page != 0 - && ioExtension.AddInt32("/documentIndex", queueEntry->page) != B_OK) - return B_NO_MEMORY; - -// TODO: rethink this! -#if 0 - if (fProgressWindow != NULL) { - BMessage progress(kMsgProgressStatusUpdate); - if (ioExtension.AddMessenger("/progressMonitor", - fProgressWindow) == B_OK - && ioExtension.AddMessage("/progressMessage", &progress) == B_OK) - fProgressWindow->Start(); - } -#endif - - // Translate image data and create a new ShowImage window - - BBitmapStream outstream; - - status = roster->Identify(&file, &ioExtension, &info, 0, NULL, - B_TRANSLATOR_BITMAP); - if (status == B_OK) { - status = roster->Translate(&file, &info, &ioExtension, &outstream, - B_TRANSLATOR_BITMAP); - } - -#if 0 - if (fProgressWindow != NULL) - fProgressWindow->Stop(); -#endif - - if (status != B_OK) - return status; - - BBitmap* bitmap; - if (outstream.DetachBitmap(&bitmap) != B_OK) - return B_ERROR; - - entry->ref = queueEntry->ref; - entry->page = queueEntry->page; - entry->bitmap = bitmap; - entry->type = info.name; - entry->mimeType = info.MIME; - - // get the number of documents (pages) if it has been supplied - int32 documentCount = 0; - if (ioExtension.FindInt32("/documentCount", &documentCount) == B_OK - && documentCount > 0) - entry->pageCount = documentCount; - else - entry->pageCount = 1; - - message.AddString("type", info.name); - message.AddString("mime", info.MIME); - message.AddRef("ref", &entry->ref); - message.AddInt32("page", entry->page); - message.AddPointer("bitmap", (void*)bitmap); - - deleter.Detach(); - - fCacheLocker.Lock(); - - fCacheMap.insert(std::make_pair( - std::make_pair(entry->ref, entry->page), entry)); - fCacheEntriesByAge.Add(entry); - - fBytes += bitmap->BitsLength(); - - while (fBytes > fMaxBytes || fCacheMap.size() > fMaxEntries) { - if (fCacheMap.size() <= 2) - break; - - // Remove the oldest entry - entry = fCacheEntriesByAge.RemoveHead(); - fBytes -= entry->bitmap->BitsLength(); - fCacheMap.erase(std::make_pair(entry->ref, entry->page)); - delete entry; - } - - fCacheLocker.Unlock(); - return B_OK; -} - - -void -ImageCache::_NotifyListeners(QueueEntry* entry, BMessage& message) -{ - std::set<BMessenger>::iterator iterator = entry->listeners.begin(); - for (; iterator != entry->listeners.end(); iterator++) { - iterator->SendMessage(&message); - } -} - - -// #pragma mark - - - -ImageFileNavigator::ImageFileNavigator(const BMessenger& target, - const entry_ref& ref, const BMessenger& trackerMessenger) - : - fTarget(target), - fProgressWindow(NULL), + fCurrentRef(ref), fDocumentIndex(1), fDocumentCount(1) { @@ -585,98 +335,14 @@ void -ImageFileNavigator::SetProgressWindow(ProgressWindow* progressWindow) +ImageFileNavigator::SetTo(const entry_ref& ref, int32 page, int32 pageCount) { - fProgressWindow = progressWindow; -} - - -status_t -ImageFileNavigator::LoadImage(const entry_ref& ref, int32 page) -{ - BTranslatorRoster* roster = BTranslatorRoster::Default(); - if (roster == NULL) - return B_ERROR; - - if (!entry_ref_is_file(ref)) - return B_ERROR; - - BFile file(&ref, B_READ_ONLY); - translator_info info; - memset(&info, 0, sizeof(translator_info)); - BMessage ioExtension; - - if (page != 0 && ioExtension.AddInt32("/documentIndex", page) != B_OK) - return B_ERROR; - - if (fProgressWindow != NULL) { - BMessage progress(kMsgProgressStatusUpdate); - if (ioExtension.AddMessenger("/progressMonitor", - fProgressWindow) == B_OK - && ioExtension.AddMessage("/progressMessage", &progress) == B_OK) - fProgressWindow->Start(); - } - - // Translate image data and create a new ShowImage window - - BBitmapStream outstream; - - status_t status = roster->Identify(&file, &ioExtension, &info, 0, NULL, - B_TRANSLATOR_BITMAP); - if (status == B_OK) { - status = roster->Translate(&file, &info, &ioExtension, &outstream, - B_TRANSLATOR_BITMAP); - } - - if (fProgressWindow != NULL) - fProgressWindow->Stop(); - - if (status != B_OK) - return status; - - BBitmap* bitmap; - if (outstream.DetachBitmap(&bitmap) != B_OK) - return B_ERROR; - fCurrentRef = ref; fDocumentIndex = page; - - // get the number of documents (pages) if it has been supplied - int32 documentCount = 0; - if (ioExtension.FindInt32("/documentCount", &documentCount) == B_OK - && documentCount > 0) - fDocumentCount = documentCount; - else - fDocumentCount = 1; - - BMessage message(kMsgImageLoaded); - message.AddString("type", info.name); - message.AddString("mime", info.MIME); - message.AddRef("ref", &ref); - message.AddInt32("page", page); - message.AddPointer("bitmap", (void*)bitmap); - status = fTarget.SendMessage(&message); - if (status != B_OK) { - delete bitmap; - return status; - } - - return B_OK; + fDocumentCount = pageCount; } -void -ImageFileNavigator::GetPath(BString* outPath) -{ - BEntry entry(&fCurrentRef); - BPath path; - if (entry.InitCheck() < B_OK || entry.GetPath(&path) < B_OK) - outPath->SetTo(""); - else - outPath->SetTo(path.Path()); -} - - int32 ImageFileNavigator::CurrentPage() { @@ -695,7 +361,7 @@ ImageFileNavigator::FirstPage() { if (fDocumentIndex != 1) { - LoadImage(fCurrentRef, 1); + fDocumentIndex = 1; return true; } return false; @@ -706,7 +372,7 @@ ImageFileNavigator::LastPage() { if (fDocumentIndex != fDocumentCount) { - LoadImage(fCurrentRef, fDocumentCount); + fDocumentIndex = fDocumentCount; return true; } return false; @@ -717,7 +383,7 @@ ImageFileNavigator::NextPage() { if (fDocumentIndex < fDocumentCount) { - LoadImage(fCurrentRef, ++fDocumentIndex); + fDocumentIndex++; return true; } return false; @@ -728,7 +394,7 @@ ImageFileNavigator::PreviousPage() { if (fDocumentIndex > 1) { - LoadImage(fCurrentRef, --fDocumentIndex); + fDocumentIndex--; return true; } return false; @@ -740,31 +406,51 @@ { if (page > 0 && page <= fDocumentCount && page != fDocumentIndex) { fDocumentIndex = page; - LoadImage(fCurrentRef, fDocumentIndex); return true; } return false; } -void +bool ImageFileNavigator::FirstFile() { - _LoadNextImage(true, true); + entry_ref ref; + if (fNavigator->FindNextImage(fCurrentRef, ref, false, true)) { + SetTo(ref, 1, 1); + fNavigator->UpdateSelection(fCurrentRef); + return true; + } + + return false; } -void +bool ImageFileNavigator::NextFile() { - _LoadNextImage(true, false); + entry_ref ref; + if (fNavigator->FindNextImage(fCurrentRef, ref, true, false)) { + SetTo(ref, 1, 1); + fNavigator->UpdateSelection(fCurrentRef); + return true; + } + + return false; } -void +bool ImageFileNavigator::PreviousFile() { - _LoadNextImage(false, false); + entry_ref ref; + if (fNavigator->FindNextImage(fCurrentRef, ref, false, false)) { + SetTo(ref, 1, 1); + fNavigator->UpdateSelection(fCurrentRef); + return true; + } + + return false; } @@ -785,7 +471,7 @@ /*! Moves the current file into the trash. - Returns true if a new file is being loaded, false if not. + Returns true if a new file should be loaded, false if not. */ bool ImageFileNavigator::MoveFileToTrash() @@ -803,41 +489,12 @@ // could be invalid BMessenger tracker(kTrackerSignature); if (tracker.SendMessage(&trash) != B_OK) - return true; + return false; - if (nextRef.device != -1 && LoadImage(nextRef) == B_OK) { - fNavigator->UpdateSelection(nextRef); + if (nextRef.device != -1) { + SetTo(nextRef, 1, 1); return true; } return false; } - - -// #pragma mark - - - -status_t -ImageFileNavigator::_LoadNextImage(bool next, bool rewind) -{ - entry_ref currentRef = fCurrentRef; - entry_ref ref; - if (fNavigator->FindNextImage(currentRef, ref, next, rewind)) { - // Keep trying to load images until: - // 1. The image loads successfully - // 2. The last file in the directory is found (for find next or find - // first) - // 3. The first file in the directory is found (for find prev) - // 4. The call to _FindNextImage fails for any other reason - while (LoadImage(ref) != B_OK) { - currentRef = ref; - if (!fNavigator->FindNextImage(currentRef, ref, next, false)) - return B_ENTRY_NOT_FOUND; - } - fNavigator->UpdateSelection(fCurrentRef); - return B_OK; - } - return B_ENTRY_NOT_FOUND; -} - - Modified: haiku/trunk/src/apps/showimage/ImageFileNavigator.h =================================================================== --- haiku/trunk/src/apps/showimage/ImageFileNavigator.h 2010-11-08 21:53:24 UTC (rev 39363) +++ haiku/trunk/src/apps/showimage/ImageFileNavigator.h 2010-11-08 23:06:36 UTC (rev 39364) @@ -22,28 +22,18 @@ class Navigator; -class ProgressWindow; -enum { - kMsgImageLoaded = 'ifnL' -}; - class ImageFileNavigator { public: - ImageFileNavigator(const BMessenger& target, - const entry_ref& ref, + ImageFileNavigator(const entry_ref& ref, const BMessenger& trackerMessenger); virtual ~ImageFileNavigator(); - void SetProgressWindow( - ProgressWindow* progressWindow); + void SetTo(const entry_ref& ref, int32 page = 1, + int32 pageCount = 1); + const entry_ref& CurrentRef() const { return fCurrentRef; } - status_t LoadImage(const entry_ref& ref, int32 page = 1); - const entry_ref& ImageRef() const { return fCurrentRef; } - - void GetPath(BString* name); - // The same image file may have multiple pages, TIFF images for // example. The page count is determined at image loading time. int32 CurrentPage(); @@ -55,20 +45,15 @@ bool PreviousPage(); bool GoToPage(int32 page); - void FirstFile(); - void NextFile(); - void PreviousFile(); + bool FirstFile(); + bool NextFile(); + bool PreviousFile(); bool HasNextFile(); bool HasPreviousFile(); bool MoveFileToTrash(); private: - status_t _LoadNextImage(bool next, bool rewind); - -private: - BMessenger fTarget; - ProgressWindow* fProgressWindow; Navigator* fNavigator; entry_ref fCurrentRef; [... truncated: 477 lines follow ...]