diff --git a/Makefile b/Makefile index aecf982..84af1a5 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ APP_MIME_SIG = application/x-vnd.Pogger SRCS = \ src/App.cpp \ src/AtomFeed.cpp \ + src/DeskbarView.cpp \ src/Entry.cpp \ src/EntriesView.cpp \ src/Feed.cpp \ diff --git a/src/App.cpp b/src/App.cpp index 4805a1b..32b8e3b 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -11,6 +11,7 @@ #include #include "AtomFeed.h" +#include "DeskbarView.h" #include "Entry.h" #include "Feed.h" #include "FeedController.h" @@ -45,6 +46,7 @@ App::App() : BApplication("application/x-vnd.Pogger") MessageReceived(&updateMessage); fUpdateRunner = new BMessageRunner(this, updateMessage, interval, count); + installDeskbar(); } @@ -106,6 +108,7 @@ App::QuitRequested() fPreferences->Save(); delete fPreferences; + removeDeskbar(); return true; } diff --git a/src/DeskbarView.cpp b/src/DeskbarView.cpp new file mode 100644 index 0000000..18ab909 --- /dev/null +++ b/src/DeskbarView.cpp @@ -0,0 +1,288 @@ +/* + * Copyright 2021, Jaidyn Levesque + * Copyright 2004-2018, Haiku, Inc. All Rights Reserved. + * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. + * All rights reserved. Distributed under the terms of the MIT license. + * + * Authors: + * Michael Weirauch, dev@m-phasis.de + */ + +#include "DeskbarView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FeedController.h" +#include "Preferences.h" +#include "Util.h" + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "DeskbarView" + + +DeskbarView::DeskbarView(BRect rect) + : BView(rect, "Pogger", B_FOLLOW_NONE, B_WILL_DRAW) +{ + _InitIcon(); +} + + +DeskbarView::DeskbarView(BMessage* message) + : BView(message) +{ + _InitIcon(); + _GetEntryDir(); +} + + +status_t +DeskbarView::Archive(BMessage* data, bool deep) const { + BView::Archive(data, deep); + + data->AddString("add_on", "application/x-vnd.Pogger"); + data->AddString("class", "Pogger"); + + return B_OK; +} + + +DeskbarView* +DeskbarView::Instantiate(BMessage* data) { + if (!validate_instantiation(data, "Pogger")) + return NULL; + return new DeskbarView(data); +} + + +void +DeskbarView::AttachedToWindow() +{ + BView::AttachedToWindow(); + AdoptParentColors(); + + SetLowColor(ViewColor()); +} + + +void +DeskbarView::MessageReceived(BMessage* msg) +{ + switch (msg->what) + { + case kEntryFolder: + { + entry_ref ref; + BEntry entry(fEntryDir); + entry.GetRef(&ref); + be_roster->Launch(&ref); + break; + } + case kQueryNew: + { + entry_ref query; + _GetNewEntryQuery(&query); + be_roster->Launch(&query); + break; + } + case kUpdateNow: + { + BMessenger messenger("application/x-vnd.Pogger"); + messenger.SendMessage(kUpdateSubscribed); + break; + } + case kOpenSettings: + { + be_roster->Launch("application/x-vnd.Pogger"); + break; + } + case kQuitPogger: + { + BMessenger messenger("application/x-vnd.Pogger"); + messenger.SendMessage(B_QUIT_REQUESTED); + break; + } + default: + BView::MessageReceived(msg); + } +} + + +void +DeskbarView::Draw(BRect rect) +{ + SetDrawingMode(B_OP_ALPHA); + DrawBitmap(fIcon); + SetDrawingMode(B_OP_COPY); +} + + +void +DeskbarView::MouseUp(BPoint point) +{ + BMessage open(kQueryNew); + MessageReceived(&open); +} + + +void +DeskbarView::MouseDown(BPoint point) +{ + uint32 buttons; + GetMouse(&point, &buttons); + if (!(buttons & B_SECONDARY_MOUSE_BUTTON)) + return; + + ConvertToScreen(&point); + + BPopUpMenu* menu = _BuildMenu(); + menu->SetTargetForItems(this); + menu->Go(point, true, false, true, true); +} + + +BPopUpMenu* +DeskbarView::_BuildMenu() +{ + BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false); + + menu->AddItem(new BMenuItem(B_TRANSLATE("Open entry folder" B_UTF8_ELLIPSIS), + new BMessage(kEntryFolder))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Query new entries" B_UTF8_ELLIPSIS), + new BMessage(kQueryNew))); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem(B_TRANSLATE("Update now"), + new BMessage(kUpdateNow))); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), + new BMessage(kOpenSettings))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Quit Pogger"), + new BMessage(kQuitPogger))); + + return menu; +} + + +void +DeskbarView::_GetEntryDir() +{ + Preferences pref = Preferences(); + pref.Load(); + fEntryDir = pref.EntryDir(); +} + + +status_t +DeskbarView::_GetNewEntryQuery(entry_ref* ref) +{ + BPath path; + find_directory(B_USER_SETTINGS_DIRECTORY, &path); + path.Append("Pogger/New Entries"); + BEntry query(path.Path()); + if (query.Exists()) + return query.GetRef(ref); + else + return _CreateNewEntryQuery(query); +} + + +status_t +DeskbarView::_CreateNewEntryQuery(BEntry query) +{ + BFile file(&query, B_READ_WRITE | B_CREATE_FILE); + if (file.InitCheck() != B_OK) + return file.InitCheck(); + + BString string("\"Feed:status\" ==\"New\""); + file.WriteAttrString("_trk/qrystr", &string); + file.WriteAttrString("_trk/qryinitstr", &string); + int32 mode = 'Fbyq'; + file.WriteAttr("_trk/qryinitmode", B_INT32_TYPE, 0, &mode, sizeof(int32)); + string = "Feed entry"; + file.WriteAttrString("_trk/qryinitmime", &string); + BNodeInfo(&file).SetType("application/x-vnd.Be-query"); + + return B_OK; +} + + +void +DeskbarView::_InitIcon() +{ + image_info info; + if (our_image(info) != B_OK) + return; + + BFile file(info.name, B_READ_ONLY); + if (file.InitCheck() < B_OK) + return; + + BResources resources(&file); + if (resources.InitCheck() < B_OK) + return; + + size_t size; + const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, "feed-type", &size); + + if (data != NULL) { + BBitmap* icon = new BBitmap(Bounds(), B_RGBA32); + if (icon->InitCheck() == B_OK + && BIconUtils::GetVectorIcon((const uint8 *)data, size, icon) + == B_OK) { + fIcon = icon; + } + else + delete icon; + } +} + + +status_t +our_image(image_info& image) +{ + int32 cookie = 0; + while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) { + if ((char *)our_image >= (char *)image.text + && (char *)our_image <= (char *)image.text + image.text_size) + return B_OK; + } + + return B_ERROR; +} + + +int32 +installDeskbar() +{ + int32 deskbarId = -1; + + removeDeskbar(); + BDeskbar deskbar; + + deskbar.AddItem( + new DeskbarView(BRect(0,0, deskbar.MaxItemHeight() - 1, + deskbar.MaxItemHeight() - 1)), + &deskbarId); + + return deskbarId; +} + + +void +removeDeskbar() +{ + BDeskbar deskbar; + deskbar.RemoveItem("Pogger"); +} + + diff --git a/src/DeskbarView.h b/src/DeskbarView.h new file mode 100644 index 0000000..2f29121 --- /dev/null +++ b/src/DeskbarView.h @@ -0,0 +1,68 @@ +/* + * Copyright 2021, Jaidyn Levesque + * Copyright 2004-2018, Haiku, Inc. All Rights Reserved. + * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. + * All rights reserved. Distributed under the terms of the MIT license. + * + * Authors: + * Michael Weirauch, dev@m-phasis.de + */ + +#ifndef DBVIEW_H +#define DBVIEW_H + +#include + +class BPopUpMenu; + + +enum +{ + kOpenSettings = 'dbos', + kQuitPogger = 'dbkp', + kUpdateNow = 'dbup', + kEntryFolder = 'dbef', + kQueryNew = 'dbqn' +}; + + +// This view has a large amount of code from the mail and bluetooth servers +// (src/servers/mail/DeskbarView.cpp src/servers/bluetooth/DeskbarReplicant.cpp) + +class DeskbarView : public BView { +public: + DeskbarView(BRect rect); + DeskbarView(BMessage* msg); + + status_t Archive(BMessage *data, bool deep = true) const; + static DeskbarView* Instantiate(BMessage *data); + void AttachedToWindow(); + + void MessageReceived(BMessage* msg); + + void Draw(BRect rect); + + void MouseUp(BPoint point); + void MouseDown(BPoint point); + + BPopUpMenu* _BuildMenu(); + void _GetEntryDir(); + status_t _GetNewEntryQuery(entry_ref* ref); + status_t _CreateNewEntryQuery(BEntry query); + void _InitIcon(); + + +private: + BBitmap* fIcon; + BString fEntryDir; +}; + + +int32 installDeskbar(); +void removeDeskbar(); + +status_t our_image(image_info& image); + + +#endif // DBVIEW_H + diff --git a/src/Entry.cpp b/src/Entry.cpp index 890dc97..826d379 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -42,11 +42,11 @@ Entry::Filetize() } outDir.CreateFile(fTitle.String(), &file); - BString betype = BString("text/x-feed-entry"); + BString betype = BString("application/x-feed-entry"); file.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, betype.String(), betype.CountChars() + 1); - BString readStatus("Unread"); + BString readStatus("New"); file.WriteAttrString("Feed:name", &fTitle); file.WriteAttrString("Feed:description", &fDescription); file.WriteAttrString("Feed:source", &fFeedTitle); diff --git a/src/Mimetypes.cpp b/src/Mimetypes.cpp index 49d9644..ba17dab 100644 --- a/src/Mimetypes.cpp +++ b/src/Mimetypes.cpp @@ -13,10 +13,15 @@ #include #include #include +#include +#include +#include + bool installMimeTypes() { + addIndices(); return (feedMimeType() && feedEntryMimeType()); } @@ -82,6 +87,26 @@ feedEntryMimeType() } +void +addIndices() +{ + int32 cookie = 0; + dev_t device; + + while ((device = next_dev(&cookie)) >= B_OK) { + fs_info info; + if (fs_stat_dev(device, &info) < 0 + || (info.flags & B_FS_HAS_QUERY) == 0) + continue; + + fs_create_index(device, "Feed:name", B_STRING_TYPE, 0); + fs_create_index(device, "Feed:source", B_STRING_TYPE, 0); + fs_create_index(device, "Feed:status", B_STRING_TYPE, 0); + fs_create_index(device, "Feed:when", B_TIME_TYPE, 0); + } +} + + // add the given attribute to a BMessage for use as attr info // borrowed from mailserver (thanks!) static void diff --git a/src/Mimetypes.h b/src/Mimetypes.h index 7620e7c..c621a74 100644 --- a/src/Mimetypes.h +++ b/src/Mimetypes.h @@ -15,6 +15,7 @@ class BMessage; bool installMimeTypes(); bool feedMimeType(); bool feedEntryMimeType(); +void addIndices(); static void addAttribute(BMessage&, const char*, const char*, int32 type = B_STRING_TYPE, int32 width = 200); diff --git a/src/Pogger.rdef b/src/Pogger.rdef index 198b0bb..bd6a413 100644 --- a/src/Pogger.rdef +++ b/src/Pogger.rdef @@ -17,6 +17,6 @@ resource app_version { }; resource file_types message { - "types" = "text/x-feed-entry", + "types" = "application/x-feed-entry", "types" = "application/x-feed-source" };