diff --git a/TODO.txt b/TODO.txt index 89aed6c..78f3e08 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,4 @@ Important Features: -* Show in desktray - * Make archivable - * Get menu working * Default column layouts for ~/feeds and ~/config/settings/Pogger/Subscriptions * Localization @@ -14,6 +11,7 @@ Important improvements: and updates every 30 minutes, it got to about 200MB after a week or so. * _Huge_ problem, but I haven't had luck figuring it out yet… +* Move from BLists to BObjectLists where possible * No hardcoded paths * General input sanitization * File error-handling @@ -31,6 +29,7 @@ Nice Improvements: * Main window * Subscription-edit window * Proper scripting support +* Show in desktray * Store feeds in kEnqueueFeeds/etc messages as paths? hmm * This way, if the user edits the feed after it is enqueued but before processing, the changes will be applied. diff --git a/src/App.cpp b/src/App.cpp index a5efb46..6dd95d0 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -54,22 +54,16 @@ App::MessageReceived(BMessage* msg) { switch (msg->what) { + case kDownloadComplete: + fMainWindow->PostMessage(msg); + case kEnqueueFeed: case kUpdateSubscribed: case kControllerCheck: { fFeedController->MessageReceived(msg); break; } - case kDownloadComplete: - fMainWindow->PostMessage(msg); - case kEnqueueFeed: - { - fNotifier->MessageReceived(msg); - fFeedController->MessageReceived(msg); - break; - } case kFeedsEdited: - case kProgress: case kDownloadStart: { fMainWindow->PostMessage(msg); @@ -77,8 +71,10 @@ App::MessageReceived(BMessage* msg) } case kClearQueue: { + fFeedController->MessageReceived(msg); break; } + case kProgress: case kParseComplete: case kParseFail: case kDownloadFail: diff --git a/src/FeedController.cpp b/src/FeedController.cpp index ebb6508..49b9231 100644 --- a/src/FeedController.cpp +++ b/src/FeedController.cpp @@ -20,11 +20,13 @@ FeedController::FeedController() : + fEnqueuedTotal(0), fMainThread(find_thread(NULL)), fDownloadThread(0), fParseThread(0), fDownloadQueue(new BList()), fMessageRunner(new BMessageRunner(be_app, BMessage(kControllerCheck), 50000, -1)) + { fDownloadThread = spawn_thread(_DownloadLoop, "here, eat this", B_NORMAL_PRIORITY, &fMainThread); @@ -58,6 +60,7 @@ FeedController::MessageReceived(BMessage* msg) _EnqueueFeed((Feed*)data); i++; } + _SendProgress(); break; } case kUpdateSubscribed: @@ -66,21 +69,18 @@ FeedController::MessageReceived(BMessage* msg) for (int i = 0; i < subFeeds.CountItems(); i++) { _EnqueueFeed((Feed*)subFeeds.ItemAt(i)); } + _SendProgress(); break; } case kClearQueue: { + fDownloadQueue->MakeEmpty(); break; } case kControllerCheck: { _ProcessQueueItem(); - _CheckStatus(); - break; - } - default: - { -// BWindow::MessageReceived(msg); + _ReceiveStatus(); break; } } @@ -100,6 +100,24 @@ FeedController::SubscribedFeeds() } +void +FeedController::_SendProgress() +{ + int32 dqCount = fDownloadQueue->CountItems(); + + if (fEnqueuedTotal < dqCount) + fEnqueuedTotal = dqCount; + + BMessage progress(kProgress); + progress.AddInt32("total", fEnqueuedTotal); + progress.AddInt32("current", fEnqueuedTotal - dqCount); + be_app->MessageReceived(&progress); + + if (dqCount == 0) + fEnqueuedTotal = 0; +} + + void FeedController::_EnqueueFeed(Feed* feed) { @@ -116,15 +134,15 @@ FeedController::_ProcessQueueItem() send_data(fDownloadThread, 0, (void*)buffer, sizeof(Feed)); BMessage downloadInit = BMessage(kDownloadStart); - downloadInit.AddString("feed_url", buffer->GetXmlUrl().UrlString()); downloadInit.AddString("feed_name", buffer->GetTitle()); + downloadInit.AddString("feed_url", buffer->GetXmlUrl().UrlString()); ((App*)be_app)->MessageReceived(&downloadInit); } } void -FeedController::_CheckStatus() +FeedController::_ReceiveStatus() { thread_id sender; @@ -137,6 +155,7 @@ FeedController::_CheckStatus() case kDownloadComplete: { BMessage complete = BMessage(kDownloadComplete); + complete.AddString("feed_name", feedBuffer->GetTitle()); complete.AddString("feed_url", feedBuffer->GetXmlUrl().UrlString()); ((App*)be_app)->MessageReceived(&complete); @@ -147,26 +166,31 @@ FeedController::_CheckStatus() case kDownloadFail: { BMessage failure = BMessage(kDownloadFail); + failure.AddString("feed_name", feedBuffer->GetTitle()); failure.AddString("feed_url", feedBuffer->GetXmlUrl().UrlString()); ((App*)be_app)->MessageReceived(&failure); - break; - } - case kParseComplete: - { - BMessage complete = BMessage(kParseComplete); - complete.AddString("feed_url", feedBuffer->GetXmlUrl().UrlString()); - complete.AddInt32("entry_count", feedBuffer->GetNewEntries().CountItems()); - ((App*)be_app)->MessageReceived(&complete); + _SendProgress(); break; } case kParseFail: { BMessage failure = BMessage(kParseFail); + failure.AddString("feed_name", feedBuffer->GetTitle()); failure.AddString("feed_url", feedBuffer->GetXmlUrl().UrlString()); ((App*)be_app)->MessageReceived(&failure); + _SendProgress(); break; } + // If parse was successful, the code is the amount of new entries + default: + BMessage complete = BMessage(kParseComplete); + complete.AddString("feed_name", feedBuffer->GetTitle()); + complete.AddString("feed_url", feedBuffer->GetXmlUrl().UrlString()); + complete.AddInt32("entry_count", code); + ((App*)be_app)->MessageReceived(&complete); + _SendProgress(); + break; } } } @@ -209,6 +233,7 @@ FeedController::_ParseLoop(void* data) int32 code = receive_data(&sender, (void*)feedBuffer, sizeof(Feed)); BList entries; + int32 entriesCount; BString feedTitle; BUrl feedUrl = feedBuffer->GetXmlUrl(); BDirectory outDir = BDirectory(((App*)be_app)->fPreferences->EntryDir()); @@ -218,9 +243,10 @@ FeedController::_ParseLoop(void* data) feed = new AtomFeed(feedBuffer); feed->Parse(); entries = feed->GetNewEntries(); + entriesCount = entries.CountItems(); feedTitle = feed->GetTitle(); - for (int i = 0; i < entries.CountItems(); i++) + for (int i = 0; i < entriesCount; i++) ((Entry*)entries.ItemAt(i))->Filetize(outDir); delete feed; } @@ -229,19 +255,20 @@ FeedController::_ParseLoop(void* data) feed = new RssFeed(feedBuffer); feed->Parse(); entries = feed->GetNewEntries(); + entriesCount = entries.CountItems(); feedTitle = feed->GetTitle(); - for (int i = 0; i < entries.CountItems(); i++) + for (int i = 0; i < entriesCount; i++) ((Entry*)entries.ItemAt(i))->Filetize(outDir); delete feed; } if (feedBuffer->IsAtom() || feedBuffer->IsRss()) { - send_data(main, kParseComplete, (void*)feedBuffer, sizeof(Feed)); + send_data(main, entriesCount, (void*)feedBuffer, sizeof(Feed)); } else { - send_data(main, kParseFail, (void*)feedBuffer, sizeof(Feed)); + send_data(main, entriesCount, (void*)feedBuffer, sizeof(Feed)); } } diff --git a/src/FeedController.h b/src/FeedController.h index 0c940ad..caf8815 100644 --- a/src/FeedController.h +++ b/src/FeedController.h @@ -16,6 +16,7 @@ class Feed; enum { + kProgress = 'npro', kEnqueueFeed = 'fenq', kClearQueue = 'frmq', kDownloadStart = 'fdst', @@ -38,12 +39,17 @@ public: static BList SubscribedFeeds(); private: + void _SendProgress(); + + void _EnqueueFeed(Feed* feed); + + void _ProcessQueueItem(); + void _ReceiveStatus(); + static int32 _DownloadLoop(void* data); static int32 _ParseLoop(void* data); - void _EnqueueFeed(Feed* feed); - void _ProcessQueueItem(); - void _CheckStatus(); + int32 fEnqueuedTotal; thread_id fMainThread; thread_id fDownloadThread; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 6e32a36..a3a0b3d 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -60,13 +60,12 @@ MainWindow::MessageReceived(BMessage *msg) case kProgress: { fFeedsView->MessageReceived(msg); - int32 max = 0; - int32 current = 0; + int32 total,current = 0; - if (msg->FindInt32("max", &max) == B_OK + if (msg->FindInt32("total", &total) == B_OK && msg->FindInt32("current", ¤t) == B_OK) { - _UpdateProgress(max, current); + _UpdateProgress(total, current); } break; } @@ -120,12 +119,12 @@ MainWindow::_InitInterface() void -MainWindow::_UpdateProgress(int32 max, int32 current) +MainWindow::_UpdateProgress(int32 total, int32 current) { - int32 prog = max - current; - - fStatusBar->SetMaxValue(max); - fStatusBar->SetTo(prog); + if (current < fStatusBar->CurrentValue()) + fStatusBar->Reset(); + fStatusBar->SetMaxValue(total); + fStatusBar->SetTo(current); } diff --git a/src/MainWindow.h b/src/MainWindow.h index 1fd0955..bb6e6fd 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -22,7 +22,7 @@ public: private: void _InitInterface(); - void _UpdateProgress(int32 max, int32 current); + void _UpdateProgress(int32 total, int32 current); BGroupView* fBaseView; BTabView* fTabView; diff --git a/src/Notifier.cpp b/src/Notifier.cpp index 4a28de9..1f22592 100644 --- a/src/Notifier.cpp +++ b/src/Notifier.cpp @@ -5,6 +5,7 @@ #include "Notifier.h" +#include #include #include @@ -14,8 +15,9 @@ Notifier::Notifier() : - fEnqueuedFeeds(0), - fFeedsInProgress(0) + fFailedFeeds(new BList()), + fUpdatedFeeds(new BList()), + fTotalEntries(0) { } @@ -25,45 +27,44 @@ Notifier::MessageReceived(BMessage* msg) { switch (msg->what) { - case kEnqueueFeed: + case kProgress: { - fEnqueuedFeeds++; - fFeedsInProgress++; - _UpdateProgress(); + int32 total, current = 0; + + if (msg->FindInt32("total", &total) == B_OK + && msg->FindInt32("current", ¤t) == B_OK + && total == current) + { + _SendNotifications(); + } break; } case kParseComplete: { BString feedName; + BString feedUrl; int32 entryCount; - if (msg->FindString("feed_name", &feedName) == B_OK + if ((msg->FindString("feed_name", &feedName) == B_OK + || msg->FindString("feed_url", &feedUrl) == B_OK) && msg->FindInt32("entry_count", &entryCount) == B_OK) { if (entryCount > 0) - _NewEntryNotification(feedName, entryCount); + _SaveUpdated(feedName, feedUrl, entryCount); } - - fFeedsInProgress--; - _UpdateProgress(); - break; - } - case kParseFail: - { - BString feedUrl = msg->GetString("feed_url", ""); - _ParseFailNotification(feedUrl); - - fFeedsInProgress--; - _UpdateProgress(); break; } case kDownloadFail: + case kParseFail: { - BString feedUrl = msg->GetString("feed_url", ""); - _DownloadFailNotification(feedUrl); + BString feedName; + BString feedUrl; - fFeedsInProgress--; - _UpdateProgress(); + if (msg->FindString("feed_name", &feedName) == B_OK + || msg->FindString("feed_url", &feedUrl) == B_OK) + { + _SaveFailed(feedName, feedUrl); + } break; } } @@ -71,19 +72,40 @@ Notifier::MessageReceived(BMessage* msg) void -Notifier::_NewEntryNotification(BString feedName, int32 entryCount) +Notifier::_SendNotifications() { - if (((App*)be_app)->fPreferences->fNewNotify == false) + _SendUpdatedNotification(); + _SendFailedNotification(); + + fFailedFeeds->MakeEmpty(); + fUpdatedFeeds->MakeEmpty(); + fTotalEntries = 0; +} + + +void +Notifier::_SendUpdatedNotification() +{ + if (((App*)be_app)->fPreferences->fNewNotify == false + || fTotalEntries == 0) { return; + } BNotification notifyNew(B_INFORMATION_NOTIFICATION); - BString notifyLabel("New Feed Entries"); + BString notifyLabel("Feed Updates"); BString notifyText("%n% new entries from %source%"); - BString numStr(""); - numStr << entryCount; - notifyText.ReplaceAll("%source%", feedName); - notifyText.ReplaceAll("%n%", numStr); + if (fUpdatedFeeds->CountItems() > 1) + notifyText = "%n% new entries from %source% and %m% others"; + + BString entryNum,feedNum = ""; + entryNum << fTotalEntries; + feedNum << fUpdatedFeeds->CountItems(); + + notifyText.ReplaceAll("%n%", entryNum); + notifyText.ReplaceAll("%m%", feedNum); + notifyText.ReplaceAll("%source%", + ((BString*)fUpdatedFeeds->ItemAt(0))->String()); notifyNew.SetTitle(notifyLabel); notifyNew.SetContent(notifyText); @@ -92,56 +114,53 @@ Notifier::_NewEntryNotification(BString feedName, int32 entryCount) void -Notifier::_ParseFailNotification(BString feedUrl) +Notifier::_SendFailedNotification() { - if (((App*)be_app)->fPreferences->fFailureNotify == false) + if (((App*)be_app)->fPreferences->fFailureNotify == false + || fFailedFeeds->CountItems() == 0) { return; + } BNotification notifyError(B_ERROR_NOTIFICATION); - BString notifyText("Failed to parse feed from %url%"); + BString notifyLabel("Update Failure"); + BString notifyText("Failed to update %source%"); - if (feedUrl.IsEmpty()) - notifyText = "Failed to parse a feed"; + if (fFailedFeeds->CountItems() > 1) + notifyText = "Failed to update %source% and %m% others"; - notifyText.ReplaceAll("%url%", feedUrl); + BString feedNum = ""; + feedNum << fFailedFeeds->CountItems(); - notifyError.SetTitle("Parse Failure"); + notifyText.ReplaceAll("%m%", feedNum); + notifyText.ReplaceAll("%source%", + ((BString*)fFailedFeeds->ItemAt(0))->String()); + + notifyError.SetTitle(notifyLabel); notifyError.SetContent(notifyText); notifyError.Send(); } void -Notifier::_DownloadFailNotification(BString feedUrl) +Notifier::_SaveUpdated(BString feedName, BString feedUrl, int32 entryCount) { - if (((App*)be_app)->fPreferences->fFailureNotify == false) - return; + BString name = feedName; + if (feedName.IsEmpty()) + name = feedUrl; - BNotification notifyError(B_ERROR_NOTIFICATION); - BString notifyText("Failed to download feed from %url%"); - - if (feedUrl.IsEmpty()) - notifyText = "Failed to download a feed"; - - notifyText.ReplaceAll("%url%", feedUrl); - - notifyError.SetTitle("Download Failure"); - notifyError.SetContent(notifyText); - notifyError.Send(); + fTotalEntries += entryCount; + fUpdatedFeeds->AddItem(new BString(feedName)); } void -Notifier::_UpdateProgress() +Notifier::_SaveFailed(BString feedName, BString feedUrl) { - BMessage progress = BMessage(kProgress); - progress.AddInt32("max", fEnqueuedFeeds); - progress.AddInt32("current", fFeedsInProgress); + BString name = feedName; + if (feedName.IsEmpty()) + name = feedUrl; - ((App*)be_app)->MessageReceived(&progress); - - if (fFeedsInProgress == 0) - fEnqueuedFeeds = 0; + fFailedFeeds->AddItem(new BString(feedName)); } diff --git a/src/Notifier.h b/src/Notifier.h index 2565100..a7de69b 100644 --- a/src/Notifier.h +++ b/src/Notifier.h @@ -7,16 +7,11 @@ #include +class BList; class BString; class BMessage; -enum -{ - kProgress = 'npro' -}; - - class Notifier { public: Notifier(); @@ -24,14 +19,16 @@ public: void MessageReceived(BMessage* msg); private: - void _NewEntryNotification(BString feedName, int32 feedCount); - void _ParseFailNotification(BString feedUrl); - void _DownloadFailNotification(BString feedUrl); + void _SendNotifications(); + void _SendUpdatedNotification(); + void _SendFailedNotification(); - void _UpdateProgress(); + void _SaveUpdated(BString feedName, BString feedUrl, int32 feedCount); + void _SaveFailed(BString feedName, BString feedUrl); - int32 fEnqueuedFeeds; - int32 fFeedsInProgress; + BList* fFailedFeeds; + BList* fUpdatedFeeds; + int32 fTotalEntries; };