From 17f2ae356afc3e10762b5693da511136798105e3 Mon Sep 17 00:00:00 2001 From: "bienvenu%netscape.com" Date: Wed, 12 Sep 2001 23:26:33 +0000 Subject: [PATCH] fix problems enabling reply/forward and related commands when offline w/o offline msg bodies (91352) and problem with delete key getting disabled after next unread (84260) r=naving, sr=sspitzer --- mailnews/base/public/nsIMsgDBView.idl | 1 + .../content/mail3PaneWindowCommands.js | 9 ++ mailnews/base/src/nsMsgDBView.cpp | 118 +++++++++++------- mailnews/base/src/nsMsgDBView.h | 2 + 4 files changed, 85 insertions(+), 45 deletions(-) diff --git a/mailnews/base/public/nsIMsgDBView.idl b/mailnews/base/public/nsIMsgDBView.idl index 6c09f76c9a75..fdf79586165d 100644 --- a/mailnews/base/public/nsIMsgDBView.idl +++ b/mailnews/base/public/nsIMsgDBView.idl @@ -168,6 +168,7 @@ interface nsMsgViewCommandType const nsMsgViewCommandTypeValue selectThread = 18; const nsMsgViewCommandTypeValue selectFlagged = 19; + const nsMsgViewCommandTypeValue cmdRequiringMsgBody = 20; }; [scriptable, uuid(65903eb2-1dd2-11b2-ac45-c5b69c1618d7)] diff --git a/mailnews/base/resources/content/mail3PaneWindowCommands.js b/mailnews/base/resources/content/mail3PaneWindowCommands.js index f53af3098524..d9600a293c90 100644 --- a/mailnews/base/resources/content/mail3PaneWindowCommands.js +++ b/mailnews/base/resources/content/mail3PaneWindowCommands.js @@ -336,6 +336,15 @@ var DefaultController = case "cmd_saveAsTemplate": case "cmd_viewPageSource": case "cmd_reload": + if ( GetNumSelectedMessages() > 0) + { + if (gDBView) + { + gDBView.getCommandStatus(nsMsgViewCommandType.cmdRequiringMsgBody, enabled, checkStatus); + return enabled.value; + } + } + return false; case "cmd_markThreadAsRead": case "cmd_markAsFlagged": case "button_file": diff --git a/mailnews/base/src/nsMsgDBView.cpp b/mailnews/base/src/nsMsgDBView.cpp index 0181532b0777..3db8728aaa16 100644 --- a/mailnews/base/src/nsMsgDBView.cpp +++ b/mailnews/base/src/nsMsgDBView.cpp @@ -94,6 +94,7 @@ nsMsgDBView::nsMsgDBView() m_currentlyDisplayedMsgKey = nsMsgKey_None; mNumSelectedRows = 0; mSupressMsgDisplay = PR_FALSE; + mOfflineMsgSelected = PR_FALSE; mIsSpecialFolder = PR_FALSE; mIsNews = PR_FALSE; mDeleteModel = nsMsgImapDeleteModels::MoveToTrash; @@ -586,8 +587,13 @@ NS_IMETHODIMP nsMsgDBView::SelectionChanged() { // if the currentSelection changed then we have a message to display PRUint32 numSelected = 0; - GetNumSelected(&numSelected); + GetNumSelected(&numSelected); + nsUInt32Array selection; + GetSelectedIndices(&selection); + nsMsgViewIndex *indices = selection.GetData(); + + PRBool offlineMsgSelected = (indices) ? OfflineMsgSelected(indices, numSelected) : PR_FALSE; // if only one item is selected then we want to display a message if (numSelected == 1) { @@ -608,6 +614,8 @@ NS_IMETHODIMP nsMsgDBView::SelectionChanged() UpdateDisplayMessage(msgkey); } } + else + numSelected = 0; // selection seems bogus, so set to 0. } // determine if we need to push command update notifications out to the UI or not. @@ -617,9 +625,10 @@ NS_IMETHODIMP nsMsgDBView::SelectionChanged() // (2) it went from 1 to 0 // (3) it went from 1 to many // (4) it went from many to 1 or 0 + // (5) a different msg was selected - perhaps it was offline or not... - if (numSelected == mNumSelectedRows || - (numSelected > 1 && mNumSelectedRows > 1) ) + if ((numSelected == mNumSelectedRows || + (numSelected > 1 && mNumSelectedRows > 1)) && mOfflineMsgSelected == offlineMsgSelected) { } @@ -628,6 +637,7 @@ NS_IMETHODIMP nsMsgDBView::SelectionChanged() mCommandUpdater->UpdateCommandStatus(); } + mOfflineMsgSelected = offlineMsgSelected; mNumSelectedRows = numSelected; return NS_OK; } @@ -1378,6 +1388,12 @@ NS_IMETHODIMP nsMsgDBView::GetCommandStatus(nsMsgViewCommandTypeValue command, P case nsMsgViewCommandType::downloadSelectedForOffline: *selectable_p = (numindices > 0); break; + case nsMsgViewCommandType::cmdRequiringMsgBody: + { + nsMsgViewIndex *indices = selection.GetData(); + *selectable_p = (numindices > 0) && (!WeAreOffline() || OfflineMsgSelected(indices, numindices)); + } + break; case nsMsgViewCommandType::downloadFlaggedForOffline: case nsMsgViewCommandType::markAllRead: *selectable_p = PR_TRUE; @@ -1569,8 +1585,8 @@ nsresult nsMsgDBView::DeleteMessages(nsIMsgWindow *window, nsMsgViewIndex *indic nsresult nsMsgDBView::DownloadForOffline(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices) { nsresult rv = NS_OK; - nsCOMPtr messageArray; - NS_NewISupportsArray(getter_AddRefs(messageArray)); + nsCOMPtr messageArray; + NS_NewISupportsArray(getter_AddRefs(messageArray)); for (nsMsgViewIndex index = 0; index < (nsMsgViewIndex) numIndices; index++) { nsMsgKey key = m_keys.GetAt(indices[index]); @@ -1581,8 +1597,9 @@ nsresult nsMsgDBView::DownloadForOffline(nsIMsgWindow *window, nsMsgViewIndex *i { PRUint32 flags; msgHdr->GetFlags(&flags); - if (! (flags & MSG_FLAG_OFFLINE)) - messageArray->AppendElement(msgHdr); + if ((flags & MSG_FLAG_OFFLINE)) + if (! (flags & MSG_FLAG_OFFLINE)) + messageArray->AppendElement(msgHdr); } } m_folder->DownloadMessagesForOffline(messageArray, window); @@ -1592,16 +1609,16 @@ nsresult nsMsgDBView::DownloadForOffline(nsIMsgWindow *window, nsMsgViewIndex *i nsresult nsMsgDBView::DownloadFlaggedForOffline(nsIMsgWindow *window) { nsresult rv = NS_OK; - nsCOMPtr messageArray; - NS_NewISupportsArray(getter_AddRefs(messageArray)); - nsCOMPtr enumerator; + nsCOMPtr messageArray; + NS_NewISupportsArray(getter_AddRefs(messageArray)); + nsCOMPtr enumerator; rv = m_db->EnumerateMessages(getter_AddRefs(enumerator)); if (NS_SUCCEEDED(rv) && enumerator) { PRBool hasMore; - - while (NS_SUCCEEDED(rv = enumerator->HasMoreElements(&hasMore)) && (hasMore == PR_TRUE)) - { + + while (NS_SUCCEEDED(rv = enumerator->HasMoreElements(&hasMore)) && (hasMore == PR_TRUE)) + { nsCOMPtr pHeader; rv = enumerator->GetNext(getter_AddRefs(pHeader)); NS_ASSERTION(NS_SUCCEEDED(rv), "nsMsgDBEnumerator broken"); @@ -1621,45 +1638,45 @@ nsresult nsMsgDBView::DownloadFlaggedForOffline(nsIMsgWindow *window) // read/unread handling. nsresult nsMsgDBView::ToggleReadByIndex(nsMsgViewIndex index) { - if (!IsValidIndex(index)) - return NS_MSG_INVALID_DBVIEW_INDEX; - return SetReadByIndex(index, !(m_flags[index] & MSG_FLAG_READ)); + if (!IsValidIndex(index)) + return NS_MSG_INVALID_DBVIEW_INDEX; + return SetReadByIndex(index, !(m_flags[index] & MSG_FLAG_READ)); } nsresult nsMsgDBView::SetReadByIndex(nsMsgViewIndex index, PRBool read) { - nsresult rv; - - if (!IsValidIndex(index)) - return NS_MSG_INVALID_DBVIEW_INDEX; - if (read) { - OrExtraFlag(index, MSG_FLAG_READ); - // MarkRead() will clear this flag in the db - // and then call OnKeyChange(), but - // because we are the instigator of the change - // we'll ignore the change. - // - // so we need to clear it in m_flags - // to keep the db and m_flags in sync - AndExtraFlag(index, ~MSG_FLAG_NEW); - } - else { - AndExtraFlag(index, ~MSG_FLAG_READ); - } - + nsresult rv; + + if (!IsValidIndex(index)) + return NS_MSG_INVALID_DBVIEW_INDEX; + if (read) { + OrExtraFlag(index, MSG_FLAG_READ); + // MarkRead() will clear this flag in the db + // and then call OnKeyChange(), but + // because we are the instigator of the change + // we'll ignore the change. + // + // so we need to clear it in m_flags + // to keep the db and m_flags in sync + AndExtraFlag(index, ~MSG_FLAG_NEW); + } + else { + AndExtraFlag(index, ~MSG_FLAG_READ); + } + nsCOMPtr dbToUse; rv = GetDBForViewIndex(index, getter_AddRefs(dbToUse)); NS_ENSURE_SUCCESS(rv, rv); - - rv = dbToUse->MarkRead(m_keys[index], read, this); - NoteChange(index, 1, nsMsgViewNotificationCode::changed); - if (m_sortType == nsMsgViewSortType::byThread) - { - nsMsgViewIndex threadIndex = ThreadIndexOfMsg(m_keys[index], index, nsnull, nsnull); - if (threadIndex != index) - NoteChange(threadIndex, 1, nsMsgViewNotificationCode::changed); - } - return rv; + + rv = dbToUse->MarkRead(m_keys[index], read, this); + NoteChange(index, 1, nsMsgViewNotificationCode::changed); + if (m_sortType == nsMsgViewSortType::byThread) + { + nsMsgViewIndex threadIndex = ThreadIndexOfMsg(m_keys[index], index, nsnull, nsnull); + if (threadIndex != index) + NoteChange(threadIndex, 1, nsMsgViewNotificationCode::changed); + } + return rv; } nsresult nsMsgDBView::SetThreadOfMsgReadByIndex(nsMsgViewIndex index, nsMsgKeyArray &keysMarkedRead, PRBool /*read*/) @@ -4356,6 +4373,17 @@ nsMsgDBView::OnStopCopy(nsresult aStatus) } // end nsIMsgCopyServiceListener methods +PRBool nsMsgDBView::OfflineMsgSelected(nsMsgViewIndex * indices, PRInt32 numIndices) +{ + nsresult rv = NS_OK; + for (nsMsgViewIndex index = 0; index < (nsMsgViewIndex) numIndices; index++) + { + PRUint32 flags = m_flags.GetAt(indices[index]); + if ((flags & MSG_FLAG_OFFLINE)) + return PR_TRUE; + } + return PR_FALSE; +} nsresult nsMsgDBView::GetKeyForFirstSelectedMessage(nsMsgKey *key) diff --git a/mailnews/base/src/nsMsgDBView.h b/mailnews/base/src/nsMsgDBView.h index 2c8e3d1f2231..b1b23adfb949 100644 --- a/mailnews/base/src/nsMsgDBView.h +++ b/mailnews/base/src/nsMsgDBView.h @@ -109,6 +109,7 @@ protected: PRBool mSupressMsgDisplay; // set when the message pane is collapsed PRBool mRemovingRow; // set when we're telling the outline a row is being removed. used to supress msg loading. // during delete/move operations. + PRBool mOfflineMsgSelected; virtual const char * GetViewName(void) {return "MsgDBView"; } nsresult FetchAuthor(nsIMsgHdr * aHdr, PRUnichar ** aAuthorString); nsresult FetchSubject(nsIMsgHdr * aMsgHdr, PRUint32 aFlags, PRUnichar ** aValue); @@ -244,6 +245,7 @@ protected: PRBool IsValidIndex(nsMsgViewIndex index); nsresult ToggleIgnored(nsMsgViewIndex * indices, PRInt32 numIndices, PRBool *resultToggleState); nsresult GetKeyForFirstSelectedMessage(nsMsgKey *key); + PRBool OfflineMsgSelected(nsMsgViewIndex * indices, PRInt32 numIndices); PRUnichar * GetString(const PRUnichar *aStringName); void InitializeAtomsAndLiterals(); PRInt32 GetLevelInUnreadView(nsIMsgDBHdr *msgHdr, nsMsgViewIndex startOfThread, nsMsgViewIndex viewIndex);