📄 feedview.cpp.svn-base
字号:
//
// handlers
//
void CFeedView::OnItemOpen() {
// OpenOnlineMessage(m_oItems[m_nSelectFirst]->Link, m_oItems[m_nSelectFirst]->SiteItem);
}
void CFeedView::OnItemMarkRead() {
LOG0(1, "CFeedView::OnItemMarkRead()");
if (m_nSelectFirst != -1) {
int i;
for (i = m_nSelectStart; i <= m_nSelectEnd; i++) {
MarkItem(i, MESSAGE_READ);
InvalidateItem(i, FALSE);
}
if (SiteItem != NULL) {
if (SiteItem->Type == CSiteItem::VFolder && SiteItem->FlagMask == MESSAGE_READ_STATE) {
// delete items
for (i = m_nSelectStart; i <= m_nSelectEnd; i++)
m_oItems.RemoveAt(m_nSelectStart);
AdjustViewTop();
Invalidate(FALSE);
}
else if (SiteItem->Type != CSiteItem::VFolder && Config.HideReadItems) {
// delete items
for (i = m_nSelectStart; i <= m_nSelectEnd; i++)
m_oItems.RemoveAt(m_nSelectStart);
AdjustViewTop();
Invalidate(FALSE);
}
}
DeselectAllItems();
SortItems();
UpdateScrollBars();
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->UpdateTopBar();
}
}
void CFeedView::OnItemMarkUnread() {
LOG0(1, "CFeedView::OnItemMarkUnread()");
if (m_nSelectFirst != -1) {
for (int i = m_nSelectStart; i <= m_nSelectEnd; i++) {
MarkItem(i, MESSAGE_UNREAD);
InvalidateItem(i, FALSE);
}
DeselectAllItems();
SortItems();
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->UpdateTopBar();
}
}
void CFeedView::OnItemMarkNew() {
LOG0(1, "CFeedView::OnItemMarkNew()");
if (m_nSelectFirst != -1) {
for (int i = m_nSelectStart; i <= m_nSelectEnd; i++) {
MarkItem(i, MESSAGE_NEW);
InvalidateItem(i, FALSE);
}
DeselectAllItems();
SortItems();
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->UpdateTopBar();
}
}
void CFeedView::OnItemFlag() {
LOG0(1, "CFeedView::OnItemFlag()");
if (m_nSelectFirst != -1) {
if (SiteItem != NULL) {
if (GetItem(m_nSelectFirst)->IsFlagged())
for (int i = m_nSelectStart; i <= m_nSelectEnd; i++)
UnflagItem(i);
else
for (int i = m_nSelectStart; i <= m_nSelectEnd; i++)
FlagItem(i);
}
DeselectAllItems();
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->UpdateTopBar();
}
}
void CFeedView::OnUpdateItemFlag(CCmdUI *pCmdUI) {
pCmdUI->SetCheck(GetItem(m_nSelectFirst)->IsFlagged());
}
void CFeedView::OnSelectAll() {
LOG0(1, "CFeedView::SelectAll()");
SelectAll();
}
void CFeedView::OnItemDelete() {
LOG0(1, "CFeedView::OnItemDelete()");
if (m_nSelectFirst != -1) {
for (int i = m_nSelectStart; i <= m_nSelectEnd; i++) {
CFeedItem *fi = GetItem(i);
fi->SetFlags(MESSAGE_DELETED, MESSAGE_DELETED);
}
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
// delete from view
int cnt = m_nSelectEnd - m_nSelectStart + 1;
m_oItems.RemoveAt(m_nSelectStart, cnt);
DeselectAllItems();
SortItems();
UpdateScrollBars();
frame->UpdateTopBar();
}
}
void CFeedView::OnUpdateItemSelected(CCmdUI *pCmdUI) {
pCmdUI->Enable(m_nSelectFirst != -1);
}
//
//
//
int CFeedView::MoveToNextItem() {
LOG0(3, "CFeedView::MoveToNextItem()");
if (m_nSelectFirst < m_oItems.GetSize() - 1) {
m_nSelectFirst++;
m_nSelectEnd = m_nSelectStart = m_nSelectFirst;
// FIXME
int y;
if (m_nSelectFirst > 0) y = m_oItemHeight[m_nSelectFirst - 1];
else y = 0;
if (y < m_nViewTop)
m_nViewTop = y;
else if (m_oItemHeight[m_nSelectFirst] > m_nViewTop + m_nClientHeight)
m_nViewTop = m_oItemHeight[m_nSelectFirst] - m_nClientHeight;
AdjustViewTop();
UpdateScrollBars();
Invalidate(FALSE);
}
return m_nSelectFirst;
}
int CFeedView::MoveToPrevItem() {
LOG0(3, "CFeedView::MoveToPrevItem()");
if (m_nSelectFirst > 0) {
m_nSelectFirst--;
m_nSelectEnd = m_nSelectStart = m_nSelectFirst;
// FIXME
int y;
if (m_nSelectFirst > 0) y = m_oItemHeight[m_nSelectFirst - 1];
else y = 0;
if (y < m_nViewTop)
m_nViewTop = y;
else if (m_oItemHeight[m_nSelectFirst] > m_nViewTop + m_nClientHeight)
m_nViewTop = m_oItemHeight[m_nSelectFirst] - m_nClientHeight;
AdjustViewTop();
UpdateScrollBars();
Invalidate(FALSE);
}
return m_nSelectFirst;
}
int CFeedView::MoveToNextChannel() {
LOG0(3, "CFeedView::MoveToNextChannel()");
int oldSiteIdx = Config.ActSiteIdx;
if (Config.ActSiteIdx < SiteList.GetCount() - 1)
Config.ActSiteIdx++;
else if (Config.WrapAround)
Config.ActSiteIdx = 0;
if (oldSiteIdx != Config.ActSiteIdx) {
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->SelectSite(Config.ActSiteIdx);
}
return Config.ActSiteIdx;
}
int CFeedView::MoveToPrevChannel() {
LOG0(3, "CFeedView::MoveToPrevChannel()");
int oldSiteIdx = Config.ActSiteIdx;
if (Config.ActSiteIdx > 0)
Config.ActSiteIdx--;
else if (Config.WrapAround)
Config.ActSiteIdx = SiteList.GetCount() - 1;
if (oldSiteIdx != Config.ActSiteIdx) {
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->SelectSite(Config.ActSiteIdx);
}
return Config.ActSiteIdx;
}
void CFeedView::OpenItem(CFeedItem *fi) {
LOG1(3, "CFeedView::OpenItem(%p)", fi);
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
CSiteItem *si = fi->SiteItem;
// enclosure bar
frame->SwitchView(CMainFrame::ArticleView);
frame->m_wndArticleView.SetFeedItem(fi);
frame->m_wndArticleView.CreateMenu(frame->m_hwndCmdBar);
frame->SetupEnclosureBar(fi);
// setup controls
frame->SetupBanner(fi, m_nSelectFirst + 1, m_oItems.GetSize());
frame->m_wndArticleView.ShowArticle();
frame->UpdateTopBar();
if (si->Feed != NULL) {
for (int i = 0; i < si->Feed->GetItemCount(); i++) {
if (si->Feed->GetItem(i) == fi) {
Config.ActFeedItem = i;
break;
}
}
}
}
void CFeedView::OpenItem(int item) {
LOG1(3, "CFeedView::OpenItem(%d)", item);
if (item < 0 || item >= m_oItems.GetSize())
return;
m_nSelectFirst = m_nSelectStart = m_nSelectEnd = item;
OpenItem(m_oItems.GetAt(item));
MarkItem(item, MESSAGE_READ);
}
void CFeedView::FlagItem(int item) {
LOG1(3, "CFeedView::FlagItem(%d)", item);
CFeedItem *fi = m_oItems.GetAt(item);
fi->SetFlags(MESSAGE_FLAG, MESSAGE_FLAG);
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->SyncItem(fi);
}
void CFeedView::UnflagItem(int item) {
LOG1(3, "CFeedView::UnflagItem(%d)", item);
CFeedItem *fi = m_oItems.GetAt(item);
fi->SetFlags(0, MESSAGE_FLAG);
CMainFrame *frame = (CMainFrame *) AfxGetMainWnd();
frame->SyncItem(fi);
}
void CFeedView::OnCopyUrl() {
LOG0(3, "CFeedView::OnCopyUrl()");
if (m_nSelectFirst != -1) {
CString links;
for (int i = m_nSelectStart; i <= m_nSelectEnd; i++) {
CFeedItem *fi = m_oItems.GetAt(i);
if (fi != NULL) {
if (i > m_nSelectStart)
links += _T("\n");
links += fi->Link;
}
}
if (!links.IsEmpty())
CopyTextToClipboard(GetSafeHwnd(), links);
DeselectAllItems();
}
}
void CFeedView::OnSendByEmail() {
LOG0(3, "CFeedView::OnSendByEmail()");
if (m_nSelectFirst != -1) {
CString links;
for (int i = m_nSelectStart; i <= m_nSelectEnd; i++) {
CFeedItem *fi = m_oItems.GetAt(i);
if (fi != NULL) {
if (i > m_nSelectStart)
links += _T("\n");
links += fi->Link;
}
}
if (!links.IsEmpty())
SendByEmail(links);
DeselectAllItems();
}
}
// Sort ////
int CompareFeedItemDate(CFeedItem *fi1, CFeedItem *fi2) {
FILETIME ft1, ft2;
SystemTimeToLinearDate(&fi1->Date, &ft1);
SystemTimeToLinearDate(&fi2->Date, &ft2);
return CompareFileTime(&ft1, &ft2);
}
int CompareFeedItemFlag(CFeedItem *fi1, CFeedItem *fi2) {
return ((int) fi1->GetReadState() - (int) fi2->GetReadState());
}
int CompareFlagsAsc(const void *arg1, const void *arg2) {
CFeedItem *fi1 = (*(CFeedItem **) arg1);
CFeedItem *fi2 = (*(CFeedItem **) arg2);
return CompareFeedItemFlag(fi1, fi2);
}
int CompareFlagsDesc(const void *arg1, const void *arg2) {
CFeedItem *fi1 = (*(CFeedItem **) arg1);
CFeedItem *fi2 = (*(CFeedItem **) arg2);
return CompareFeedItemFlag(fi2, fi1);
}
int CompareDateAsc(const void *arg1, const void *arg2) {
CFeedItem *fi1 = (*(CFeedItem **) arg1);
CFeedItem *fi2 = (*(CFeedItem **) arg2);
return CompareFeedItemDate(fi1, fi2);
}
int CompareDateDesc(const void *arg1, const void *arg2) {
CFeedItem *fi1 = (*(CFeedItem **) arg1);
CFeedItem *fi2 = (*(CFeedItem **) arg2);
return CompareFeedItemDate(fi2, fi1);
}
int CompareVFolder(const void *arg1, const void *arg2) {
CFeedItem *fi1 = (*(CFeedItem **) arg1);
CFeedItem *fi2 = (*(CFeedItem **) arg2);
if (fi1->SiteItem == fi2->SiteItem) {
switch (fi1->SiteItem->Sort.Item) {
case CSortInfo::Date:
if (fi1->SiteItem->Sort.Type == CSortInfo::Ascending) return CompareFeedItemDate(fi1, fi2);
else return CompareFeedItemDate(fi2, fi1);
case CSortInfo::Read:
if (fi1->SiteItem->Sort.Type == CSortInfo::Ascending) return CompareFeedItemFlag(fi1, fi2);
else return CompareFeedItemFlag(fi2, fi1);
}
}
else {
return fi1->SiteItem - fi2->SiteItem;
}
return CompareFeedItemDate(fi2, fi1);
}
void CFeedView::Sort(int (__cdecl *compare)(const void *elem1, const void *elem2)) {
int count = GetItemCount();
int i;
CFeedItem **items = new CFeedItem *[count];
for (i = 0; i < count; i++)
items[i] = m_oItems[i];
qsort((void *) items, count, sizeof(CFeedItem *), compare);
for (i = 0; i < count; i++)
m_oItems.SetAt(i, items[i]);
// UpdateItemHeights();
delete [] items;
}
void CFeedView::SortItems() {
LOG0(3, "CFeedView::SortItems()");
if (SiteItem == NULL)
return; // no sorting if we dont know how to sort
if (SiteItem->Type == CSiteItem::VFolder && Config.GroupByFeed) {
Sort(CompareVFolder);
}
else {
switch (SiteItem->Sort.Item) {
case CSortInfo::Date:
if (SiteItem->Sort.Type == CSortInfo::Ascending) Sort(CompareDateAsc);
else Sort(CompareDateDesc);
break;
case CSortInfo::Read:
if (SiteItem->Sort.Type == CSortInfo::Ascending) Sort(CompareFlagsAsc);
else Sort(CompareFlagsDesc);
break;
}
}
UpdateItemHeights();
}
void CFeedView::OnSortAscending() {
LOG0(3, "CFeedView::SortAscending()");
if (SiteItem == NULL)
return;
if (SiteItem->Sort.Type != CSortInfo::Ascending) {
SiteItem->Sort.Type = CSortInfo::Ascending;
DeselectAllItems();
SortItems();
}
}
void CFeedView::OnSortDescending() {
LOG0(3, "CFeedView::SortDescending()");
if (SiteItem == NULL)
return;
if (SiteItem->Sort.Type != CSortInfo::Descending) {
SiteItem->Sort.Type = CSortInfo::Descending;
DeselectAllItems();
SortItems();
}
}
void CFeedView::InsertItems(CSiteItem *si) {
SetRedraw(FALSE);
DeleteAllItems();
SiteItem = si;
CFeed *feed = si->Feed;
if (feed != NULL) {
feed->Lock();
if (si->Type == CSiteItem::Site) {
for (int i = 0, j = 0; i < feed->GetItemCount(); i++) {
CFeedItem *item = feed->GetItem(i);
if (!Config.HideReadItems || !item->IsRead())
if (InsertItem(j, item))
j++;
}
}
else if (si->Type == CSiteItem::VFolder) {
for (int i = 0, j = 0; i < feed->GetItemCount(); i++) {
CFeedItem *item = feed->GetItem(i);
if ((item->GetFlags() & si->FlagMask) != 0)
if (InsertItem(j, item))
j++;
}
}
feed->Unlock();
}
SortItems();
UpdateScrollBars();
SetRedraw(TRUE);
Invalidate();
}
void CFeedView::OnViewHideReadItems() {
Config.HideReadItems = !Config.HideReadItems;
Config.SaveUI();
InsertItems(SiteItem);
UpdateScrollBars();
UpdateItemHeights();
}
void CFeedView::OnUpdateViewHideReadItems(CCmdUI *pCmdUI) {
pCmdUI->SetCheck(Config.HideReadItems);
}
int CFeedView::CalcItemHeight(int idx) {
if (m_bWrapTitles) {
CDC *pDC = GetDC();
CRect rc(0, 0, m_nClientWidth, m_nClientHeight);
rc.DeflateRect(SCALEX(LEFT_SKIP), SCALEY(PADDING_TOP), SCALEX(PADDING_RIGHT), SCALEY(PADDING_BOTTOM));
int wd = rc.Width();
CString strTitle = m_oItems[idx]->Title;
ReplaceHTMLEntities(strTitle);
CFont *pOldFont = pDC->SelectObject(&m_fntBold);
pDC->DrawText(strTitle, &rc, DT_LEFT | DT_TOP | DT_NOPREFIX | DT_CALCRECT | DT_WORDBREAK);
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);
return rc.Height() + SCALEY(DATE_HEIGHT);
}
else
return SCALEY(Appearance.FeedViewFontCfg.Size + ITEM_MARGIN);
}
void CFeedView::UpdateItemHeights() {
CRect rc;
GetClientRect(rc);
m_nClientWidth = rc.Width();
m_nTotalHeight = 0;
bool refresh = false;
for (int i = 0; i < m_oItems.GetSize(); i++) {
m_nTotalHeight += CalcItemHeight(i);
if (m_nTotalHeight > m_nClientHeight) {
m_nClientWidth -= ::GetSystemMetrics(SM_CXVSCROLL);
refresh = true;
break;
}
m_oItemHeight[i] = m_nTotalHeight;
}
if (refresh) {
m_nTotalHeight = 0;
for (int i = 0; i < m_oItems.GetSize(); i++) {
m_nTotalHeight += CalcItemHeight(i);
m_oItemHeight[i] = m_nTotalHeight;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -