diff --git a/Makefile b/Makefile index a0ff428..35c011d 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,7 @@ SRCS = \ src/Feed.cpp \ src/FeedEditWindow.cpp \ src/FeedListItem.cpp \ + src/FeedListView.cpp \ src/FeedsView.cpp \ src/MainWindow.cpp \ src/Mimetypes.cpp \ diff --git a/src/FeedController.cpp b/src/FeedController.cpp index f2238f3..4dae1d2 100644 --- a/src/FeedController.cpp +++ b/src/FeedController.cpp @@ -59,13 +59,19 @@ FeedController::MessageReceived(BMessage* msg) case kEnqueueFeed: { int i = 0; - const void* data; + BString feedID; + BString feedSource; ssize_t size = sizeof(Feed); - while (msg->HasData("feeds", B_RAW_TYPE, i)) { - msg->FindData("feeds", B_RAW_TYPE, i, &data, &size); - fDownloadQueue->AddItem((Feed*)data); + while (msg->HasString("feed_identifiers", i)) { + msg->FindString("feed_identifiers", i, &feedID); + msg->FindString("feed_sources", i, &feedSource); + + Feed* feed = SourceManager::GetFeed(feedID.String(), + feedSource.String()); + fDownloadQueue->AddItem(feed); _SendProgress(); + i++; } fMessageRunner->SetCount(-1); break; diff --git a/src/FeedEditWindow.cpp b/src/FeedEditWindow.cpp index f861476..f376fd9 100644 --- a/src/FeedEditWindow.cpp +++ b/src/FeedEditWindow.cpp @@ -152,10 +152,11 @@ FeedEditWindow::_SaveFeed() SourceManager::EditFeed(fFeed); BMessage edited(kFeedsEdited); -// BMessage enqueueUpdated(kEnqueueFeed); -// enqueueUpdated.AddData("feeds", B_RAW_TYPE, &fFeed, sizeof(Feed)); -// -// ((App*)be_app)->MessageReceived(&enqueueUpdated); + BMessage enqueueUpdated(kEnqueueFeed); + enqueueUpdated.AddString("feed_identifiers", fFeed->Identifier()); + enqueueUpdated.AddString("feed_sources", fFeed->Source()); + + ((App*)be_app)->MessageReceived(&enqueueUpdated); ((App*)be_app)->PostMessage(&edited); Quit(); } diff --git a/src/FeedListItem.cpp b/src/FeedListItem.cpp index a3fc211..b049485 100644 --- a/src/FeedListItem.cpp +++ b/src/FeedListItem.cpp @@ -24,6 +24,7 @@ FeedListItem::FeedListItem(Feed* feed) fFeedIdentifier(feed->Identifier()), fFeedSource(feed->Source()) { + fFeed = feed; if (feed->Title().IsEmpty() == true) SetText(B_TRANSLATE("Untitled Feed")); } @@ -87,3 +88,10 @@ FeedListItem::SetStatus(int8 status) } +Feed* +FeedListItem::GetFeed() +{ + return fFeed; +} + + diff --git a/src/FeedListItem.h b/src/FeedListItem.h index a9e5f99..5454f89 100644 --- a/src/FeedListItem.h +++ b/src/FeedListItem.h @@ -31,6 +31,7 @@ public: BUrl FeedUrl(); const char* FeedIdentifier(); const char* FeedSource(); + Feed* GetFeed(); void SetStatus(int8 status); @@ -39,6 +40,7 @@ private: BUrl fFeedUrl; BString fFeedIdentifier; BString fFeedSource; + Feed* fFeed; }; diff --git a/src/FeedListView.cpp b/src/FeedListView.cpp new file mode 100644 index 0000000..f85efb3 --- /dev/null +++ b/src/FeedListView.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "FeedListView.h" + +#include +#include +#include +#include +#include + +#include "App.h" + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "FeedListView" + + +FeedListView::FeedListView(const char* name) + : BOutlineListView(name) +{ +} + + +void +FeedListView::MouseDown(BPoint where) +{ + BOutlineListView::MouseDown(where); + + uint32 buttons = 0; + Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); + + if (!(buttons & B_SECONDARY_MOUSE_BUTTON)) + return; + + BMenuItem* item; + int32 selIndex = CurrentSelection(); + if (Superitem(ItemAt(selIndex)) == NULL) + item = _SourcePopUp()->Go(ConvertToScreen(where)); + else + item = _FeedPopUp()->Go(ConvertToScreen(where)); + + if (item != NULL) + Window()->MessageReceived(item->Message()); + return; +} + + +BPopUpMenu* +FeedListView::_FeedPopUp() +{ + BPopUpMenu* menu = new BPopUpMenu("feedPopUp"); + menu->SetTargetForItems(Window()); + menu->AddItem(new BMenuItem(B_TRANSLATE("Update feed"), + new BMessage(kFeedsEnqueueSelected))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Edit feed…"), + new BMessage(kFeedsEditSelected))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Remove feed…"), + new BMessage(kFeedsRemoveSelected))); + + return menu; +} + + +BPopUpMenu* +FeedListView::_SourcePopUp() +{ + BMessage enqueue(kFeedsEnqueueSelected); + + BPopUpMenu* menu = new BPopUpMenu("sourcePopUp"); + menu->AddItem(new BMenuItem(B_TRANSLATE("Update source"), + new BMessage(kFeedsEnqueueSelected))); +// menu->AddItem(BMenuItem("Configure source…", BMessage(''))); +// menu->AddItem(BMenuItem("Remove source…", BMessage(''))); + return menu; +} + + diff --git a/src/FeedListView.h b/src/FeedListView.h new file mode 100644 index 0000000..9fc73b4 --- /dev/null +++ b/src/FeedListView.h @@ -0,0 +1,35 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef FEEDLISTVIEW_H +#define FEEDLISTVIEW_H + +#include +#include + +class BPopUpMenu; + + +enum +{ + kFeedsRemoveSelected = 'srem', + kFeedsEditSelected = 'sedt', + kFeedsEnqueueSelected = 'senq' +}; + + +class FeedListView : public BOutlineListView { +public: + FeedListView(const char* name); + + void MouseDown(BPoint where); + +private: + BPopUpMenu* _FeedPopUp(); + BPopUpMenu* _SourcePopUp(); +}; + + +#endif // FEEDLISTVIEW_H + diff --git a/src/FeedSource.h b/src/FeedSource.h deleted file mode 100644 index e28c32a..0000000 --- a/src/FeedSource.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021, Jaidyn Levesque - * All rights reserved. Distributed under the terms of the MIT license. - */ -#ifndef FEEDSOURCE_H -#define FEEDSOURCE_H - -#include - -#include "Feed.h" - - -// Hierarchy: FeedSource → Feed → Entry -// TODO: RemoveFeed(), AddFeed(), etc. -class FeedSource { -public: - static BStringList FeedIdentifiers(); - - Feed RemoveFeed(Feed feed); - Feed RemoveFeed(const char* identifier); -}; - - -#endif // FEEDSOURCE_H - diff --git a/src/FeedsView.cpp b/src/FeedsView.cpp index 40ed11c..57d53b5 100644 --- a/src/FeedsView.cpp +++ b/src/FeedsView.cpp @@ -21,6 +21,7 @@ #include "FeedController.h" #include "FeedEditWindow.h" #include "FeedListItem.h" +#include "FeedListView.h" #include "Notifier.h" #include "SourceListItem.h" #include "SourceManager.h" @@ -43,25 +44,30 @@ FeedsView::MessageReceived(BMessage* msg) { switch (msg->what) { - case kFeedsAddButton: + case kFeedsEnqueueSelected: + { + _UpdateSelected(); + break; + } + case kFeedsRemoveSelected: + { + if (_RemoveSelected() == true) + _PopulateFeedList(); + break; + } + case kFeedsEditSelected: + { + if (fFeedsListView->CurrentSelection() >= 0) + _EditSelected(); + break; + } + case kFeedsAddNew: { FeedEditWindow* edit = new FeedEditWindow(); edit->Show(); edit->Activate(); break; } - case kFeedsRemoveButton: - { - _RemoveSelectedFeed(); - _PopulateFeedList(); - break; - } - case kFeedsEditButton: - { - if (fFeedsListView->CurrentSelection() >= 0) - _EditSelectedFeed(); - break; - } case kFeedsSelected: { bool enabled = msg->GetInt32("index", -1) >= 0; @@ -116,23 +122,24 @@ void FeedsView::_InitInterface() { // Feeds list - fFeedsListView = new BOutlineListView("feedsList"); + fFeedsListView = new FeedListView("feedsList"); fFeedsScrollView = new BScrollView("feedsScroll", fFeedsListView, B_WILL_DRAW, false, true); fFeedsListView->SetSelectionMessage(new BMessage(kFeedsSelected)); - fFeedsListView->SetInvocationMessage(new BMessage(kFeedsEditButton)); + fFeedsListView->SetInvocationMessage(new BMessage(kFeedsEditSelected)); _PopulateFeedList(); fProgressLabel = new BStringView("progressLabel", ""); // Add, Remove, Edit - fAddButton = new BButton("addFeed", "+", new BMessage(kFeedsAddButton)); - fRemoveButton = new BButton("removeFeed", "-", new BMessage(kFeedsRemoveButton)); + fAddButton = new BButton("addFeed", "+", new BMessage(kFeedsAddNew)); + fRemoveButton = new BButton("removeFeed", "-", + new BMessage(kFeedsRemoveSelected)); fAddButton->SetToolTip(B_TRANSLATE("Add new feed")); fRemoveButton->SetToolTip(B_TRANSLATE("Remove selected feed")); fEditButton = new BButton("editFeed", B_TRANSLATE("Edit…"), - new BMessage(kFeedsEditButton)); + new BMessage(kFeedsEditSelected)); font_height fontHeight; GetFontHeight(&fontHeight); @@ -184,22 +191,62 @@ FeedsView::_InitInterface() .End(); } - void -FeedsView::_EditSelectedFeed() +FeedsView::_UpdateSelected() { int32 selIndex = fFeedsListView->CurrentSelection(); - FeedListItem* selected = (FeedListItem*)fFeedsListView->ItemAt(selIndex); - FeedEditWindow* edit = new FeedEditWindow(selected->FeedIdentifier(), - selected->FeedSource()); - edit->Show(); - edit->Activate(); + // Enqueue single feed + if (fFeedsListView->Superitem(fFeedsListView->ItemAt(selIndex)) != NULL) { + FeedListItem* selected = (FeedListItem*)fFeedsListView->ItemAt(selIndex); + + BMessage enqueue(kEnqueueFeed); + enqueue.AddString("feed_identifiers", selected->FeedIdentifier()); + enqueue.AddString("feed_sources", selected->FeedSource()); + + ((App*)be_app)->MessageReceived(&enqueue); + } + // Enqueue feeds from a source + else { + BMessage enqueue(kEnqueueFeed); + SourceListItem* selected = (SourceListItem*)fFeedsListView->ItemAt(selIndex); + BObjectList feeds = selected->FeedSource()->Feeds(); + + for (int i = 0; i < feeds.CountItems(); i++) { + Feed* selected = feeds.ItemAt(i); + enqueue.AddString("feed_identifiers", selected->Identifier()); + enqueue.AddString("feed_sources", selected->Source()); + } + ((App*)be_app)->MessageReceived(&enqueue); + } } void -FeedsView::_RemoveSelectedFeed() +FeedsView::_EditSelected() +{ + int32 selIndex = fFeedsListView->CurrentSelection(); + + if (fFeedsListView->Superitem(fFeedsListView->ItemAt(selIndex)) != NULL) { + FeedListItem* selected = (FeedListItem*)fFeedsListView->ItemAt(selIndex); + + FeedEditWindow* edit = new FeedEditWindow(selected->FeedIdentifier(), + selected->FeedSource()); + + edit->Show(); + edit->Activate(); + } + else { + SourceListItem* selected = (SourceListItem*)fFeedsListView->ItemAt(selIndex); + Source* source = selected->FeedSource(); +// if (source->IsConfigurable() == true) + // … Do something about that + } +} + + +bool +FeedsView::_RemoveSelected() { BAlert* alert = new BAlert(B_TRANSLATE("Confirm removal"), B_TRANSLATE("Are you sure you want to remove the selected feed?"), @@ -209,13 +256,17 @@ FeedsView::_RemoveSelectedFeed() alert->SetShortcut(1, B_ESCAPE); int32 button = alert->Go(); if (button != 0) - return; + return false; int32 selIndex = fFeedsListView->CurrentSelection(); FeedListItem* selected = (FeedListItem*)fFeedsListView->ItemAt(selIndex); + if (fFeedsListView->Superitem(selected) == NULL) + return false; + SourceManager::RemoveFeed(SourceManager::GetFeed(selected->FeedIdentifier(), selected->FeedSource())); + return true; } diff --git a/src/FeedsView.h b/src/FeedsView.h index caaf38c..545473c 100644 --- a/src/FeedsView.h +++ b/src/FeedsView.h @@ -10,18 +10,16 @@ #include class BMessage; -class BOutlineListView; +class FeedListView; class BScrollView; class BStringView; enum { - kFeedsAddButton = 'sadd', - kFeedsRemoveButton = 'srem', - kFeedsEditButton = 'sedt', - kFeedsSelected = 'flsl', - kFeedsEdited = 'fedd' + kFeedsAddNew = 'sadd', + kFeedsSelected = 'flsl', + kFeedsEdited = 'fedd' }; @@ -34,8 +32,9 @@ public: private: void _InitInterface(); - void _EditSelectedFeed(); - void _RemoveSelectedFeed(); + void _UpdateSelected(); + void _EditSelected(); + bool _RemoveSelected(); void _PopulateFeedList(); @@ -45,7 +44,7 @@ private: BButton* fRemoveButton; BButton* fEditButton; BStringView* fProgressLabel; - BOutlineListView* fFeedsListView; + FeedListView* fFeedsListView; BScrollView* fFeedsScrollView; }; diff --git a/src/LocalSource.cpp b/src/LocalSource.cpp deleted file mode 100644 index 6d56c9f..0000000 --- a/src/LocalSource.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright 2021, Jaidyn Levesque - * All rights reserved. Distributed under the terms of the MIT license. - */ - -#include "LocalSource.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "Feed.h" -#include "Util.h" - -#undef B_TRANSLATION_CONTEXT -#define B_TRANSLATION_CONTEXT "LocalSource" - - -LocalSource::LocalSource() -{ - BDirectory subDir = BDirectory(_SubscriptionPath().Path()); - if (subDir.InitCheck() == B_ENTRY_NOT_FOUND) { -// subDir.CreateDirectory(subPath.Path(), &subDir); - -// subPath.Append("Haiku Project"); -// Feed defaultSub(BUrl("https://www.haiku-os.org/blog/index.xml"), -// BEntry(subPath.Path())); -// defaultSub.SetTitle("Haiku Project"); -// defaultSub.Filetize(); - } -} - - -BObjectList -LocalSource::Feeds() -{ - BDirectory subDir = BDirectory(_SubscriptionPath().Path()); - BEntry feedEntry; - BPath feedPath; - - BObjectList feeds; - - while (subDir.GetNextEntry(&feedEntry) == B_OK - && feedEntry.GetPath(&feedPath) == B_OK) - { - Feed* feed = GetFeed(feedPath.Path()); - feeds.AddItem(feed); - } - - return feeds; -} - - -Feed* -LocalSource::GetFeed(const char* identifier) -{ - BFile file(identifier, B_READ_ONLY); - time_t tt_lastDate = 0; - BDateTime lastDate; - BString title; - BString url; - BString hash; - - file.ReadAttrString("Feed:name", &title); - file.ReadAttrString("META:url", &url); - file.ReadAttrString("Feed:hash", &hash); - file.ReadAttr("Feed:when", B_TIME_TYPE, 0, &tt_lastDate, sizeof(time_t)); - lastDate.SetTime_t(tt_lastDate); - - Feed* feed = new Feed(identifier, title.String(), url.String()); - feed->SetHash(hash); - feed->SetLastDate(lastDate); - return feed; -} - - -bool -LocalSource::Fetch(Feed* feed) -{ - BFile cacheFile = BFile(feed->Identifier(), B_READ_WRITE | B_CREATE_FILE); - BString hash; - - int32 result = fetch(feed->Url(), &cacheFile, &hash, 30); - feed->SetHash(hash); - - if (result == 0) - return true; - return false; -} - - -bool -LocalSource::Parse(Feed* feed) -{ - if (IsUpdated(feed) == false) - return true; - - if (_IsAtom(feed) == true) - return _AtomParse(feed); - else if (_IsRss(feed) == true) - return _RssParse(feed); - return false; -} - - -void -LocalSource::AddFeed(Feed* newFeed) -{ - if (newFeed->Identifier().IsEmpty() == true) { - BPath subPath = _SubscriptionPath(); - subPath.Append(urlToFilename(newFeed->Url())); - newFeed->SetIdentifier(subPath.Path()); - } - EditFeed(newFeed); -} - - -void -LocalSource::EditFeed(Feed* updated) -{ - Feed* old = GetFeed(updated->Identifier()); - BFile file(updated->Identifier(), B_READ_WRITE | B_CREATE_FILE); - - if (old->Title() != updated->Title()) { - BString title = updated->Title(); - file.WriteAttrString("Feed:name", &title); - } - if (old->Url() != updated->Url()) { - BString url = updated->Url().UrlString(); - file.WriteAttrString("META:url", &url); - } - if (old->Hash() != updated->Hash()) { - BString hash = updated->Hash(); - file.WriteAttrString("Feed:hash", &hash); - } - if (old->Date() != updated->Date()) { - time_t tt_date = updated->Date().Time_t(); - file.WriteAttr("Feed:when", B_TIME_TYPE, 0, &tt_date, sizeof(time_t)); - } - - BString type("application/x-feed-source"); - file.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, type.String(), - type.CountChars() + 1); -} - - -void -LocalSource::RemoveFeed(Feed* mortonta) -{ - BEntry entry(mortonta->Identifier().String()); - entry.Remove(); -} - - -bool -LocalSource::IsUpdated(Feed* feed) -{ - return (GetFeed(feed->Identifier())->Hash() != feed->Hash()); -} - - -bool -LocalSource::_IsAtom(Feed* feed) -{ - tinyxml2::XMLDocument xml; - xml.LoadFile(feed->Identifier().String()); - - if (xml.FirstChildElement("feed")) - return true; - return false; -} - - -bool -LocalSource::_IsRss(Feed* feed) -{ - tinyxml2::XMLDocument xml; - xml.LoadFile(feed->Identifier().String()); - - if (xml.FirstChildElement("rss")) - return true; - return false; -} - - -bool -LocalSource::_AtomParse(Feed* atomFeed) -{ - tinyxml2::XMLDocument xml; - xml.LoadFile(atomFeed->Identifier().String()); - - tinyxml2::XMLElement* xfeed = xml.FirstChildElement("feed"); - - _AtomRootParse(atomFeed, xfeed); - _AtomEntriesParse(atomFeed, xfeed); - return true; -} - - -void -LocalSource::_AtomRootParse(Feed* feed, tinyxml2::XMLElement* xfeed) -{ - tinyxml2::XMLElement* xentry = xfeed->FirstChildElement("entry"); - - bool set = false; - - _SetTitle(feed, xfeed->FirstChildElement("title")); - - set = _SetDate(feed, xfeed->FirstChildElement("updated")); - if (!set) - set = _SetDate(feed, xfeed->FirstChildElement("published")); - if (!set && xentry) - set = _SetDate(feed, xentry->FirstChildElement("updated")); - if (!set && xentry) - set = _SetDate(feed, xentry->FirstChildElement("published")); - - BString logString(B_TRANSLATE("Channel '%source%' at %url%:\n")); - logString.ReplaceAll("%source%", feed->Title().String()); - logString.ReplaceAll("%url%", feed->Url().UrlString()); - - std::cout << logString.String(); -} - - -void -LocalSource::_AtomEntriesParse(Feed* feed, tinyxml2::XMLElement* xfeed) -{ - tinyxml2::XMLElement* xentry; - - xentry = xfeed->FirstChildElement("entry"); - - int entryCount = _XmlCountSiblings(xentry, "entry"); - BObjectList entries(entryCount, true); - - BString logString(B_TRANSLATE("\t-%count% entries-\n")); - BString entryStr; - entryStr << entryCount; - logString.ReplaceAll("%count%", entryStr); - - std::cout << logString.String(); - - while (xentry) { - Entry* newEntry = _AtomEntryParse(feed, xentry); - if (newEntry != NULL) - entries.AddItem(newEntry); - xentry = xentry->NextSiblingElement("entry"); - } - - feed->SetEntries(entries); -} - - -Entry* -LocalSource::_AtomEntryParse(Feed* feed, tinyxml2::XMLElement* xentry) -{ - Entry* newEntry = new Entry(); - - tinyxml2::XMLElement* xcontent = xentry->FirstChildElement("content"); - tinyxml2::XMLElement* xmedia = xentry->FirstChildElement("media:group"); - tinyxml2::XMLPrinter xprinter; - - newEntry->SetTitle(xentry->FirstChildElement("title")); - newEntry->SetPostUrl(xentry->FirstChildElement("link")->Attribute("href")); - newEntry->SetFeedTitle(feed->Title()); - - bool set = false; - set = newEntry->SetDescription(xentry->FirstChildElement("summary")); - if (!set) - set = newEntry->SetDescription(xentry->FirstChildElement("description")); - if (!set && xmedia) - set = newEntry->SetDescription( - xmedia->FirstChildElement("media:description")); - - set = _SetDate(newEntry, xentry->FirstChildElement("updated")); - if (!set) - set = _SetDate(newEntry, xentry->FirstChildElement("published")); - - if (feed->Date() == NULL || feed->Date() < newEntry->Date()) - feed->SetDate(newEntry->Date()); - - if (xcontent) { - xcontent->Accept(&xprinter); - newEntry->SetContent(xprinter.CStr()); - } - - return newEntry; -} - - -bool -LocalSource::_RssParse(Feed* feed) -{ - tinyxml2::XMLDocument xml; - xml.LoadFile(feed->Identifier().String()); - - tinyxml2::XMLElement* xchan = xml.FirstChildElement("rss")->FirstChildElement("channel"); - - _RssRootParse(feed, xchan); - _RssEntriesParse(feed, xchan); - return true; -} - - -void -LocalSource::_RssRootParse(Feed* feed, tinyxml2::XMLElement* xchan) -{ - _SetTitle(feed, xchan->FirstChildElement("title")); - _SetDate(feed, xchan->FirstChildElement("lastBuildDate")); - - BString logString(B_TRANSLATE("Channel '%source%' at %url%:\n")); - logString.ReplaceAll("%source%", feed->Title().String()); - logString.ReplaceAll("%url%", feed->Url().UrlString()); - - std::cout << logString.String(); -} - - -void -LocalSource::_RssEntriesParse(Feed* feed, tinyxml2::XMLElement* xchan) -{ - tinyxml2::XMLElement* xitem; - - xitem = xchan->FirstChildElement("item"); - - int entryCount = _XmlCountSiblings(xitem, "item"); - BObjectList entries = BObjectList(entryCount, true); - - BString logString(B_TRANSLATE("\t-%count% entries-\n")); - BString entryStr; - entryStr << entryCount; - logString.ReplaceAll("%count%", entryStr); - - std::cout << logString.String(); - - while (xitem) { - entries.AddItem(_RssEntryParse(feed, xitem)); - xitem = xitem->NextSiblingElement("item"); - } - feed->SetEntries(entries); -} - - -Entry* -LocalSource::_RssEntryParse(Feed* feed, tinyxml2::XMLElement* xitem) -{ - Entry* newEntry = new Entry(); - - newEntry->SetTitle(xitem->FirstChildElement("title")); - newEntry->SetDescription(xitem->FirstChildElement("description")); - _SetDate(newEntry, xitem->FirstChildElement("pubDate")); - newEntry->SetPostUrl(xitem->FirstChildElement("link")); - newEntry->SetContent(xitem->FirstChildElement("content:encoded")); - newEntry->SetFeedTitle(feed->Title()); - - if (feed->Date() == NULL || feed->Date() < newEntry->Date()) - feed->SetDate(newEntry->Date()); - - return newEntry; -} - - -bool -LocalSource::_SetTitle(Feed* feed, tinyxml2::XMLElement* elem) -{ - if (elem != NULL && feed->Title().IsEmpty() == true) - return feed->SetTitle(elem->GetText()); - return false; -} - -bool -LocalSource::_SetDate(Feed* feed, const char* dateCStr) -{ - if (dateCStr == NULL) - return false; - return feed->SetDate(feedDateToBDate(dateCStr)); -} - - -bool -LocalSource::_SetDate(Feed* feed, tinyxml2::XMLElement* elem) -{ - if (elem == NULL) - return false; - return _SetDate(feed, elem->GetText()); -} - - -bool -LocalSource::_SetDate(Entry* entry, const char* dateStr) -{ - if (dateStr == NULL) - return false; - return entry->SetDate(feedDateToBDate(dateStr)); -} - - -bool -LocalSource::_SetDate(Entry* entry, tinyxml2::XMLElement* elem) -{ - if (elem == NULL) - return false; - - return _SetDate(entry, elem->GetText()); -} - - -// Count the amount of siblings to an element of given type name -int -LocalSource::_XmlCountSiblings (tinyxml2::XMLElement* xsibling, - const char* sibling_name) -{ - int count = 0; - while (xsibling) { - count++; - xsibling = xsibling->NextSiblingElement(sibling_name); - } - return count; -} - - -BPath -LocalSource::_SubscriptionPath() -{ - BPath subPath; - find_directory(B_USER_SETTINGS_DIRECTORY, &subPath); - subPath.Append("Pogger"); - subPath.Append("Subscriptions"); - return subPath; -} - - diff --git a/src/LocalSource.h b/src/LocalSource.h deleted file mode 100644 index 8c2534c..0000000 --- a/src/LocalSource.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2021, Jaidyn Levesque - * All rights reserved. Distributed under the terms of the MIT license. - */ -#ifndef LOCALSOURCE_H -#define LOCALSOURCE_H - -#include "FeedSource.h" - -class LocalSource : public FeedSource { -public: - LocalSource(); - - static BObjectList Feeds(); - - static Feed* GetFeed(const char* identifier); - - static bool Fetch(Feed* feed); - static bool Parse(Feed* feed); - - static void AddFeed(Feed* newFeed); - static void EditFeed(Feed* updated); - static void RemoveFeed(Feed* mortonta); - - static bool IsUpdated(Feed* feed); - -private: - static bool _IsAtom(Feed* feed); - static bool _IsRss(Feed* feed); - - static bool _AtomParse(Feed* feed); - static void _AtomRootParse(Feed* feed, tinyxml2::XMLElement*); - static void _AtomEntriesParse(Feed* feed, tinyxml2::XMLElement*); - static Entry* _AtomEntryParse(Feed* feed, tinyxml2::XMLElement*); - - static bool _RssParse(Feed* feed); - static void _RssRootParse(Feed* feed, tinyxml2::XMLElement*); - static void _RssEntriesParse(Feed* feed, tinyxml2::XMLElement*); - static Entry* _RssEntryParse(Feed* feed, tinyxml2::XMLElement*); - - static bool _SetTitle(Feed* feed, tinyxml2::XMLElement*); - - static bool _SetDate(Feed* feed, const char*); - static bool _SetDate(Feed* feed, tinyxml2::XMLElement*); - static bool _SetDate(Entry* entry, const char*); - static bool _SetDate(Entry* entry, tinyxml2::XMLElement*); - - static int _XmlCountSiblings(tinyxml2::XMLElement*, const char*); - static BPath _SubscriptionPath(); -}; - - -#endif // LOCALSOURCE_H - diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 54ca0e8..7820689 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -17,6 +17,7 @@ #include "App.h" #include "EntriesView.h" #include "FeedController.h" +#include "FeedListView.h" #include "FeedsView.h" #include "Notifier.h" #include "UpdatesView.h" @@ -49,9 +50,10 @@ MainWindow::MessageReceived(BMessage *msg) { switch (msg->what) { - case kFeedsAddButton: - case kFeedsRemoveButton: - case kFeedsEditButton: + case kFeedsAddNew: + case kFeedsEnqueueSelected: + case kFeedsRemoveSelected: + case kFeedsEditSelected: case kFeedsSelected: case kFeedsEdited: case kDownloadStart: