diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index d58985d9e1..7c5246df11 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -131,18 +132,17 @@ bool BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const return (*this == other) || (*this > other); } -void BrowsingHistoryItem::increaseInvokationCount() +void BrowsingHistoryItem::invoked() { // Eventually, we may overflow... uint32 count = m_invokationCount + 1; if (count > m_invokationCount) m_invokationCount = count; + m_dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); } // #pragma mark - BrowsingHistory -BrowsingHistory BrowsingHistory::s_defaultInstance; - BrowsingHistory::BrowsingHistory() : BLocker("browsing history") { @@ -150,18 +150,91 @@ BrowsingHistory::BrowsingHistory() if (openSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); - // TODO: ... + + BMessage historyItemArchive; + for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { + addItem(BrowsingHistoryItem(&historyItemArchive)); + historyItemArchive.MakeEmpty(); + } } } BrowsingHistory::~BrowsingHistory() { saveSettings(); + privateClear(); } /*static*/ BrowsingHistory* BrowsingHistory::defaultInstance() { - return &s_defaultInstance; + static BrowsingHistory defaultInstance; + + return &defaultInstance; +} + +bool BrowsingHistory::addItem(const BrowsingHistoryItem& item) +{ + BAutolock _(this); + + int32 count = countItems(); + int32 insertionIndex = count; + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.ItemAtFast(i)); + if (item.url() == existingItem->url()) { + existingItem->invoked(); + return true; + } + if (item < *existingItem) + insertionIndex = i; + } + BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); + if (!newItem || !m_historyItems.AddItem(newItem, insertionIndex)) { + delete newItem; + return false; + } + + newItem->invoked(); + saveSettings(); + + return true; +} + +int32 BrowsingHistory::BrowsingHistory::countItems() const +{ + BAutolock _(const_cast(this)); + + return m_historyItems.CountItems(); +} + +BrowsingHistoryItem BrowsingHistory::historyItemAt(int32 index) const +{ + BAutolock _(const_cast(this)); + + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.ItemAt(index)); + if (!existingItem) + return BrowsingHistoryItem(BString()); + + return BrowsingHistoryItem(*existingItem); +} + +void BrowsingHistory::clear() +{ + BAutolock _(this); + privateClear(); + saveSettings(); +} + +void BrowsingHistory::privateClear() +{ + int32 count = countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* item = reinterpret_cast( + m_historyItems.ItemAtFast(i)); + delete item; + } + m_historyItems.MakeEmpty(); } // #pragma mark - private @@ -171,7 +244,16 @@ void BrowsingHistory::saveSettings() BFile settingsFile; if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; - // TODO: ... + BMessage historyItemArchive; + int32 count = countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem item = historyItemAt(i); + if (item.archive(&historyItemArchive) != B_OK) + break; + if (settingsArchive.AddMessage("history item", &historyItemArchive) != B_OK) + break; + historyItemArchive.MakeEmpty(); + } settingsArchive.Flatten(&settingsFile); } } diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index b660cb30fb..00e4f3a5e7 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -29,6 +29,7 @@ #define BrowsingHistory_h #include "DateTime.h" +#include #include class BFile; @@ -55,7 +56,7 @@ public: const BString& url() const { return m_url; } const BDateTime& dateTime() const { return m_dateTime; } uint32 invokationCount() const { return m_invokationCount; } - void increaseInvokationCount(); + void invoked(); private: BString m_url; @@ -67,15 +68,23 @@ class BrowsingHistory : public BLocker { public: static BrowsingHistory* defaultInstance(); + bool addItem(const BrowsingHistoryItem& item); + + // Should Lock() the object when using these in some loop or so: + int32 countItems() const; + BrowsingHistoryItem historyItemAt(int32 index) const; + void clear(); + private: BrowsingHistory(); virtual ~BrowsingHistory(); + void privateClear(); void saveSettings(); bool openSettingsFile(BFile& file, uint32 mode); private: - static BrowsingHistory s_defaultInstance; + BList m_historyItems; }; #endif // BrowsingHistory_h diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 7fb3a366ea..fb654ef5ac 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -33,9 +33,11 @@ #include "LauncherWindow.h" #include "AuthenticationPanel.h" +#include "BrowsingHistory.h" #include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" +#include #include #include #include @@ -59,6 +61,7 @@ enum { GO_FORWARD = 'gofo', GOTO_URL = 'goul', RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', TEXT_SIZE_INCREASE = 'tsin', TEXT_SIZE_DECREASE = 'tsdc', @@ -111,6 +114,9 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); m_menuBar->AddItem(menu); + m_goMenu = new BMenu("Go"); + m_menuBar->AddItem(m_goMenu); + // Back & Forward m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); m_ForwardButton = new BButton("", "Forward", new BMessage(GO_FORWARD)); @@ -218,10 +224,13 @@ void LauncherWindow::MessageReceived(BMessage* message) case RELOAD: webView()->loadRequest(m_url->Text()); break; - case GOTO_URL: - if (m_loadedURL != m_url->Text()) - webView()->loadRequest(m_url->Text()); + case GOTO_URL: { + BString url = m_url->Text(); + message->FindString("url", &url); + if (m_loadedURL != url) + webView()->loadRequest(url.String()); break; + } case GO_BACK: webView()->goBack(); break; @@ -229,6 +238,17 @@ void LauncherWindow::MessageReceived(BMessage* message) webView()->goForward(); break; + case CLEAR_HISTORY: { + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (history->countItems() == 0) + break; + BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " + "the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->clear(); + break; + } + case B_SIMPLE_DATA: { // User possibly dropped files on this window. // If there is more than one entry_ref, let the app handle it (open one @@ -305,6 +325,35 @@ bool LauncherWindow::QuitRequested() return false; } +void LauncherWindow::MenusBeginning() +{ + BMenuItem* menuItem; + while ((menuItem = m_goMenu->RemoveItem(0L))) + delete menuItem; + + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; + + int32 count = history->countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem historyItem = history->historyItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.url().String()); + // TODO: More sophisticated menu structure... sorted by days/weeks... + menuItem = new BMenuItem(historyItem.url().String(), message); + m_goMenu->AddItem(menuItem); + } + + + if (m_goMenu->CountItems() > 3) { + m_goMenu->AddSeparatorItem(); + m_goMenu->AddItem(new BMenuItem("Clear history", new BMessage(CLEAR_HISTORY))); + } + + history->Unlock(); +} + // #pragma mark - Notification API void LauncherWindow::navigationRequested(const BString& url) @@ -393,6 +442,11 @@ void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, m_ForwardButton->SetEnabled(canGoForward); } +void LauncherWindow::updateGlobalHistory(const BString& url) +{ + BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); +} + void LauncherWindow::authenticationChallenge(BMessage* message) { BString text; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ca4b8391b5..3c814f9893 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -62,6 +62,7 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); + virtual void MenusBeginning(); // WebViewWindow notification API implementations virtual void navigationRequested(const BString& url); @@ -75,10 +76,12 @@ public: virtual void statusChanged(const BString& status); virtual void navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop); + virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); private: BMenuBar* m_menuBar; + BMenu* m_goMenu; BButton* m_BackButton; BButton* m_ForwardButton; BTextControl* m_url;