diff --git a/browser/components/places/skin-win/places.css b/browser/components/places/skin-win/places.css index ca5355508f9..afa6b84e0a2 100755 --- a/browser/components/places/skin-win/places.css +++ b/browser/components/places/skin-win/places.css @@ -58,6 +58,16 @@ treechildren::-moz-tree-image(title, container, open, toolbar-root) { -moz-image-region: rect(17px, 16px, 32px, 0px); } +treechildren::-moz-tree-row(session-start) { + border-top:1px dotted ThreeDShadow; +} + +/* FIXME this should make the date field invisible, but only does it for + unselected items and maybe won't work for different color schemes. */ +treechildren::-moz-tree-cell-text(date, session-continue) { + color:white; +} + treechildren::-moz-tree-image(title, separator) { list-style-image: none; width: 0px !important; diff --git a/browser/components/places/src/nsNavBookmarks.cpp b/browser/components/places/src/nsNavBookmarks.cpp index 033db54038d..9f732622e71 100644 --- a/browser/components/places/src/nsNavBookmarks.cpp +++ b/browser/components/places/src/nsNavBookmarks.cpp @@ -55,10 +55,10 @@ const PRInt32 nsNavBookmarks::kGetFolderInfoIndex_Title = 1; const PRInt32 nsNavBookmarks::kGetFolderInfoIndex_Type = 2; // These columns sit to the right of the kGetInfoIndex_* columns. -const PRInt32 nsNavBookmarks::kGetChildrenIndex_Position = 8; -const PRInt32 nsNavBookmarks::kGetChildrenIndex_ItemChild = 9; -const PRInt32 nsNavBookmarks::kGetChildrenIndex_FolderChild = 10; -const PRInt32 nsNavBookmarks::kGetChildrenIndex_FolderTitle = 11; +const PRInt32 nsNavBookmarks::kGetChildrenIndex_Position = 9; +const PRInt32 nsNavBookmarks::kGetChildrenIndex_ItemChild = 10; +const PRInt32 nsNavBookmarks::kGetChildrenIndex_FolderChild = 11; +const PRInt32 nsNavBookmarks::kGetChildrenIndex_FolderTitle = 12; nsNavBookmarks* nsNavBookmarks::sInstance = nsnull; @@ -168,10 +168,11 @@ nsNavBookmarks::Init() // mDBGetURLPageInfo, and additionally contains columns for position, // item_child, and folder_child from moz_bookmarks. This selects only // _item_ children which are in moz_history. + // Results are kGetInfoIndex_* NS_NAMED_LITERAL_CSTRING(selectItemChildren, "SELECT h.id, h.url, h.title, h.user_title, h.rev_host, h.visit_count, " "(SELECT MAX(visit_date) FROM moz_historyvisit WHERE page_id = h.id), " - "f.url, a.position, a.item_child, a.folder_child, null " + "f.url, null, a.position, a.item_child, a.folder_child, null " "FROM moz_bookmarks a " "JOIN moz_history h ON a.item_child = h.id " "LEFT OUTER JOIN moz_favicon f ON h.favicon = f.id " @@ -181,9 +182,9 @@ nsNavBookmarks::Init() // of mDBGetVisitPageInfo, containing additional columns for position, // item_child, and folder_child from moz_bookmarks, and name from // moz_bookmarks_folders. This selects only _folder_ children which are - // in moz_bookmarks_folders. + // in moz_bookmarks_folders. Results are kGetInfoIndex_* kGetChildrenIndex_* NS_NAMED_LITERAL_CSTRING(selectFolderChildren, - "SELECT null, null, null, null, null, null, null, null, a.position, a.item_child, a.folder_child, c.name " + "SELECT null, null, null, null, null, null, null, null, null, a.position, a.item_child, a.folder_child, c.name " "FROM moz_bookmarks a " "JOIN moz_bookmarks_folders c ON c.id = a.folder_child " "WHERE a.parent = ?1 AND a.position >= ?2 AND a.position <= ?3"); diff --git a/browser/components/places/src/nsNavHistory.cpp b/browser/components/places/src/nsNavHistory.cpp index 8e742740c54..7e6f9ae6639 100644 --- a/browser/components/places/src/nsNavHistory.cpp +++ b/browser/components/places/src/nsNavHistory.cpp @@ -167,6 +167,7 @@ const PRInt32 nsNavHistory::kGetInfoIndex_RevHost = 4; const PRInt32 nsNavHistory::kGetInfoIndex_VisitCount = 5; const PRInt32 nsNavHistory::kGetInfoIndex_VisitDate = 6; const PRInt32 nsNavHistory::kGetInfoIndex_FaviconURL = 7; +const PRInt32 nsNavHistory::kGetInfoIndex_SessionId = 8; const PRInt32 nsNavHistory::kAutoCompleteIndex_URL = 0; const PRInt32 nsNavHistory::kAutoCompleteIndex_Title = 1; @@ -181,6 +182,8 @@ const char nsNavHistory::kAnnotationPreviousEncoding[] = "history/encoding"; nsIAtom* nsNavHistory::sMenuRootAtom = nsnull; nsIAtom* nsNavHistory::sToolbarRootAtom = nsnull; +nsIAtom* nsNavHistory::sSessionStartAtom = nsnull; +nsIAtom* nsNavHistory::sSessionContinueAtom = nsnull; nsNavHistory* nsNavHistory::gHistoryService; @@ -195,6 +198,8 @@ nsNavHistory::nsNavHistory() : mNowValid(PR_FALSE), sMenuRootAtom = NS_NewAtom("menu-root"); sToolbarRootAtom = NS_NewAtom("toolbar-root"); + sSessionStartAtom = NS_NewAtom("session-start"); + sSessionContinueAtom = NS_NewAtom("session-continue"); } @@ -1329,7 +1334,8 @@ nsNavHistory::ExecuteQueries(nsINavHistoryQuery** aQueries, PRUint32 aQueryCount // if we want visits, this is easy, just combine all possible matches // between the history and visits table and do our query. queryString = NS_LITERAL_CSTRING( - "SELECT h.id, h.url, h.title, h.user_title, h.rev_host, h.visit_count, v.visit_date, f.url " + "SELECT h.id, h.url, h.title, h.user_title, h.rev_host, h.visit_count, " + "v.visit_date, f.url, v.session " "FROM moz_history h " "JOIN moz_historyvisit v ON h.id = v.page_id " "LEFT OUTER JOIN moz_favicon f ON h.favicon = f.id " @@ -1337,11 +1343,12 @@ nsNavHistory::ExecuteQueries(nsINavHistoryQuery** aQueries, PRUint32 aQueryCount } else { // For URLs, it is more complicated, because we want each URL once. The // GROUP BY clause gives us this. To get the max visit time, we populate - // one column by using a nested SELECT on the visit table. + // one column by using a nested SELECT on the visit table. Also, ignore + // session information. queryString = NS_LITERAL_CSTRING( "SELECT h.id, h.url, h.title, h.user_title, h.rev_host, h.visit_count, " "(SELECT MAX(visit_date) FROM moz_historyvisit WHERE page_id = h.id), " - "f.url " + "f.url, null " "FROM moz_history h " "JOIN moz_historyvisit v ON h.id = v.page_id " "LEFT OUTER JOIN moz_favicon f ON h.favicon = f.id " @@ -2727,7 +2734,11 @@ nsNavHistory::FillURLResult(mozIStorageValueArray *aRow, NS_ENSURE_SUCCESS(rv, rv); // favicon - aRow->GetUTF8String(kGetInfoIndex_FaviconURL, aNode->mFaviconURL); + rv = aRow->GetUTF8String(kGetInfoIndex_FaviconURL, aNode->mFaviconURL); + NS_ENSURE_SUCCESS(rv, rv); + + // session + rv = aRow->GetInt64(kGetInfoIndex_SessionId, &aNode->mSessionID); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; diff --git a/browser/components/places/src/nsNavHistory.h b/browser/components/places/src/nsNavHistory.h index 9162ba4e917..2815cf21651 100644 --- a/browser/components/places/src/nsNavHistory.h +++ b/browser/components/places/src/nsNavHistory.h @@ -174,8 +174,13 @@ public: static const PRInt32 kGetInfoIndex_VisitDate; static const PRInt32 kGetInfoIndex_FaviconURL; + // used in execute queries to get session ID info (only for visits) + static const PRInt32 kGetInfoIndex_SessionId; + static nsIAtom* sMenuRootAtom; static nsIAtom* sToolbarRootAtom; + static nsIAtom* sSessionStartAtom; + static nsIAtom* sSessionContinueAtom; // Take a row of kGetInfoIndex_* columns and construct a ResultNode. // The row must contain the full set of columns. diff --git a/browser/components/places/src/nsNavHistoryResult.cpp b/browser/components/places/src/nsNavHistoryResult.cpp index b819c022f17..2c1c0e3cddf 100755 --- a/browser/components/places/src/nsNavHistoryResult.cpp +++ b/browser/components/places/src/nsNavHistoryResult.cpp @@ -92,6 +92,7 @@ nsNavHistoryResultNode::nsNavHistoryResultNode() : mID(0), mAccessCount(0), mTime(0), + mSessionID(0), mExpanded(PR_FALSE) { } @@ -1070,7 +1071,8 @@ nsNavHistoryResult::nsNavHistoryResult(nsNavHistory* aHistoryService, PRUint32 aQueryCount, nsNavHistoryQueryOptions* aOptions) : mBundle(aHistoryBundle), mHistoryService(aHistoryService), - mCollapseDuplicates(PR_TRUE) + mCollapseDuplicates(PR_TRUE), + mShowSessions(PR_FALSE) { NS_ASSERTION(aOptions, "must have options!"); // Fill saved source queries with copies of the original (the caller might @@ -1156,6 +1158,7 @@ nsNavHistoryResult::FilledAllResults() FillTreeStats(this, -1), RebuildAllListRecurse(mChildren); InitializeVisibleList(); + ComputeShowSessions(); } // nsNavHistoryResult::BuildChildrenFor @@ -1663,6 +1666,35 @@ nsNavHistoryResult::FormatFriendlyTime(PRTime aTime, nsAString& aResult) } +// nsNavHistoryResult::ComputeShowSessions +// +// Computes the value of mShowSessions, which is used to see if we should +// try to set styles for session groupings. We only want to do session +// grouping if we're in an appropriate view, which is view by visit and +// sorted by date. + +void +nsNavHistoryResult::ComputeShowSessions() +{ + mShowSessions = PR_FALSE; + NS_ASSERTION(mOptions, "navHistoryResults must have valid options"); + if (mOptions->ResultType() != nsINavHistoryQueryOptions::RESULT_TYPE_VISIT) + return; // not visits + if (mOptions->SortingMode() != nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING && + mOptions->SortingMode() != nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING) + return; // not date sorting + + PRUint32 groupCount; + const PRInt32* groups = mOptions->GroupingMode(&groupCount); + for (PRUint32 i = 0; i < groupCount; i ++) { + if (groups[i] != nsINavHistoryQueryOptions::GROUP_BY_DAY) + return; // non-time-based grouping + } + + mShowSessions = PR_TRUE; +} + + // nsNavHistoryResult::FillTreeStats // // This basically does a recursive depth-first traversal of the tree to fill @@ -1723,6 +1755,9 @@ nsNavHistoryResult::RebuildList() { PRInt32 oldVisibleCount = mVisibleElements.Count(); + // something changed, so we better update the show sessions value + ComputeShowSessions(); + mAllElements.Clear(); mVisibleElements.Clear(); RebuildAllListRecurse(mChildren); @@ -1885,7 +1920,22 @@ NS_IMETHODIMP nsNavHistoryResult::SetSelection(nsITreeSelection* aSelection) /* void getRowProperties (in long index, in nsISupportsArray properties); */ NS_IMETHODIMP nsNavHistoryResult::GetRowProperties(PRInt32 index, nsISupportsArray *properties) { - return NS_ERROR_NOT_IMPLEMENTED; + if (! mShowSessions) + return NS_OK; // don't need to bother to compute session boundaries + + if (index < 0 || index >= mVisibleElements.Count()) + return NS_ERROR_INVALID_ARG; + nsNavHistoryResultNode *node = VisibleElementAt(index); + + if (node->mSessionID != 0) { + if (index == 0 || + node->mSessionID != VisibleElementAt(index - 1)->mSessionID) { + properties->AppendElement(nsNavHistory::sSessionStartAtom); + } else { + properties->AppendElement(nsNavHistory::sSessionContinueAtom); + } + } + return NS_OK; } /* void getCellProperties (in long row, in nsITreeColumn col, in nsISupportsArray properties); */ @@ -1906,6 +1956,14 @@ NS_IMETHODIMP nsNavHistoryResult::GetCellProperties(PRInt32 row, nsITreeColumn * else if (toolbarRootId == folderId) properties->AppendElement(nsNavHistory::sToolbarRootAtom); + if (mShowSessions && node->mSessionID != 0) { + if (row == 0 || + node->mSessionID != VisibleElementAt(row - 1)->mSessionID) { + properties->AppendElement(nsNavHistory::sSessionStartAtom); + } else { + properties->AppendElement(nsNavHistory::sSessionContinueAtom); + } + } return NS_OK; } diff --git a/browser/components/places/src/nsNavHistoryResult.h b/browser/components/places/src/nsNavHistoryResult.h index 3bab4ce54a6..6989d65af11 100644 --- a/browser/components/places/src/nsNavHistoryResult.h +++ b/browser/components/places/src/nsNavHistoryResult.h @@ -131,6 +131,7 @@ protected: PRTime mTime; nsString mHost; nsCString mFaviconURL; + PRInt64 mSessionID; // Filled in by the result type generator in nsNavHistory nsCOMArray mChildren; @@ -300,6 +301,12 @@ private: return (nsNavHistoryResultNode*)mVisibleElements[index]; } + // This value indicates whether we should try to compute session boundaries. + // It is cached so we don't have to compute it every time we want to get a + // row style. + PRBool mShowSessions; + void ComputeShowSessions(); + void FillTreeStats(nsNavHistoryResultNode* aResult, PRInt32 aLevel); void InitializeVisibleList(); void RebuildList();