Subscription adding/editing/removal
This commit is contained in:
parent
f67a9f3d28
commit
c6f5c4fed0
1
Makefile
1
Makefile
|
@ -36,6 +36,7 @@ SRCS = \
|
|||
src/EntriesView.cpp, \
|
||||
src/Feed.cpp, \
|
||||
src/FeedController.cpp \
|
||||
src/FeedEditWindow.cpp \
|
||||
src/FeedListItem.cpp \
|
||||
src/FeedsView.cpp, \
|
||||
src/MainWindow.cpp, \
|
||||
|
|
9
TODO.txt
9
TODO.txt
|
@ -1,6 +1,9 @@
|
|||
* Add subscriptions
|
||||
* Adding/editing from GUI
|
||||
* Do this for file refs when Feeds, too
|
||||
* Feeds list
|
||||
* Update when feeds are edited
|
||||
* Store feeds in kEnqueueFeeds/etc messages as paths? hmm
|
||||
* This way, if the user edits the feed after it is enqueued, the changes
|
||||
will be applied.
|
||||
* Support for clearing queue
|
||||
* Revamp configuration
|
||||
* Fix saving, etc.
|
||||
* Show progress
|
||||
|
|
16
src/App.cpp
16
src/App.cpp
|
@ -46,7 +46,7 @@ App::App() : BApplication("application/x-vnd.Pogger")
|
|||
fMainWindow->Show();
|
||||
|
||||
BMessage* updateMessage = new BMessage(kUpdateSubscribed);
|
||||
MessageReceived(updateMessage);
|
||||
// MessageReceived(updateMessage);
|
||||
fUpdateRunner = new BMessageRunner(this, updateMessage,
|
||||
cfg->updateInterval);
|
||||
}
|
||||
|
@ -58,11 +58,8 @@ App::MessageReceived(BMessage* msg)
|
|||
switch (msg->what)
|
||||
{
|
||||
case kEnqueueFeed:
|
||||
{
|
||||
fFeedController->MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
case kUpdateSubscribed:
|
||||
case kDownloadComplete:
|
||||
{
|
||||
fFeedController->MessageReceived(msg);
|
||||
break;
|
||||
|
@ -71,23 +68,18 @@ App::MessageReceived(BMessage* msg)
|
|||
{
|
||||
break;
|
||||
}
|
||||
case kParseFail:
|
||||
case kParseComplete:
|
||||
{
|
||||
fNotifier->MessageReceived(msg);
|
||||
fFeedController->MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
case kParseFail:
|
||||
case kDownloadFail:
|
||||
{
|
||||
fNotifier->MessageReceived(msg);
|
||||
fFeedController->MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
case kDownloadComplete:
|
||||
{
|
||||
fFeedController->MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// BApplication::MessageReceived(msg);
|
||||
|
|
|
@ -42,7 +42,7 @@ AtomFeed::Parse ()
|
|||
RootParse(xfeed);
|
||||
ParseEntries(xfeed);
|
||||
|
||||
_PostParse();
|
||||
Filetize();
|
||||
}
|
||||
|
||||
|
||||
|
|
44
src/Feed.cpp
44
src/Feed.cpp
|
@ -98,24 +98,6 @@ Feed::Parse()
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
Feed::_PostParse()
|
||||
{
|
||||
BFile feedFile(cachePath, B_WRITE_ONLY);
|
||||
time_t tt_date = date.Time_t();
|
||||
BString url = xmlUrl.UrlString();
|
||||
BString name = GetTitle();
|
||||
BString type("application/x-feed-source");
|
||||
|
||||
feedFile.WriteAttrString("Feed:name", &name);
|
||||
feedFile.WriteAttrString("META:url", &url);
|
||||
feedFile.WriteAttrString("BEOS:TYPE", &type);
|
||||
feedFile.WriteAttr("Feed:when", B_TIME_TYPE, 0, &tt_date, sizeof(time_t));
|
||||
feedFile.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, type.String(),
|
||||
type.CountChars() + 1);
|
||||
}
|
||||
|
||||
|
||||
// Download a remote feed's XML to the cache path.
|
||||
bool
|
||||
Feed::Fetch()
|
||||
|
@ -133,6 +115,32 @@ Feed::Fetch()
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
Feed::Filetize()
|
||||
{
|
||||
BFile feedFile(cachePath, B_WRITE_ONLY | B_CREATE_FILE);
|
||||
time_t tt_date = date.Time_t();
|
||||
BString url = xmlUrl.UrlString();
|
||||
BString name = GetTitle();
|
||||
BString type("application/x-feed-source");
|
||||
|
||||
feedFile.WriteAttrString("Feed:name", &name);
|
||||
feedFile.WriteAttrString("META:url", &url);
|
||||
feedFile.WriteAttrString("BEOS:TYPE", &type);
|
||||
feedFile.WriteAttr("Feed:when", B_TIME_TYPE, 0, &tt_date, sizeof(time_t));
|
||||
feedFile.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, type.String(),
|
||||
type.CountChars() + 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Feed::Unfiletize()
|
||||
{
|
||||
BEntry entry(GetCachePath().String());
|
||||
entry.Remove();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Feed::IsRss()
|
||||
{
|
||||
|
|
14
src/Feed.h
14
src/Feed.h
|
@ -34,28 +34,32 @@ public:
|
|||
|
||||
bool Fetch();
|
||||
|
||||
void Filetize();
|
||||
void Unfiletize();
|
||||
|
||||
bool IsRss();
|
||||
bool IsAtom();
|
||||
bool IsUpdated();
|
||||
|
||||
BString GetTitle();
|
||||
bool SetDate(BDateTime);
|
||||
|
||||
BUrl GetXmlUrl();
|
||||
BDateTime GetDate();
|
||||
|
||||
bool SetTitle(const char*);
|
||||
bool SetXmlUrl(BUrl newUrl);
|
||||
bool SetCachePath(BString path);
|
||||
|
||||
BString GetCachePath();
|
||||
|
||||
protected:
|
||||
bool SetTitle(const char*);
|
||||
bool SetTitle(tinyxml2::XMLElement*);
|
||||
bool SetDate(BDateTime);
|
||||
bool SetDate(const char*);
|
||||
bool SetDate(tinyxml2::XMLElement*);
|
||||
bool SetXmlUrl(BUrl newUrl);
|
||||
bool SetCachePath(BString path);
|
||||
|
||||
bool AddEntry(Entry*);
|
||||
|
||||
void _PostParse();
|
||||
int xmlCountSiblings(tinyxml2::XMLElement*, const char*);
|
||||
|
||||
BString title;
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "FeedEditWindow.h"
|
||||
|
||||
#include <Button.h>
|
||||
#include <Message.h>
|
||||
#include <LayoutBuilder.h>
|
||||
#include <SeparatorView.h>
|
||||
#include <StringView.h>
|
||||
#include <TextControl.h>
|
||||
|
||||
#include "App.h"
|
||||
#include "Feed.h"
|
||||
#include "FeedController.h"
|
||||
#include "FeedListItem.h"
|
||||
|
||||
|
||||
FeedEditWindow::FeedEditWindow()
|
||||
:
|
||||
BWindow(BRect(BPoint(-1000.0, -1000.0), BSize(500, 150)), "New Feed",
|
||||
B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
|
||||
{
|
||||
_InitInterface();
|
||||
MoveOnScreen();
|
||||
fDeleteButton->SetEnabled(false);
|
||||
|
||||
fFeed = new Feed();
|
||||
}
|
||||
|
||||
|
||||
FeedEditWindow::FeedEditWindow(BEntry feedEntry)
|
||||
:
|
||||
FeedEditWindow()
|
||||
{
|
||||
SetTitle("Edit Feed");
|
||||
fFeed = new Feed(feedEntry);
|
||||
|
||||
fFeedNameText->SetText(fFeed->GetTitle().String());
|
||||
fFeedUrlText->SetText(fFeed->GetXmlUrl().UrlString().String());
|
||||
|
||||
fDeleteButton->SetEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
FeedEditWindow::FeedEditWindow(FeedListItem* feedItem)
|
||||
:
|
||||
FeedEditWindow(BEntry(feedItem->GetFeedPath()))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FeedEditWindow::MessageReceived(BMessage* msg)
|
||||
{
|
||||
switch (msg->what)
|
||||
{
|
||||
case kSaveButton:
|
||||
{
|
||||
_SaveFeed();
|
||||
break;
|
||||
}
|
||||
case kDeleteButton:
|
||||
{
|
||||
_DeleteFeed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FeedEditWindow::_InitInterface()
|
||||
{
|
||||
// Name and URL
|
||||
fFeedNameLabel = new BStringView("feedNameLabel", "Feed name:");
|
||||
fFeedNameText = new BTextControl("feedName", "", "", NULL);
|
||||
fFeedUrlLabel = new BStringView("feedUrlLabel", "Feed URL:");
|
||||
fFeedUrlText = new BTextControl("feedUrl", "", "", NULL);
|
||||
|
||||
// Save/Delete
|
||||
fSaveButton = new BButton("save", "Save",
|
||||
new BMessage(kSaveButton));
|
||||
fDeleteButton = new BButton("delete", "Delete",
|
||||
new BMessage(kDeleteButton));
|
||||
|
||||
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
|
||||
.SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0)
|
||||
|
||||
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
|
||||
.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
|
||||
.SetInsets(B_USE_ITEM_INSETS, 0, 0, B_USE_ITEM_INSETS)
|
||||
.Add(fFeedNameLabel)
|
||||
.Add(fFeedUrlLabel)
|
||||
.End()
|
||||
.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
|
||||
.SetInsets(B_USE_ITEM_INSETS, 0, B_USE_ITEM_INSETS,
|
||||
B_USE_ITEM_INSETS)
|
||||
.Add(fFeedNameText)
|
||||
.Add(fFeedUrlText)
|
||||
.End()
|
||||
.End()
|
||||
|
||||
.Add(new BSeparatorView(B_HORIZONTAL))
|
||||
.AddGroup(B_HORIZONTAL)
|
||||
.AddGlue()
|
||||
.Add(fDeleteButton)
|
||||
.Add(fSaveButton)
|
||||
.SetInsets(B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING,
|
||||
B_USE_DEFAULT_SPACING, B_USE_WINDOW_SPACING)
|
||||
.End()
|
||||
.End();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FeedEditWindow::_SaveFeed()
|
||||
{
|
||||
BString subLocation("/boot/home/config/settings/Pogger/Subscriptions/");
|
||||
BString title(fFeedNameText->Text());
|
||||
const char* urlString = fFeedUrlText->Text();
|
||||
BString filename;
|
||||
if (title.IsEmpty())
|
||||
filename = BString(urlString);
|
||||
else
|
||||
filename = BString(title);
|
||||
subLocation.Append(filename);
|
||||
|
||||
if (fFeed->GetCachePath().IsEmpty())
|
||||
fFeed->SetCachePath(subLocation);
|
||||
|
||||
if (!title.IsEmpty())
|
||||
fFeed->SetTitle(title.String());
|
||||
fFeed->SetXmlUrl(BUrl(urlString));
|
||||
fFeed->Filetize();
|
||||
|
||||
BMessage* firstUpdate = new BMessage(kEnqueueFeed);
|
||||
firstUpdate->AddData("feeds", B_RAW_TYPE, (void*)fFeed, sizeof(Feed));
|
||||
((App*)be_app)->MessageReceived(firstUpdate);
|
||||
Quit();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FeedEditWindow::_DeleteFeed()
|
||||
{
|
||||
fFeed->Unfiletize();
|
||||
Quit();
|
||||
}
|
||||
|
||||
|
|
@ -17,3 +17,15 @@ FeedListItem::FeedListItem(Feed* feed)
|
|||
}
|
||||
|
||||
|
||||
BString
|
||||
FeedListItem::GetFeedPath()
|
||||
{
|
||||
return fFeedPath;
|
||||
}
|
||||
|
||||
|
||||
BUrl
|
||||
FeedListItem::GetFeedUrl()
|
||||
{
|
||||
return fFeedUrl;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ class FeedListItem : public BStringItem
|
|||
public:
|
||||
FeedListItem(Feed* feed);
|
||||
|
||||
BUrl GetFeedUrl();
|
||||
BString GetFeedPath();
|
||||
|
||||
private:
|
||||
BUrl fFeedUrl;
|
||||
BString fFeedPath;
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
|
||||
#include <cstdio>
|
||||
|
||||
#include "App.h"
|
||||
#include "Feed.h"
|
||||
#include "FeedController.h"
|
||||
#include "FeedEditWindow.h"
|
||||
#include "FeedListItem.h"
|
||||
|
||||
|
||||
|
@ -31,6 +34,33 @@ FeedsView::MessageReceived(BMessage* msg)
|
|||
{
|
||||
switch (msg->what)
|
||||
{
|
||||
case kFeedsAddButton:
|
||||
{
|
||||
FeedEditWindow* edit = new FeedEditWindow();
|
||||
edit->Show();
|
||||
edit->Activate();
|
||||
break;
|
||||
}
|
||||
case kFeedsRemoveButton:
|
||||
{
|
||||
_RemoveSelectedFeed();
|
||||
break;
|
||||
}
|
||||
case kFeedsEditButton:
|
||||
{
|
||||
_EditSelectedFeed();
|
||||
break;
|
||||
}
|
||||
case kFeedsSelected:
|
||||
{
|
||||
fEditButton->SetEnabled(true);
|
||||
fRemoveButton->SetEnabled(true);
|
||||
break;
|
||||
}
|
||||
case kFeedsEdited:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// BWindow::MessageReceived(msg);
|
||||
|
@ -47,6 +77,8 @@ FeedsView::_InitInterface()
|
|||
fFeedsListView = new BListView("feedsList");
|
||||
fFeedsScrollView = new BScrollView("feedsScroll", fFeedsListView,
|
||||
B_WILL_DRAW, false, true);
|
||||
fFeedsListView->SetSelectionMessage(new BMessage(kFeedsSelected));
|
||||
fFeedsListView->SetInvocationMessage(new BMessage(kFeedsEditButton));
|
||||
|
||||
BList feeds = FeedController::SubscribedFeeds();
|
||||
for (int i = 0; i < feeds.CountItems(); i++) {
|
||||
|
@ -55,28 +87,32 @@ FeedsView::_InitInterface()
|
|||
}
|
||||
|
||||
// Add, Remove, Edit
|
||||
fAddButton = new BButton("addFeed", "+",
|
||||
new BMessage('fadd'));
|
||||
fRemoveButton = new BButton("removeFeed", "-",
|
||||
new BMessage('frem'));
|
||||
fAddButton = new BButton("addFeed", "+", new BMessage(kFeedsAddButton));
|
||||
fRemoveButton = new BButton("removeFeed", "-", new BMessage(kFeedsRemoveButton));
|
||||
fEditButton = new BButton("editFeed", "Edit…", new BMessage(kFeedsEditButton));
|
||||
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
int16 buttonHeight = int16(fontHeight.ascent + fontHeight.descent + 12);
|
||||
BSize charButtonSize(buttonHeight, buttonHeight);
|
||||
|
||||
fAddButton->SetTarget(this);
|
||||
fAddButton->SetExplicitSize(charButtonSize);
|
||||
fRemoveButton->SetTarget(this);
|
||||
fAddButton->SetEnabled(true);
|
||||
fRemoveButton->SetExplicitSize(charButtonSize);
|
||||
fRemoveButton->SetEnabled(false);
|
||||
fEditButton->SetExplicitSize(
|
||||
BSize(fEditButton->ExplicitPreferredSize().Width(),
|
||||
charButtonSize.Height()));
|
||||
fEditButton->SetEnabled(false);
|
||||
|
||||
|
||||
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
|
||||
.SetInsets(B_USE_DEFAULT_SPACING)
|
||||
.Add(fFeedsScrollView)
|
||||
|
||||
// Add, Remove, and Edit buttons
|
||||
.AddGroup(B_HORIZONTAL, 0, 0.0)
|
||||
|
||||
// Add and Remove buttons
|
||||
.Add(new BSeparatorView(B_VERTICAL))
|
||||
.AddGroup(B_VERTICAL, 0, 0.0)
|
||||
.AddGroup(B_HORIZONTAL, 1, 0.0)
|
||||
|
@ -88,7 +124,41 @@ FeedsView::_InitInterface()
|
|||
.End()
|
||||
.Add(new BSeparatorView(B_VERTICAL))
|
||||
.AddGlue()
|
||||
|
||||
// Edit button
|
||||
.Add(new BSeparatorView(B_VERTICAL))
|
||||
.AddGroup(B_VERTICAL, 0, 0.0)
|
||||
.AddGroup(B_HORIZONTAL, 1, 0.0)
|
||||
.SetInsets(1)
|
||||
.Add(fEditButton)
|
||||
.End()
|
||||
.Add(new BSeparatorView(B_HORIZONTAL))
|
||||
.End()
|
||||
.Add(new BSeparatorView(B_VERTICAL))
|
||||
.End();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FeedsView::_EditSelectedFeed()
|
||||
{
|
||||
int32 selIndex = fFeedsListView->CurrentSelection();
|
||||
FeedListItem* selected = (FeedListItem*)fFeedsListView->ItemAt(selIndex);
|
||||
FeedEditWindow* edit = new FeedEditWindow(selected);
|
||||
|
||||
edit->Show();
|
||||
edit->Activate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FeedsView::_RemoveSelectedFeed()
|
||||
{
|
||||
int32 selIndex = fFeedsListView->CurrentSelection();
|
||||
FeedListItem* selected = (FeedListItem*)fFeedsListView->ItemAt(selIndex);
|
||||
Feed delFeed = Feed(BEntry(selected->GetFeedPath()));
|
||||
|
||||
delFeed.Unfiletize();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,16 @@ class BListView;
|
|||
class BScrollView;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
kFeedsAddButton = 'sadd',
|
||||
kFeedsRemoveButton = 'srem',
|
||||
kFeedsEditButton = 'sedt',
|
||||
kFeedsSelected = 'flsl',
|
||||
kFeedsEdited = 'fedd'
|
||||
};
|
||||
|
||||
|
||||
class FeedsView : public BGroupView {
|
||||
public:
|
||||
FeedsView(const char* name);
|
||||
|
@ -23,8 +33,12 @@ public:
|
|||
private:
|
||||
void _InitInterface();
|
||||
|
||||
void _EditSelectedFeed();
|
||||
void _RemoveSelectedFeed();
|
||||
|
||||
BButton* fAddButton;
|
||||
BButton* fRemoveButton;
|
||||
BButton* fEditButton;
|
||||
BListView* fFeedsListView;
|
||||
BScrollView* fFeedsScrollView;
|
||||
};
|
||||
|
|
|
@ -21,10 +21,7 @@
|
|||
#include "UpdatesView.h"
|
||||
|
||||
|
||||
enum { M_BUTTON_CLICKED = 'btcl' };
|
||||
|
||||
|
||||
MainWindow::MainWindow (void)
|
||||
MainWindow::MainWindow()
|
||||
:
|
||||
BWindow(BRect(BPoint(-1000.0, -1000.0), BSize(520, 380)), "Pogger",
|
||||
B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
|
||||
|
@ -39,6 +36,14 @@ MainWindow::MessageReceived(BMessage *msg)
|
|||
{
|
||||
switch (msg->what)
|
||||
{
|
||||
case kFeedsAddButton:
|
||||
case kFeedsRemoveButton:
|
||||
case kFeedsEditButton:
|
||||
case kFeedsSelected:
|
||||
{
|
||||
fFeedsView->MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
BWindow::MessageReceived(msg);
|
||||
|
|
|
@ -24,7 +24,8 @@ Notifier::MessageReceived(BMessage* msg)
|
|||
if (msg->FindString("feed_name", &feedName) == B_OK
|
||||
&& msg->FindInt32("entry_count", &entryCount) == B_OK)
|
||||
{
|
||||
_NewEntryNotification(feedName, entryCount);
|
||||
if (entryCount > 0)
|
||||
_NewEntryNotification(feedName, entryCount);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ RssFeed::Parse()
|
|||
RootParse(xchan);
|
||||
ParseEntries(xchan);
|
||||
|
||||
_PostParse();
|
||||
Filetize();
|
||||
}
|
||||
|
||||
|
||||
|
|
Ŝarĝante…
Reference in New Issue