NOT PART OF THE BUILD

Pre-landing work for the mailnews performance branch. Add news files on the branch to the tip.
This commit is contained in:
mscott%netscape.com 2001-03-15 22:35:34 +00:00
parent 1eeba25c9e
commit 2fb926cb69
7 changed files with 1120 additions and 0 deletions

View File

@ -0,0 +1,40 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
// this is a service -there's only one Offline Manager, because you can only do one operation at a time
// (go online or offline).
interface nsIMsgWindow;
[scriptable, uuid(5e885fec-09b0-11d5-a5bf-0060b0fc04b7)]
interface nsIMsgOfflineManager : nsISupports
{
attribute nsIMsgWindow window; // should be a progress window.
attribute boolean inProgress; // an online->offine or online->offline operation in progress.
// the offline menu should be disabled.
void goOnline(in boolean sendUnsentMessages, in boolean playbackOfflineImapOperations, in nsIMsgWindow aMsgWindow);
void synchronizeForOffline(in boolean downloadNews, in boolean downloadMail, in boolean sendUnsentMessages,
in boolean goOfflineWhenDone, in nsIMsgWindow aMsgWindow);
};

View File

@ -0,0 +1,371 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* The offline manager service - manages going online and offline, and synchronization
*/
#include "msgCore.h"
#include "nsMsgOfflineManager.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsMsgBaseCID.h"
#include "nsIImapService.h"
#include "nsMsgImapCID.h"
#include "nsIMsgSendLater.h"
#include "nsIMsgAccountManager.h"
#include "nsMsgCompCID.h"
#include "nsIIOService.h"
#include "nsMsgNewsCID.h"
#include "nsINntpService.h"
static NS_DEFINE_CID(kCImapService, NS_IMAPSERVICE_CID);
static NS_DEFINE_CID(kCMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
static NS_DEFINE_CID(kMsgSendLaterCID, NS_MSGSENDLATER_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kNntpServiceCID, NS_NNTPSERVICE_CID);
NS_IMPL_THREADSAFE_ISUPPORTS5(nsMsgOfflineManager,
nsIMsgOfflineManager,
nsIMsgSendLaterListener,
nsIObserver,
nsISupportsWeakReference,
nsIUrlListener)
nsMsgOfflineManager::nsMsgOfflineManager() :
m_inProgress (PR_FALSE),
m_sendUnsentMessages(PR_FALSE),
m_downloadNews(PR_FALSE),
m_downloadMail(PR_FALSE),
m_playbackOfflineImapOps(PR_FALSE),
m_goOfflineWhenDone(PR_FALSE),
m_curState(eNoState),
m_curOperation(eNoOp)
{
NS_INIT_REFCNT();
}
nsMsgOfflineManager::~nsMsgOfflineManager()
{
}
/* attribute nsIMsgWindow window; */
NS_IMETHODIMP nsMsgOfflineManager::GetWindow(nsIMsgWindow * *aWindow)
{
NS_ENSURE_ARG(aWindow);
*aWindow = m_window;
NS_IF_ADDREF(*aWindow);
return NS_OK;
}
NS_IMETHODIMP nsMsgOfflineManager::SetWindow(nsIMsgWindow * aWindow)
{
m_window = aWindow;
if (m_window)
m_window->GetStatusFeedback(getter_AddRefs(m_statusFeedback));
else
m_statusFeedback = nsnull;
return NS_OK;
}
/* attribute boolean inProgress; */
NS_IMETHODIMP nsMsgOfflineManager::GetInProgress(PRBool *aInProgress)
{
NS_ENSURE_ARG(aInProgress);
*aInProgress = m_inProgress;
return NS_OK;
}
NS_IMETHODIMP nsMsgOfflineManager::SetInProgress(PRBool aInProgress)
{
m_inProgress = aInProgress;
return NS_OK;
}
nsresult nsMsgOfflineManager::StopRunning(nsresult exitStatus)
{
m_inProgress = PR_FALSE;
return exitStatus;
}
nsresult nsMsgOfflineManager::AdvanceToNextState(nsresult exitStatus)
{
if (!NS_SUCCEEDED(exitStatus))
{
return StopRunning(exitStatus);
}
if (m_curOperation == eGoingOnline)
{
switch (m_curState)
{
case eNoState:
if (m_sendUnsentMessages)
{
m_curState = eSendingUnsent;
SendUnsentMessages();
}
else
AdvanceToNextState(NS_OK);
break;
case eSendingUnsent:
m_curState = eSynchronizingOfflineImapChanges;
if (m_playbackOfflineImapOps)
return SynchronizeOfflineImapChanges();
else
AdvanceToNextState(NS_OK); // recurse to next state.
break;
case eSynchronizingOfflineImapChanges:
m_curState = eDone;
return StopRunning(exitStatus);
default:
NS_ASSERTION(PR_FALSE, "unhandled current state when going online");
}
}
else if (m_curOperation == eDownloadingForOffline)
{
switch (m_curState)
{
case eNoState:
m_curState = eDownloadingNews;
if (m_downloadNews)
DownloadOfflineNewsgroups();
else
AdvanceToNextState(NS_OK);
break;
case eSendingUnsent:
if (m_goOfflineWhenDone)
{
SetOnlineState(PR_FALSE);
}
break;
case eDownloadingNews:
m_curState = eDownloadingMail;
if (m_downloadMail)
DownloadMail();
else
AdvanceToNextState(NS_OK);
break;
case eDownloadingMail:
m_curState = eSendingUnsent;
if (m_sendUnsentMessages)
SendUnsentMessages();
else
AdvanceToNextState(NS_OK);
break;
default:
NS_ASSERTION(PR_FALSE, "unhandled current state when downloading for offline");
}
}
return NS_OK;
}
nsresult nsMsgOfflineManager::SynchronizeOfflineImapChanges()
{
nsresult rv = NS_OK;
NS_WITH_SERVICE(nsIImapService, imapService, kCImapService, &rv);
NS_ENSURE_SUCCESS(rv, rv);
return imapService->PlaybackAllOfflineOperations(m_window, this);
}
nsresult nsMsgOfflineManager::SendUnsentMessages()
{
nsresult rv;
nsCOMPtr<nsIMsgSendLater> pMsgSendLater = do_CreateInstance(kMsgSendLaterCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
NS_WITH_SERVICE(nsIMsgAccountManager,accountManager,kCMsgAccountManagerCID,&rv);
NS_ENSURE_SUCCESS(rv, rv);
// now we have to iterate over the identities, finding the *unique* unsent messages folder
// for each one, determine if they have unsent messages, and if so, add them to the list
// of identities to send unsent messages from.
// However, I think there's only ever one unsent messages folder at the moment,
// so I think we'll go with that for now.
nsCOMPtr<nsISupportsArray> identities;
if (NS_SUCCEEDED(rv) && accountManager)
{
rv = accountManager->GetAllIdentities(getter_AddRefs(identities));
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr <nsIMsgIdentity> identityToUse;
PRUint32 numIndentities;
identities->Count(&numIndentities);
for (PRUint32 i = 0; i < numIndentities; i++)
{
// convert supports->Identity
nsCOMPtr<nsISupports> thisSupports;
rv = identities->GetElementAt(i, getter_AddRefs(thisSupports));
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIMsgIdentity> thisIdentity = do_QueryInterface(thisSupports, &rv);
if (NS_SUCCEEDED(rv) && thisIdentity)
{
nsCOMPtr <nsIMsgFolder> outboxFolder;
pMsgSendLater->GetUnsentMessagesFolder(thisIdentity, getter_AddRefs(outboxFolder));
if (outboxFolder)
{
PRInt32 numMessages;
outboxFolder->GetTotalMessages(PR_FALSE, &numMessages);
if (numMessages > 0)
{
identityToUse = thisIdentity;
break;
}
}
}
}
if (identityToUse)
{
pMsgSendLater->AddListener(this);
pMsgSendLater->SetMsgWindow(m_window);
rv = pMsgSendLater->SendUnsentMessages(identityToUse);
// if we succeeded, return - we'll run the next operation when the
// send finishes. Otherwise, advance to the next state.
if (NS_SUCCEEDED(rv))
return rv;
}
return AdvanceToNextState(rv);
}
nsresult nsMsgOfflineManager::DownloadOfflineNewsgroups()
{
nsresult rv;
NS_WITH_SERVICE(nsINntpService, nntpService, kNntpServiceCID, &rv);
if (NS_SUCCEEDED(rv) && nntpService)
rv = nntpService->DownloadNewsgroupsForOffline(m_window, this);
if (!NS_SUCCEEDED(rv))
return AdvanceToNextState(rv);
return rv;
}
nsresult nsMsgOfflineManager::DownloadMail()
{
nsresult rv = NS_OK;
NS_WITH_SERVICE(nsIImapService, imapService, kCImapService, &rv);
NS_ENSURE_SUCCESS(rv, rv);
return imapService->DownloadAllOffineImapFolders(m_window, this);
// ### we should do get new mail on pop servers, and download imap messages for offline use.
}
/* void goOnline (in boolean sendUnsentMessages, in boolean playbackOfflineImapOperations, in nsIMsgWindow aMsgWindow); */
NS_IMETHODIMP nsMsgOfflineManager::GoOnline(PRBool sendUnsentMessages, PRBool playbackOfflineImapOperations, nsIMsgWindow *aMsgWindow)
{
m_sendUnsentMessages = sendUnsentMessages;
m_playbackOfflineImapOps = playbackOfflineImapOperations;
m_curOperation = eGoingOnline;
SetWindow(aMsgWindow);
if (!m_sendUnsentMessages && !playbackOfflineImapOperations)
{
return SetOnlineState(PR_TRUE);
}
else
AdvanceToNextState(NS_OK);
return NS_OK;
}
/* void synchronizeForOffline (in boolean downloadNews, in boolean downloadMail, in boolean sendUnsentMessages, in boolean goOfflineWhenDone, in nsIMsgWindow aMsgWindow); */
NS_IMETHODIMP nsMsgOfflineManager::SynchronizeForOffline(PRBool downloadNews, PRBool downloadMail, PRBool sendUnsentMessages, PRBool goOfflineWhenDone, nsIMsgWindow *aMsgWindow)
{
m_curOperation = eDownloadingForOffline;
nsresult rv = NS_OK;
m_downloadNews = downloadNews;
m_downloadMail = downloadMail;
m_sendUnsentMessages = sendUnsentMessages;
m_window = aMsgWindow;
m_goOfflineWhenDone = goOfflineWhenDone;
m_curState = eNoState;
if (!downloadNews && !downloadMail && !sendUnsentMessages)
{
if (goOfflineWhenDone)
return SetOnlineState(PR_FALSE);
}
else
return AdvanceToNextState(NS_OK);
return NS_OK;
}
nsresult nsMsgOfflineManager::SetOnlineState(PRBool online)
{
nsresult rv;
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
if (NS_SUCCEEDED(rv) && netService)
{
rv = netService->SetOffline(!online);
}
return rv;
}
// nsIUrlListener methods
NS_IMETHODIMP
nsMsgOfflineManager::OnStartRunningUrl(nsIURI * aUrl)
{
return NS_OK;
}
NS_IMETHODIMP
nsMsgOfflineManager::OnStopRunningUrl(nsIURI * aUrl, nsresult aExitCode)
{
AdvanceToNextState(aExitCode);
return NS_OK;
}
NS_IMETHODIMP nsMsgOfflineManager::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData)
{
return NS_OK;
}
// nsIMsgSendLaterListener implementation
NS_IMETHODIMP nsMsgOfflineManager::OnStartSending(PRUint32 aTotalMessageCount)
{
return NS_OK;
}
NS_IMETHODIMP nsMsgOfflineManager::OnProgress(PRUint32 aCurrentMessage, PRUint32 aTotalMessage)
{
if (m_statusFeedback && aTotalMessage)
return m_statusFeedback->ShowProgress ((100 * aCurrentMessage) / aTotalMessage);
else
return NS_OK;
}
NS_IMETHODIMP nsMsgOfflineManager::OnStatus(const PRUnichar *aMsg)
{
if (m_statusFeedback && aMsg)
return m_statusFeedback->ShowStatusString (aMsg);
else
return NS_OK;
}
NS_IMETHODIMP nsMsgOfflineManager::OnStopSending(nsresult aStatus, const PRUnichar *aMsg, PRUint32 aTotalTried,
PRUint32 aSuccessful)
{
#ifdef NS_DEBUG
if (NS_SUCCEEDED(aStatus))
printf("SendLaterListener::OnStopSending: Tried to send %d messages. %d successful.\n",
aTotalTried, aSuccessful);
#endif
return AdvanceToNextState(aStatus);
}

View File

@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMsgOfflineManager_h__
#define nsMsgOfflineManager_h__
#include "nscore.h"
#include "nsIMsgOfflineManager.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "nsIUrlListener.h"
#include "nsIMsgWindow.h"
#include "nsIMsgSendLaterListener.h"
class nsMsgOfflineManager
: public nsIMsgOfflineManager,
public nsIObserver,
public nsSupportsWeakReference,
public nsIMsgSendLaterListener,
public nsIUrlListener
{
public:
nsMsgOfflineManager();
virtual ~nsMsgOfflineManager();
NS_DECL_ISUPPORTS
/* nsIMsgOfflineManager methods */
NS_DECL_NSIMSGOFFLINEMANAGER
NS_DECL_NSIOBSERVER
NS_DECL_NSIURLLISTENER
NS_DECL_NSIMSGSENDLATERLISTENER
typedef enum
{
eStarting = 0,
eSynchronizingOfflineImapChanges = 1,
eDownloadingNews = 2,
eDownloadingMail = 3,
eSendingUnsent = 4,
eDone = 5,
eNoState = 6 // we're not doing anything
} offlineManagerState;
typedef enum
{
eGoingOnline = 0,
eDownloadingForOffline = 1,
eNoOp = 2 // no operation in progress
} offlineManagerOperation;
private:
nsresult AdvanceToNextState(nsresult exitStatus);
nsresult SynchronizeOfflineImapChanges();
nsresult StopRunning(nsresult exitStatus);
nsresult SendUnsentMessages();
nsresult DownloadOfflineNewsgroups();
nsresult DownloadMail();
nsresult SetOnlineState(PRBool online);
PRBool m_inProgress;
PRBool m_sendUnsentMessages;
PRBool m_downloadNews;
PRBool m_downloadMail;
PRBool m_playbackOfflineImapOps;
PRBool m_goOfflineWhenDone;
offlineManagerState m_curState;
offlineManagerOperation m_curOperation;
nsCOMPtr <nsIMsgWindow> m_window;
nsCOMPtr <nsIMsgStatusFeedback> m_statusFeedback;
};
#endif

View File

@ -0,0 +1,162 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "msgCore.h"
#include "nsMsgSearchDBView.h"
#include "nsIMsgHdr.h"
#include "nsIMsgThread.h"
nsMsgSearchDBView::nsMsgSearchDBView()
{
/* member initializers and constructor code */
// don't try to display messages for the search pane.
mSupressMsgDisplay = PR_TRUE;
}
nsMsgSearchDBView::~nsMsgSearchDBView()
{
/* destructor code */
}
NS_IMPL_ADDREF_INHERITED(nsMsgSearchDBView, nsMsgDBView)
NS_IMPL_RELEASE_INHERITED(nsMsgSearchDBView, nsMsgDBView)
NS_IMPL_QUERY_HEAD(nsMsgSearchDBView)
NS_IMPL_QUERY_BODY(nsIMsgSearchNotify)
NS_IMPL_QUERY_TAIL_INHERITING(nsMsgDBView)
NS_IMETHODIMP nsMsgSearchDBView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder, nsMsgViewFlagsTypeValue viewFlags, PRInt32 *pCount)
{
nsresult rv;
m_folders = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = nsMsgDBView::Open(folder, sortType, sortOrder, viewFlags, pCount);
NS_ENSURE_SUCCESS(rv, rv);
if (pCount)
*pCount = 0;
return rv;
}
NS_IMETHODIMP nsMsgSearchDBView::GetCellText(PRInt32 aRow, const PRUnichar * aColID, PRUnichar ** aValue)
{
nsresult rv;
if (aColID[0] == 'l') // location
{
nsCOMPtr <nsIMsgDBHdr> msgHdr;
rv = GetMsgHdrForViewIndex(aRow, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
return FetchLocation(msgHdr, aValue);
}
else
return nsMsgDBView::GetCellText(aRow, aColID, aValue);
}
nsresult nsMsgSearchDBView::FetchLocation(nsIMsgDBHdr * aHdr, PRUnichar ** aSizeString)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsMsgSearchDBView::GetMsgHdrForViewIndex(nsMsgViewIndex index, nsIMsgDBHdr **msgHdr)
{
nsresult rv;
nsCOMPtr <nsISupports> supports = getter_AddRefs(m_folders->ElementAt(index));
if(supports)
{
nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(supports);
if (folder)
{
nsCOMPtr <nsIMsgDatabase> db;
rv = folder->GetMsgDatabase(mMsgWindow, getter_AddRefs(db));
NS_ENSURE_SUCCESS(rv, rv);
if (db)
rv = db->GetMsgHdrForKey(m_keys.GetAt(index), msgHdr);
}
}
return rv;
}
NS_IMETHODIMP nsMsgSearchDBView::GetFolderForViewIndex(nsMsgViewIndex index, nsIMsgFolder **aFolder)
{
return m_folders->QueryElementAt(index, NS_GET_IID(nsIMsgFolder), (void **) aFolder);
}
nsresult nsMsgSearchDBView::GetDBForViewIndex(nsMsgViewIndex index, nsIMsgDatabase **db)
{
nsCOMPtr <nsIMsgFolder> aFolder;
GetFolderForViewIndex(index, getter_AddRefs(aFolder));
if (aFolder)
return aFolder->GetMsgDatabase(nsnull, getter_AddRefs(db));
else
return NS_MSG_INVALID_DBVIEW_INDEX;
}
NS_IMETHODIMP
nsMsgSearchDBView::OnSearchHit(nsIMsgDBHdr* aMsgHdr, nsIMsgFolder *folder)
{
NS_ENSURE_ARG(aMsgHdr);
NS_ENSURE_ARG(folder);
nsCOMPtr <nsISupports> supports = do_QueryInterface(folder);
m_folders->AppendElement(supports);
nsresult rv = NS_OK;
nsMsgKey msgKey;
PRUint32 msgFlags;
aMsgHdr->GetMessageKey(&msgKey);
aMsgHdr->GetFlags(&msgFlags);
m_keys.Add(msgKey);
m_levels.Add(0);
m_flags.Add(msgFlags);
if (mOutliner)
mOutliner->RowCountChanged(m_keys.GetSize() - 1, 1);
return rv;
}
NS_IMETHODIMP
nsMsgSearchDBView::OnSearchDone(nsresult status)
{
return NS_OK;
}
// for now also acts as a way of resetting the search datasource
NS_IMETHODIMP
nsMsgSearchDBView::OnNewSearch()
{
if (mOutliner)
{
PRInt32 viewSize = m_keys.GetSize();
mOutliner->RowCountChanged(0, -viewSize); // all rows gone.
}
m_folders->Clear();
m_keys.RemoveAll();
m_levels.RemoveAll();
m_flags.RemoveAll();
// mSearchResults->Clear();
return NS_OK;
}

View File

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _nsMsgSearchDBViewsH_
#define _nsMsgSearchDBView_H_
#include "nsMsgDBView.h"
#include "nsIMsgSearchNotify.h"
class nsMsgSearchDBView : public nsMsgDBView, public nsIMsgSearchNotify
{
public:
nsMsgSearchDBView();
virtual ~nsMsgSearchDBView();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIMSGSEARCHNOTIFY
virtual const char * GetViewName(void) {return "SearchView"; }
NS_IMETHOD Open(nsIMsgFolder *folder, nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder,
nsMsgViewFlagsTypeValue viewFlags, PRInt32 *pCount);
// override to get location
NS_IMETHOD GetCellText(PRInt32 aRow, const PRUnichar * aColID, PRUnichar ** aValue);
virtual nsresult GetMsgHdrForViewIndex(nsMsgViewIndex index, nsIMsgDBHdr **msgHdr);
NS_IMETHOD GetFolderForViewIndex(nsMsgViewIndex index, nsIMsgFolder **folder);
protected:
nsresult FetchLocation(nsIMsgDBHdr * aHdr, PRUnichar ** aSizeString);
virtual nsresult GetDBForViewIndex(nsMsgViewIndex index, nsIMsgDatabase **db);
nsCOMPtr <nsISupportsArray> m_folders; // maybe we should store ranges, or the actual headers instead.
};
#endif

View File

@ -0,0 +1,319 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "msgCore.h"
#include "nsMsgSpecialViews.h"
#include "nsIMsgThread.h"
nsMsgThreadsWithUnreadDBView::nsMsgThreadsWithUnreadDBView()
{
}
nsMsgThreadsWithUnreadDBView::~nsMsgThreadsWithUnreadDBView()
{
}
NS_IMETHODIMP nsMsgThreadsWithUnreadDBView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder, nsMsgViewFlagsTypeValue viewFlags, PRInt32 *pCount)
{
return nsMsgThreadedDBView::Open(folder, sortType, sortOrder, viewFlags, pCount);
}
NS_IMETHODIMP nsMsgThreadsWithUnreadDBView::GetViewType(nsMsgViewTypeValue *aViewType)
{
NS_ENSURE_ARG_POINTER(aViewType);
*aViewType = nsMsgViewType::eShowThreadsWithUnread;
return NS_OK;
}
PRBool nsMsgThreadsWithUnreadDBView::WantsThisThread(nsIMsgThread *threadHdr)
{
if (threadHdr)
{
PRUint32 numNewChildren;
threadHdr->GetNumUnreadChildren(&numNewChildren);
if (numNewChildren > 0)
return PR_TRUE;
}
return PR_FALSE;
}
nsresult nsMsgThreadsWithUnreadDBView::AddMsgToThreadNotInView(nsIMsgThread *threadHdr, nsIMsgDBHdr *msgHdr, PRBool ensureListed)
{
nsresult rv = NS_OK;
nsCOMPtr <nsIMsgDBHdr> parentHdr;
PRUint32 msgFlags;
PRUint32 newFlags;
msgHdr->GetFlags(&msgFlags);
GetFirstMessageHdrToDisplayInThread(threadHdr, getter_AddRefs(parentHdr));
if (parentHdr && (ensureListed || !(msgFlags & MSG_FLAG_READ)))
{
parentHdr->OrFlags(MSG_VIEW_FLAG_HASCHILDREN | MSG_VIEW_FLAG_ISTHREAD, &newFlags);
if (!(m_viewFlags & nsMsgViewFlagsType::kUnreadOnly))
parentHdr->OrFlags(MSG_FLAG_ELIDED, &newFlags);
rv = AddHdr(parentHdr);
}
return rv;
}
NS_IMETHODIMP nsMsgWatchedThreadsWithUnreadDBView::GetViewType(nsMsgViewTypeValue *aViewType)
{
NS_ENSURE_ARG_POINTER(aViewType);
*aViewType = nsMsgViewType::eShowWatchedThreadsWithUnread;
return NS_OK;
}
PRBool nsMsgWatchedThreadsWithUnreadDBView::WantsThisThread(nsIMsgThread *threadHdr)
{
if (threadHdr)
{
PRUint32 numNewChildren;
PRUint32 threadFlags;
threadHdr->GetNumUnreadChildren(&numNewChildren);
threadHdr->GetFlags(&threadFlags);
if (numNewChildren > 0 && (threadFlags & MSG_FLAG_WATCHED) != 0)
return PR_TRUE;
}
return PR_FALSE;
}
nsresult nsMsgWatchedThreadsWithUnreadDBView::AddMsgToThreadNotInView(nsIMsgThread *threadHdr, nsIMsgDBHdr *msgHdr, PRBool ensureListed)
{
nsresult rv = NS_OK;
PRUint32 threadFlags;
PRUint32 msgFlags, newFlags;
msgHdr->GetFlags(&msgFlags);
threadHdr->GetFlags(&threadFlags);
if (threadFlags & MSG_FLAG_WATCHED)
{
nsCOMPtr <nsIMsgDBHdr> parentHdr;
GetFirstMessageHdrToDisplayInThread(threadHdr, getter_AddRefs(parentHdr));
if (parentHdr && (ensureListed || !(msgFlags & MSG_FLAG_READ)))
{
parentHdr->OrFlags(MSG_FLAG_ELIDED | MSG_VIEW_FLAG_HASCHILDREN | MSG_VIEW_FLAG_ISTHREAD, &newFlags);
rv = AddHdr(parentHdr);
}
}
return rv;
}
#ifdef WE_DO_CACHELESS_VIEWS
// This view will initially be used for cacheless IMAP.
CachelessView::CachelessView(ViewType viewType)
{
m_viewType = viewType;
m_viewFlags = kThreadedDisplay;
SetInitialSortState();
m_folder = NULL;
m_master = NULL;
m_sizeInitialized = FALSE;
#ifdef DEBUG_bienvenu
SetViewSize(1); // start off with a size until we figure out how to hook up IMAP response to view.
#endif
}
CachelessView::~CachelessView()
{
}
MsgERR CachelessView::Open(MessageDB *messageDB, ViewType viewType, /*WORD viewFlags,*/ uint32* pCount, XP_Bool runInForeground)
{
MsgERR err;
if ((err = MessageDBView::Open(messageDB, viewType, pCount, runInForeground)) != eSUCCESS)
return err;
if (pCount)
*pCount = 0;
return Init(pCount, runInForeground);
}
MsgERR CachelessView::SetViewSize(int32 setSize)
{
m_idArray.RemoveAll();
// Initialize whole view as MSG_MESSAGEKEYNONE
m_idArray.InsertAt(0, MSG_MESSAGEKEYNONE, setSize);
m_flags.InsertAt(0, 0, setSize);
m_levels.InsertAt(0, 0, setSize);
return eSUCCESS;
}
void CachelessView::ClearPendingIds()
{
for (MSG_ViewIndex viewIndex = m_curStartSeq - 1; viewIndex < m_curEndSeq; viewIndex++)
{
if (GetAt(viewIndex) == kIdPending)
SetKeyByIndex(viewIndex, kIdNone);
}
}
/*static*/ void CachelessView::ExitFunction (URL_Struct * /* URL_s */, int /* status */, MWContext *context)
{
// need to remove kIdPending from view
MSG_Pane *pane = context->imapURLPane;
if (pane)
{
MessageDBView *view = pane->GetMsgView();
if (view && view->GetViewType() == ViewCacheless)
{
CachelessView *cachelessView = (CachelessView *) view;
cachelessView->ClearPendingIds();
}
}
}
MsgERR CachelessView::ListShortMsgHdrByIndex(MSG_ViewIndex startIndex, int numToList, MSG_MessageLine *pOutput, int *pNumListed)
{
MsgERR err = eSUCCESS;
XP_BZERO(pOutput, sizeof(*pOutput) * numToList);
int i;
for (i = 0; i < numToList && err == eSUCCESS; i++)
{
(pOutput + i)->messageKey = MSG_MESSAGEKEYNONE;
if (i + startIndex < m_idArray.GetSize())
{
MessageKey keyToList = m_idArray.GetAt(i + startIndex);
if (keyToList != kIdNone && keyToList != kIdPending)
{
err = m_messageDB->GetShortMessageHdr(m_idArray[i + startIndex], pOutput + i);
if (err == eSUCCESS)
{
char extraFlag = m_flags[i + startIndex];
CopyExtraFlagsToPublicFlags(extraFlag, &((pOutput + i)->flags));
(pOutput + i)->level = 0;
}
}
else if (keyToList == kIdNone)
{
if (m_folder->GetType() == FOLDER_IMAPMAIL)
{
XPPtrArray panes;
MSG_IMAPFolderInfoMail *imapFolder = (MSG_IMAPFolderInfoMail *) m_folder;
m_curStartSeq = startIndex + 1; // imap sequence #'s seem to be 1 relative
m_curEndSeq = m_curStartSeq + MAX(10, numToList);
// What's a good chunk size to list? Try 10 for now, or numToList.
if (m_curStartSeq + 1 < m_idArray.GetSize())
{
MessageKey nextKeyToList = m_idArray.GetAt(m_curStartSeq + 1);
if (nextKeyToList != kIdNone && nextKeyToList != kIdPending && m_curStartSeq > 0)
{
nextKeyToList = m_idArray.GetAt(startIndex - 1);
if (nextKeyToList == kIdNone)
{
MSG_ViewIndex tempStart = m_curStartSeq;
m_curStartSeq = m_curStartSeq - MIN(10, m_curStartSeq - 1);
m_curEndSeq = tempStart;
}
}
}
if (!m_sizeInitialized && imapFolder->GetMailboxSpec()->number_of_messages > 0)
{
SetViewSize(imapFolder->GetMailboxSpec()->number_of_messages);
m_sizeInitialized = TRUE;
}
m_master->FindPanesReferringToFolder (m_folder, &panes);
MSG_Pane *pane = (panes.GetSize() > 0) ? (MSG_Pane *) panes.GetAt(0) : (MSG_Pane *)NULL;
if (m_curEndSeq > GetSize())
m_curEndSeq = GetSize();
if (pane)
{
char *imapFolderURL = imapFolder->SetupHeaderFetchUrl(pane, GetDB(), m_curStartSeq, m_curEndSeq);
MSG_UrlQueue::AddUrlToPane(imapFolderURL, CachelessView::ExitFunction, pane, NET_SUPER_RELOAD);
FREEIF(imapFolderURL);
}
}
}
}
}
if (pNumListed != NULL)
*pNumListed = i;
return err;
}
MsgERR CachelessView::AddNewMessages()
{
return eSUCCESS;
}
MsgERR CachelessView::AddHdr(nsIMsgDBHdr *msgHdr)
{
char flags = 0;
#ifdef DEBUG_bienvenu
XP_ASSERT((int) m_idArray.GetSize() == m_flags.GetSize() && (int) m_idArray.GetSize() == m_levels.GetSize());
#endif
CopyDBFlagsToExtraFlags(msgHdr->GetFlags(), &flags);
if (msgHdr->GetArticleNum() == msgHdr->GetThreadId())
flags |= kIsThread;
// if unreadonly, level is 0 because we must be the only msg in the thread.
char levelToAdd = (m_viewFlags & kUnreadOnly) ? 0 : msgHdr->GetLevel();
m_idArray.Add(msgHdr->getID());
m_flags.Add(flags);
m_levels.Add(levelToAdd);
NoteChange(m_idArray.GetSize() - 1, 1, MSG_NotifyInsertOrDelete);
OnHeaderAddedOrDeleted();
return eSUCCESS;
}
// for news, xover line, potentially, for IMAP, imap line...
MsgERR CachelessView::AddHdrFromServerLine(char * /*line*/, MessageKey * /*msgId*/)
{
return eSUCCESS;
}
void CachelessView::SetInitialSortState(void)
{
m_sortOrder = SortTypeAscending;
m_sortType = SortById;
}
MsgERR CachelessView::Init(uint32 * /*pCount*/, XP_Bool /* runInForeground */ /* = TRUE */)
{
MsgERR ret = eSUCCESS;
m_sortType = SortById;
MailDB *mailDB = NULL;
if (GetDB())
mailDB = GetDB()->GetMailDB();
if (mailDB)
{
m_master = mailDB->GetMaster();
if (m_master)
{
ENeoString mailBoxName;
mailDB->m_neoFolderInfo->GetMailboxName(mailBoxName);
m_folder = m_master->FindImapMailFolder(mailBoxName);
}
}
return ret;
}
#endif // WE_DO_CACHELESS_VIEW

View File

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _nsMsgSpecialViews_H_
#define _nsMsgSpecialViews_H_
#include "nsMsgThreadedDBView.h"
class nsMsgThreadsWithUnreadDBView : public nsMsgThreadedDBView
{
public:
nsMsgThreadsWithUnreadDBView();
virtual ~nsMsgThreadsWithUnreadDBView();
virtual const char * GetViewName(void) {return "ThreadsWithUnreadView"; }
NS_IMETHOD Open(nsIMsgFolder *folder, nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder, nsMsgViewFlagsTypeValue viewFlags, PRInt32 *pCount);
NS_IMETHOD GetViewType(nsMsgViewTypeValue *aViewType);
virtual PRBool WantsThisThread(nsIMsgThread *threadHdr);
protected:
virtual nsresult AddMsgToThreadNotInView(nsIMsgThread *threadHdr, nsIMsgDBHdr *msgHdr, PRBool ensureListed);
};
class nsMsgWatchedThreadsWithUnreadDBView : public nsMsgThreadedDBView
{
public:
NS_IMETHOD GetViewType(nsMsgViewTypeValue *aViewType);
virtual const char * GetViewName(void) {return "WatchedThreadsWithUnreadView"; }
virtual PRBool WantsThisThread(nsIMsgThread *threadHdr);
protected:
virtual nsresult AddMsgToThreadNotInView(nsIMsgThread *threadHdr, nsIMsgDBHdr *msgHdr, PRBool ensureListed);
};
#ifdef DOING_CACHELESS_VIEW
// This view will initially be used for cacheless IMAP.
class nsMsgCachelessView : public nsMsgDBView
{
public:
nsMsgCachelessView();
NS_IMETHOD GetViewType(nsMsgViewTypeValue *aViewType);
virtual ~nsMsgCachelessView();
virtual const char * GetViewName(void) {return "nsMsgCachelessView"; }
NS_IMETHOD Open(nsIMsgFolder *folder, nsMsgViewSortTypeValue viewType, PRInt32 *count);
nsresult SetViewSize(PRInt32 setSize); // Override
virtual nsresult AddNewMessages() ;
virtual nsresult AddHdr(nsIMsgDBHdr *msgHdr);
// for news, xover line, potentially, for IMAP, imap line...
virtual nsresult AddHdrFromServerLine(char *line, nsMsgKey *msgId) ;
virtual void SetInitialSortState(void);
virtual nsresult Init(PRUint32 *pCount);
protected:
void ClearPendingIds();
nsIMsgFolder *m_folder;
nsMsgViewIndex m_curStartSeq;
nsMsgViewIndex m_curEndSeq;
PRBool m_sizeInitialized;
};
#endif /* DOING_CACHELESS_VIEW */
#endif