/*
* Copyright (C) 2001-2006 Jacek Sieka, arnetheduck on gmail point 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#if !defined(DIRECTORY_LISTING_FRM_H)
#define DIRECTORY_LISTING_FRM_H
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include "../client/User.h"
#include "../client/FastAlloc.h"
#include "FlatTabCtrl.h"
#include "TypedListViewCtrl.h"
#include "WinUtil.h"
#include "UCHandler.h"
#include "QueueFrame.h"
#include "SearchFrm.h"
#include "../client/DirectoryListing.h"
#include "../client/StringSearch.h"
#include "../client/FavoriteManager.h"
#include "../client/ShareManager.h"
#define STATUS_MESSAGE_MAP 9
class DirectoryListingFrame : public MDITabChildWindowImpl<DirectoryListingFrame>,
public CSplitterImpl<DirectoryListingFrame>, public UCHandler<DirectoryListingFrame>, private SettingsManagerListener
{
public:
static void openWindow(const tstring& aFile, const User::Ptr& aUser);
typedef MDITabChildWindowImpl<DirectoryListingFrame> baseClass;
typedef UCHandler<DirectoryListingFrame> ucBase;
enum {
COLUMN_FILENAME,
COLUMN_TYPE,
COLUMN_SIZE,
COLUMN_EXACT_SIZE,
COLUMN_TTH,
COLUMN_LAST
};
DirectoryListingFrame(const tstring& aFile, const User::Ptr& aUser);
virtual ~DirectoryListingFrame() { delete dl; }
DECLARE_FRAME_WND_CLASS(_T("DirectoryListingFrame"), IDR_DIRECTORY)
BEGIN_MSG_MAP(DirectoryListingFrame)
NOTIFY_HANDLER(IDC_FILES, LVN_GETDISPINFO, ctrlList.onGetDispInfo)
NOTIFY_HANDLER(IDC_FILES, LVN_COLUMNCLICK, ctrlList.onColumnClick)
NOTIFY_HANDLER(IDC_FILES, LVN_GETINFOTIP, ctrlList.onInfoTip)
NOTIFY_HANDLER(IDC_FILES, LVN_KEYDOWN, onKeyDown)
NOTIFY_HANDLER(IDC_FILES, NM_DBLCLK, onDoubleClickFiles)
NOTIFY_HANDLER(IDC_FILES, LVN_ITEMCHANGED, onItemChanged)
NOTIFY_HANDLER(IDC_FILES, NM_CUSTOMDRAW, onCustomDraw)
NOTIFY_HANDLER(IDC_DIRECTORIES, TVN_KEYDOWN, onKeyDownDirs)
NOTIFY_HANDLER(IDC_DIRECTORIES, TVN_SELCHANGED, onSelChangedDirectories)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_CONTEXTMENU, onContextMenu)
MESSAGE_HANDLER(WM_CLOSE, onClose)
MESSAGE_HANDLER(WM_SETFOCUS, onSetFocus)
MESSAGE_HANDLER(FTM_CONTEXTMENU, onTabContextMenu)
COMMAND_ID_HANDLER(IDC_DOWNLOAD, onDownload)
COMMAND_ID_HANDLER(IDC_DOWNLOADDIR, onDownloadDir)
COMMAND_ID_HANDLER(IDC_DOWNLOADDIRTO, onDownloadDirTo)
COMMAND_ID_HANDLER(IDC_DOWNLOADTO, onDownloadTo)
COMMAND_ID_HANDLER(IDC_GO_TO_DIRECTORY, onGoToDirectory)
COMMAND_ID_HANDLER(IDC_VIEW_AS_TEXT, onViewAsText)
COMMAND_ID_HANDLER(IDC_ADD_TO_FAVORITES, onAddToFavorites)
COMMAND_ID_HANDLER(IDC_PRIVATEMESSAGE, onPM)
COMMAND_ID_HANDLER(IDC_CLOSE_WINDOW, onCloseWindow)
COMMAND_ID_HANDLER(IDC_SEARCH_ALTERNATES, onSearchAlternates)
COMMAND_ID_HANDLER(IDC_SEARCH_ALTERNATES_FILE, onSearchAlternatesFile)
COMMAND_RANGE_HANDLER(IDC_MULTI_COPY, IDC_MULTI_COPY + COLUMN_LAST + 1, onCopy)
COMMAND_RANGE_HANDLER(IDC_DOWNLOAD_TARGET, IDC_DOWNLOAD_TARGET + targets.size() + WinUtil::lastDirs.size(), onDownloadTarget)
COMMAND_RANGE_HANDLER(IDC_DOWNLOAD_TARGET_DIR, IDC_DOWNLOAD_TARGET_DIR + WinUtil::lastDirs.size(), onDownloadTargetDir)
COMMAND_RANGE_HANDLER(IDC_DOWNLOAD_FAVORITE_DIRS, IDC_DOWNLOAD_FAVORITE_DIRS + FavoriteManager::getInstance()->getFavoriteDirs().size(), onDownloadFavoriteDirs)
COMMAND_RANGE_HANDLER(IDC_DOWNLOAD_WHOLE_FAVORITE_DIRS, IDC_DOWNLOAD_WHOLE_FAVORITE_DIRS + FavoriteManager::getInstance()->getFavoriteDirs().size(), onDownloadWholeFavoriteDirs)
COMMAND_RANGE_HANDLER(IDC_PRIORITY_PAUSED, IDC_PRIORITY_HIGHEST, onDownloadWithPrio)
COMMAND_RANGE_HANDLER(IDC_PRIORITY_PAUSED+90, IDC_PRIORITY_HIGHEST+90, onDownloadDirWithPrio)
CHAIN_COMMANDS(ucBase)
CHAIN_MSG_MAP(baseClass)
CHAIN_MSG_MAP(CSplitterImpl<DirectoryListingFrame>)
ALT_MSG_MAP(STATUS_MESSAGE_MAP)
COMMAND_ID_HANDLER(IDC_FIND, onFind)
COMMAND_ID_HANDLER(IDC_NEXT, onNext)
COMMAND_ID_HANDLER(IDC_MATCH_QUEUE, onMatchQueue)
END_MSG_MAP()
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
LRESULT onDownload(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadWithPrio(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadDir(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadDirWithPrio(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadDirTo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadTo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onViewAsText(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onCopy(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onAddToFavorites(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onPM(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onGoToDirectory(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadTarget(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadTargetDir(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDoubleClickFiles(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
LRESULT onSelChangedDirectories(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
LRESULT onContextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled);
LRESULT onDownloadFavoriteDirs(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onDownloadWholeFavoriteDirs(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onSearchAlternates(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onSearchAlternatesFile(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
LRESULT onTabContextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/);
LRESULT onCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled);
void downloadList(const tstring& aTarget, bool view = false, QueueItem::Priority prio = QueueItem::DEFAULT);
void updateTree(DirectoryListing::Directory* tree, HTREEITEM treeItem);
void UpdateLayout(BOOL bResizeBars = TRUE);
void findFile(bool findNext);
void runUserCommand(UserCommand& uc);
LRESULT onItemChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) {
updateStatus();
return 0;
}
LRESULT onSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
ctrlList.SetFocus();
return 0;
}
void setWindowTitle() {
if(error.empty())
SetWindowText(Text::toT(dl->getUser()->getFullNick()).c_str());
else
SetWindowText(error.c_str());
}
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
return 1;
}
void clearList() {
int j = ctrlList.GetItemCount();
for(int i = 0; i < j; i++) {
delete (ItemInfo*)ctrlList.GetItemData(i);
}
ctrlList.DeleteAllItems();
}
LRESULT onFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
searching = true;
findFile(false);
searching = false;
updateStatus();
return 0;
}
LRESULT onNext(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
searching = true;
findFile(true);
searching = false;
updateStatus();
return 0;
}
LRESULT onMatchQueue(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT onKeyDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
LRESULT onKeyDownDirs(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) {
NMTVKEYDOWN* kd = (NMTVKEYDOWN*) pnmh;
if(kd->wVKey == VK_TAB) {
onTab();
}
return 0;
}
void onTab() {
HWND focus = ::GetFocus();
if(focus == ctrlTree.m_hWnd) {
ctrlList.SetFocus();
} else if(focus == ctrlList.m_hWnd) {
ctrlTree.SetFocus();
}
}
LRESULT onCloseWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
PostMessage(WM_CLOSE);
return 0;
}
static void closeAll();
private:
void changeDir(DirectoryListing::Directory* d, BOOL enableRedraw);
HTREEITEM findFile(const StringSearch& str, HTREEITEM root, int &foundFile, int &skipHits);
void updateStatus();
void GoToDirectory(HTREEITEM hItem, TStringList::iterator& iPath, const TStringList::iterator& iPathEnd);
class ItemInfo : public FastAlloc<ItemInfo> {
public:
enum ItemType {
FILE,
DIRECTORY
} type;
union {
DirectoryListing::File* file;
DirectoryListing::Directory* dir;
};
ItemInfo(DirectoryListing::File* f, bool utf8) : type(FILE), file(f) {
if(utf8) {
columns[COLUMN_FILENAME] = Text::toT(f->getName());
} else {
columns[COLUMN_FILENAME] = Text::acpToWide(f->getName());
}
columns[COLUMN_TYPE] = Util::getFileExt(columns[COLUMN_FILENAME]);
if(columns[COLUMN_TYPE].size() > 0 && columns[COLUMN_TYPE][0] == '.')
columns[COLUMN_TYPE].erase(0, 1);
columns[COLUMN_SIZE] = Text::toT(Util::formatBytes(f->getSize()));
columns[COLUMN_EXACT_SIZE] = Util::formatExactSize(f->getSize()); // McDC Extension
if(f->getTTH() != NULL)
columns[COLUMN_TTH] = Text::toT(f->getTTH()->toBase32());
}
ItemInfo(DirectoryListing::Directory* d, bool utf8) : type(DIRECTORY), dir(d) {
if(utf8) {
columns[COLUMN_FILENAME] = Text::toT(d->getName());
} else {
columns[COLUMN_FILENAME] = Text::toT(Text::acpToUtf8(d->getName()));
}
columns[COLUMN_SIZE] = Text::toT(Util::formatBytes(d->getTotalSize()));
columns[COLUMN_EXACT_SIZE] = Util::formatExactSize(d->getTotalSize()); // McDC Extension
}
const tstring& getText(int col) const {
dcassert(col >= 0 && col < COLUMN_LAST);
return columns[col];
}
struct TotalSize {
TotalSize() : total(0) { }
void operator()(ItemInfo* a) { total += a->type == DIRECTORY ? a->dir->getTotalSize() : a->file->getSize(); }
int64_t total;
};
static int compareItems(ItemInfo* a, ItemInfo* b, int col) {
if(a->type == DIRECTORY) {
if(b->type == DIRECTORY) {
switch(col) {
case COLUMN_SIZE: return compare(a->dir->getTotalSize(), b->dir->getTotalSize());
case COLUMN_EXACT_SIZE: return compare(a->dir->getTotalSize(), b->dir->getTotalSize());
default: return lstrcmpi(a->columns[col].c_str(), b->columns[col].c_str());
}
} else {
return -1;
}
} else if(b->type == DIRECTORY) {
return 1;
} else {
switch(col) {
case COLUMN_SIZE: return compare(a->file->getSize(), b->file->getSize());
case COLUMN_EXACT_SIZE: return compare(a->file->getSize(), b->file->getSize());
default: return lstrcmp(a->columns[col].c_str(), b->columns[col].c_str());
}
}
}
private:
tstring columns[COLUMN_LAST];
};
OMenu targetMenu;
OMenu targetDirMenu;
OMenu fileMenu;
OMenu directoryMenu;
OMenu priorityMenu;
OMenu priorityDirMenu;
OMenu copyMenu;
OMenu tabMenu;
CContainedWindow statusContainer;
StringList targets;
CTreeViewCtrl ctrlTree;
TypedListViewCtrl<ItemInfo, IDC_FILES> ctrlList;
CStatusBarCtrl ctrlStatus;
HTREEITEM treeRoot;
CButton ctrlFind, ctrlFindNext;
CButton ctrlMatchQueue;
/** Parameter map for user commands */
StringMap ucParams;
string findStr;
tstring error;
string size;
tstring start;
int skipHits;
size_t files;
bool updating;
bool searching;
bool closed;
int statusSizes[8];
DirectoryListing* dl;
static int columnIndexes[COLUMN_LAST];
static int columnSizes[COLUMN_LAST];
virtual void on(SettingsManagerListener::Save, SimpleXML* /*xml*/) throw();
typedef multimap< HWND , DirectoryListingFrame* > FrameMap;
typedef pair< HWND , DirectoryListingFrame* > FramePair;
typedef FrameMap::iterator FrameIter;
static FrameMap frames;
};
#endif // !defined(DIRECTORY_LISTING_FRM_H)
/**
* @file
* $Id: DirectoryListingFrm.h 109 2006-10-31 03:21:46Z crakter $
*/