?? updatebar.cpp.svn-base
字號:
/**
* UpdateBar.cpp
*
* Copyright (C) 2008 David Andrs <pda@jasnapaka.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "StdAfx.h"
#include "prssr.h"
#include "../share/UIHelper.h"
#include "../share/fs.h"
#include "UpdateBar.h"
#include "Appearance.h"
#include "misc.h"
#include "MainFrm.h"
#include "Config.h"
#include "Errors.h"
#include "SuspendKiller.h"
#include "net/Connection.h"
#include "net/Download.h"
#include "xml/FeedFile.h"
#include "Site.h"
#include "www/LocalHtmlFile.h"
#include "misc/shnotif.h"
#ifdef MYDEBUG
#undef THIS_FILE
static TCHAR THIS_FILE[] = _T(__FILE__);
#include "debug\crtdbg.h"
#define new MYDEBUG_NEW
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define BUFSIZE 8192
static BOOL TranslateForOfflineReading(const CString &srcFileName, const CString &destFileName, const CString &srcEncoding = _T("windows-1251")) {
LOG2(5, "TranslateForOfflineReading('%S', '%S')", srcFileName, destFileName);
BOOL translated = FALSE;
if (Config.AdvancedHtmlOptimizer) {
MoveFile(srcFileName, destFileName);
}
else {
CLocalHtmlFile file;
file.LoadFromFile(srcFileName);
file.DetectEncoding(srcEncoding);
file.Filter();
// TODO: find the content and drop everything else
file.TranslateForOffline();
file.Recode();
file.Save(destFileName);
}
return TRUE;
}
void ClearCacheFiles(EFileType type, const CString &cacheLocation, CStringList &deleteList) {
LOG0(5, "ClearCacheFiles()");
CString rootDir = GetCachePath(type, cacheLocation);
while (!deleteList.IsEmpty()) {
CString strPath = deleteList.RemoveHead();
DeleteFile(strPath);
RemoveEmptyDirs(strPath, rootDir);
}
}
void ClearImages(CArray<CFeedItem *, CFeedItem *> &items) {
LOG0(1, "ClearImages()");
CStringList files;
for (int i = 0; i < items.GetSize(); i++) {
CFeedItem *fi = items.GetAt(i);
CStringList links;
// clear images
fi->GetItemImages(links);
while (!links.IsEmpty()) {
CString url = links.RemoveHead();
files.AddTail(GetCacheFile(FILE_TYPE_IMAGE, Config.CacheLocation, url));
}
}
if (files.GetCount() > 0) {
ClearCacheFiles(FILE_TYPE_IMAGE, Config.CacheLocation, files);
}
}
void ClearHtmlPages(CArray<CFeedItem *, CFeedItem *> &items) {
LOG0(1, "ClearHtmlPages()");
CStringList files;
for (int i = 0; i < items.GetSize(); i++) {
CFeedItem *fi = items.GetAt(i);
files.AddTail(GetCacheFile(FILE_TYPE_HTML, Config.CacheLocation, fi->Link));
}
if (files.GetCount() > 0)
ClearCacheFiles(FILE_TYPE_HTML, Config.CacheLocation, files);
}
void ClearEnclosures(CArray<CFeedItem *, CFeedItem *> &items) {
LOG0(1, "ClearEnclosures()");
CStringList files;
for (int i = 0; i < items.GetSize(); i++) {
CFeedItem *fi = items.GetAt(i);
CStringList links;
// clear enclosures
fi->GetEnclosures(links);
while (!links.IsEmpty()) {
CString url = links.RemoveHead();
files.AddTail(GetCacheFile(FILE_TYPE_ENCLOSURE, Config.CacheLocation, url));
}
}
if (files.GetCount() > 0)
ClearCacheFiles(FILE_TYPE_ENCLOSURE, Config.CacheLocation, files);
}
//
// CDownloadQueue
//
CDownloadQueue::CDownloadQueue() {
InitializeCriticalSection(&CS);
}
CDownloadQueue::~CDownloadQueue() {
DeleteCriticalSection(&CS);
}
BOOL CDownloadQueue::IsEmpty() {
EnterCriticalSection(&CS);
BOOL b = Items.IsEmpty();
LeaveCriticalSection(&CS);
return b;
}
int CDownloadQueue::GetCount() {
EnterCriticalSection(&CS);
int cnt = Items.GetCount();
LeaveCriticalSection(&CS);
return cnt;
}
void CDownloadQueue::Enqueue(CDownloadItem *item) {
EnterCriticalSection(&CS);
Items.AddTail(item);
LeaveCriticalSection(&CS);
// SetEvent(HDownloadQNewItem); // notify download thread that it has some work to do
}
CDownloadItem *CDownloadQueue::Dequeue() {
EnterCriticalSection(&CS);
CDownloadItem *item = Items.RemoveHead();
LeaveCriticalSection(&CS);
return item;
}
//
// CUpdateBar
//
DWORD WINAPI UpdateStubProc(LPVOID lpParameter) {
CUpdateBar *bar = (CUpdateBar *) lpParameter;
bar->UpdateThread();
return 0;
}
CUpdateBar::CUpdateBar() {
LOG0(5, "CUpdateBar::CUpdateBar()");
HUpdateThread = NULL;
Downloader = NULL;
ErrorCount = 0;
Terminate = FALSE;
InitializeCriticalSection(&CSUpdateList);
InitializeCriticalSection(&CSDownloader);
}
CUpdateBar::~CUpdateBar() {
LOG0(5, "CUpdateBar::~CUpdateBar()");
DeleteCriticalSection(&CSDownloader);
DeleteCriticalSection(&CSUpdateList);
}
BOOL CUpdateBar::Create(CWnd *pParentWnd) {
// DWORD dwStyle = WS_CHILD | CBRS_BOTTOM;
// m_dwStyle = dwStyle;
m_dwStyle = CBRS_BOTTOM;
BOOL ret;
CRect rect; rect.SetRectEmpty();
ret = CWnd::Create(NULL, NULL, WS_CHILD, rect, pParentWnd, AFX_IDW_TOOLBAR + 2);
m_ctlProgress.Create(WS_CHILD | WS_VISIBLE | PBS_SMOOTH, CRect(0, 0, 0, 0), this, IDC_UPDATE_PROGRESS);
m_ctlText.Create(_T(""), WS_CHILD | SS_LEFTNOWORDWRAP | SS_NOTIFY | SS_NOPREFIX, CRect(0, 0, 0, 0), this, IDC_UPDATE_TEXT);
m_ctlText.SetFont(&Appearance.BaseFont);
m_ctlStopBtn.Create(NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, CRect(0, 0, 0, 0), this, IDC_UPDATE_STOP);
AfxSetResourceHandle(theApp.GetDPISpecificInstanceHandle());
m_ctlStopBtn.LoadBitmaps(IDB_CLOSE);
AfxSetResourceHandle(AfxGetInstanceHandle());
m_ctlStopBtn.SizeToContent();
return ret;
}
void CUpdateBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler) {
}
CSize CUpdateBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz) {
LOG0(1, "CUpdateBar::CalcFixedLayout()");
CDC *pDC = GetDC();
int cx = pDC->GetDeviceCaps(HORZRES);
ReleaseDC(pDC);
return CSize(cx, SCALEY(21) - 1);
}
void CUpdateBar::Redraw() {
UpdateProgressText();
m_ctlProgress.Redraw(FALSE);
}
void CUpdateBar::EnqueueSite(CSiteItem *site, BOOL updateOnly) {
LOG0(1, "CUpdateBar::EnqueueSites()");
EnterCriticalSection(&CSUpdateList);
UpdateList.AddTail(new CUpdateItem(site, updateOnly));
LeaveCriticalSection(&CSUpdateList);
}
void CUpdateBar::EnqueueSites(CList<CSiteItem *, CSiteItem *> &sites, BOOL updateOnly) {
LOG0(1, "CUpdateBar::EnqueueSites()");
EnterCriticalSection(&CSUpdateList);
POSITION pos = sites.GetHeadPosition();
while (pos != NULL) {
CSiteItem *si = sites.GetNext(pos);
UpdateList.AddTail(new CUpdateItem(si, updateOnly));
}
LeaveCriticalSection(&CSUpdateList);
}
void CUpdateBar::EnqueueImages(CArray<CFeedItem *, CFeedItem *> &items) {
LOG0(1, "CUpdateBar::EnqueueImages()");
for (int i = 0; i < items.GetSize(); i++) {
CFeedItem *fi = items.GetAt(i);
//
CStringList images;
fi->GetItemImages(images);
POSITION pos = images.GetHeadPosition();
while (pos != NULL) {
CString imgUrl = images.GetNext(pos);
EnqueueItem(imgUrl, FILE_TYPE_IMAGE);
}
}
}
void CUpdateBar::EnqueueHtml(const CString &url, CSiteItem *siteItem) {
// URL rewriting
CString surl = SanitizeUrl(url);
CString rurl;
if (Config.UseHtmlOptimizer) rurl = MakeHtmlOptimizerUrl(surl, Config.HtmlOptimizerURL);
else rurl = RewriteUrl(surl, Config.RewriteRules);
CString strFileName = GetCacheFile(FILE_TYPE_HTML, Config.CacheLocation, surl);
if (!FileExists(strFileName)) {
CDownloadItem *di = new CDownloadItem();
di->URL = rurl;
di->Type = FILE_TYPE_HTML;
di->Try = DOWNLOAD_TRIES;
di->FileName = strFileName;
di->SiteIdx = SiteList.GetIndexOf(siteItem);
DownloadQueue.Enqueue(di);
}
}
void CUpdateBar::EnqueueHtmls(CArray<CFeedItem *, CFeedItem *> &items) {
LOG0(1, "CUpdateBar::EnqueueHtml()");
for (int i = 0; i < items.GetSize(); i++) {
CFeedItem *fi = items.GetAt(i);
EnqueueHtml(fi->Link, fi->SiteItem);
}
}
void CUpdateBar::EnqueueEnclosures(CArray<CFeedItem *, CFeedItem *> &items, DWORD limit/* = 0*/) {
LOG0(1, "CUpdateBar::EnqueueEnclosures()");
for (int i = 0; i < items.GetSize(); i++) {
CFeedItem *fi = items.GetAt(i);
//
CStringList encs;
fi->GetEnclosures(encs);
POSITION pos = encs.GetHeadPosition();
while (pos != NULL) {
CString encUrl = encs.GetNext(pos);
EnqueueItem(encUrl, FILE_TYPE_ENCLOSURE);
}
}
}
void CUpdateBar::EnqueueItem(const CString &strUrl, EFileType type) {
CString url = SanitizeUrl(strUrl);
CString strFileName = GetCacheFile(type, Config.CacheLocation, url);
if (!FileExists(strFileName)) {
CDownloadItem *di = new CDownloadItem();
di->URL = strUrl;
di->Type = type;
di->Try = DOWNLOAD_TRIES;
di->FileName = strFileName;
di->SiteIdx = SITE_INVALID;
DownloadQueue.Enqueue(di);
}
}
void CUpdateBar::Start() {
LOG0(1, "CUpdateBar::Start()");
if (HUpdateThread == NULL && (UpdateList.GetCount() > 0 || DownloadQueue.GetCount() > 0)) {
if (Config.ClearErrorLog)
Errors.Cleanup();
DownloadQueue.FinishedItems = 0;
HUpdateThread = CreateThread(NULL, 0, UpdateStubProc, this, 0, NULL);
// SetThreadPriority(HUpdateThread, THREAD_PRIORITY_LOWEST);
}
}
void CUpdateBar::UpdateFeeds() {
LOG0(1, "CUpdateBar::UpdateFeeds()");
m_ctlProgress.SetRange(0, UpdateList.GetCount());
m_ctlProgress.SetPos(0);
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
EnterCriticalSection(&CSDownloader);
/* Downloader = new CDownloader;
CFeedSync *sync = NULL;
switch (Config.SyncSite) {
case SYNC_SITE_GOOGLE_READER: sync = new CGReaderSync(Downloader, Config.SyncUserName, Config.SyncPassword); break;
default: sync = new CNetworkSync(Downloader); break;
}
*/
Downloader = &frame->Downloader;
CFeedSync *sync = frame->Syncer;
LeaveCriticalSection(&CSDownloader);
BOOL authenticated;
if (sync->NeedAuth()) {
State = UPDATE_STATE_AUTHENTICATING;
UpdateProgressText();
authenticated = sync->Authenticate();
}
else
authenticated = TRUE;
if (authenticated) {
if (Config.SyncSite == 0)
State = UPDATE_STATE_RSS;
else
State = UPDATE_STATE_SYNCING;
UpdateProgressText();
// sync
POSITION pos = UpdateList.GetHeadPosition();
while (!Terminate && pos != NULL) {
EnterCriticalSection(&CSUpdateList);
CUpdateItem *ui = UpdateList.GetNext(pos);
CSiteItem *si = ui->SiteItem;
LeaveCriticalSection(&CSUpdateList);
SiteName = si->Name;
Redraw();
LOG1(3, "Syncing %S", si->Name);
si->EnsureSiteLoaded();
// sync feed
CFeed *feed = new CFeed;
if (sync->SyncFeed(si, feed, ui->UpdateOnly)) {
si->Status = CSiteItem::Ok;
if (si->Feed == NULL) {
si->Feed = new CFeed();
si->Feed->Copyright = feed->Copyright;
si->Feed->Description = feed->Description;
si->Feed->HtmlUrl = feed->HtmlUrl;
si->Feed->Language = feed->Language;
si->Feed->Published = feed->Published;
si->Feed->Title = feed->Title;
si->Feed->UpdateInterval = feed->UpdateInterval;
}
// If the authentication was not required, SavePassword is FALSE
if (Downloader->GetSavePassword()) {
si->Info->UserName = Downloader->GetUserName();
si->Info->Password = Downloader->GetPassword();
}
// mark all new items in the old feed as unread
for (int i = 0; i < si->Feed->GetItemCount(); i++) {
CFeedItem *fi = si->Feed->GetItem(i);
if (fi->IsNew())
fi->SetFlags(MESSAGE_UNREAD, MESSAGE_READ_STATE);
}
// merge feed
CArray<CFeedItem *, CFeedItem *> newItems;
CArray<CFeedItem *, CFeedItem *> itemsToClean;
sync->MergeFeed(si, feed, newItems, itemsToClean);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -