📄 searchfrm.cpp
字号:
/*
* 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.
*/
#include "stdafx.h"
#include "../client/DCPlusPlus.h"
#include "Resource.h"
#include "SearchFrm.h"
#include "LineDlg.h"
#include "../client/QueueManager.h"
#include "../client/StringTokenizer.h"
#include "../client/ClientManager.h"
TStringList SearchFrame::lastSearches;
int SearchFrame::columnIndexes[] = { COLUMN_FILENAME, COLUMN_NICK, COLUMN_TYPE, COLUMN_SIZE,
COLUMN_PATH, COLUMN_SLOTS, COLUMN_CONNECTION, COLUMN_HUB, COLUMN_EXACT_SIZE, COLUMN_IP, COLUMN_TTH, COLUMN_CID };
int SearchFrame::columnSizes[] = { 200, 100, 50, 80, 100, 40, 70, 150, 80, 100, 125, 125 };
static ResourceManager::Strings columnNames[] = { ResourceManager::FILE, ResourceManager::USER, ResourceManager::TYPE, ResourceManager::SIZE,
ResourceManager::PATH, ResourceManager::SLOTS, ResourceManager::CONNECTION,
ResourceManager::HUB, ResourceManager::EXACT_SIZE, ResourceManager::IP_BARE, ResourceManager::TTH_ROOT, ResourceManager::CID };
SearchFrame::FrameMap SearchFrame::frames;
void SearchFrame::openWindow(const tstring& str /* = Util::emptyString */, LONGLONG size /* = 0 */, SearchManager::SizeModes mode /* = SearchManager::SIZE_ATLEAST */, SearchManager::TypeModes type /* = SearchManager::TYPE_ANY ( 0 ) */) {
SearchFrame* pChild = new SearchFrame();
pChild->setInitial(str, size, mode, type);
pChild->CreateEx(WinUtil::mdiClient);
frames.insert( FramePair(pChild->m_hWnd, pChild) );
}
void SearchFrame::closeAll() {
for(FrameIter i = frames.begin(); i != frames.end(); ++i)
::PostMessage(i->first, WM_CLOSE, 0, 0);
}
LRESULT SearchFrame::onCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
CreateSimpleStatusBar(ATL_IDS_IDLEMESSAGE, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP);
ctrlStatus.Attach(m_hWndStatusBar);
ctrlSearchBox.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_VSCROLL | CBS_DROPDOWN | CBS_AUTOHSCROLL, 0);
for(TStringIter i = lastSearches.begin(); i != lastSearches.end(); ++i) {
ctrlSearchBox.InsertString(0, i->c_str());
}
searchBoxContainer.SubclassWindow(ctrlSearchBox.m_hWnd);
ctrlSearchBox.SetExtendedUI();
ctrlPurge.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_PURGE);
ctrlPurge.SetWindowText(CTSTRING(PURGE));
ctrlPurge.SetFont(WinUtil::systemFont);
purgeContainer.SubclassWindow(ctrlPurge.m_hWnd);
ctrlMode.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_HSCROLL | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_CLIENTEDGE);
modeContainer.SubclassWindow(ctrlMode.m_hWnd);
ctrlSize.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
ES_AUTOHSCROLL | ES_NUMBER, WS_EX_CLIENTEDGE);
sizeContainer.SubclassWindow(ctrlSize.m_hWnd);
ctrlSizeMode.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_HSCROLL | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_CLIENTEDGE);
sizeModeContainer.SubclassWindow(ctrlSizeMode.m_hWnd);
ctrlFiletype.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_HSCROLL | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_CLIENTEDGE);
fileTypeContainer.SubclassWindow(ctrlFiletype.m_hWnd);
ctrlResults.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_HSCROLL | WS_VSCROLL | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS, WS_EX_CLIENTEDGE, IDC_RESULTS);
ctrlResults.SetExtendedListViewStyle(LVS_EX_LABELTIP | LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT);
ctrlResults.SetImageList(WinUtil::fileImages, LVSIL_SMALL);
resultsContainer.SubclassWindow(ctrlResults.m_hWnd);
ctrlHubs.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_HSCROLL | WS_VSCROLL | LVS_REPORT | LVS_NOCOLUMNHEADER, WS_EX_CLIENTEDGE, IDC_HUB);
ctrlHubs.SetExtendedListViewStyle(LVS_EX_LABELTIP | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
hubsContainer.SubclassWindow(ctrlHubs.m_hWnd);
searchLabel.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
searchLabel.SetFont(WinUtil::systemFont, FALSE);
searchLabel.SetWindowText(CTSTRING(SEARCH_FOR));
sizeLabel.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
sizeLabel.SetFont(WinUtil::systemFont, FALSE);
sizeLabel.SetWindowText(CTSTRING(SIZE));
typeLabel.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
typeLabel.SetFont(WinUtil::systemFont, FALSE);
typeLabel.SetWindowText(CTSTRING(FILE_TYPE));
optionLabel.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
optionLabel.SetFont(WinUtil::systemFont, FALSE);
optionLabel.SetWindowText(CTSTRING(SEARCH_OPTIONS));
hubsLabel.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
hubsLabel.SetFont(WinUtil::systemFont, FALSE);
hubsLabel.SetWindowText(CTSTRING(HUBS));
ctrlSlots.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, IDC_FREESLOTS);
ctrlSlots.SetButtonStyle(BS_AUTOCHECKBOX, FALSE);
ctrlSlots.SetFont(WinUtil::systemFont, FALSE);
ctrlSlots.SetWindowText(CTSTRING(ONLY_FREE_SLOTS));
ctrlSlots.SetCheck(onlyFree);
slotsContainer.SubclassWindow(ctrlSlots.m_hWnd);
ctrlTTH.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, IDC_ONLYTTH);
ctrlTTH.SetButtonStyle(BS_AUTOCHECKBOX, FALSE);
ctrlTTH.SetFont(WinUtil::systemFont, FALSE);
ctrlTTH.SetWindowText(CTSTRING(ONLY_TTH));
ctrlTTH.SetCheck(onlyTTH);
tthContainer.SubclassWindow(ctrlTTH.m_hWnd);
ctrlShowUI.Create(ctrlStatus.m_hWnd, rcDefault, _T("+/-"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
ctrlShowUI.SetButtonStyle(BS_AUTOCHECKBOX, false);
ctrlShowUI.SetCheck(1);
showUIContainer.SubclassWindow(ctrlShowUI.m_hWnd);
ctrlDoSearch.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_SEARCH);
ctrlDoSearch.SetWindowText(CTSTRING(SEARCH));
ctrlDoSearch.SetFont(WinUtil::systemFont);
doSearchContainer.SubclassWindow(ctrlDoSearch.m_hWnd);
ctrlSearchBox.SetFont(WinUtil::systemFont, FALSE);
ctrlSize.SetFont(WinUtil::systemFont, FALSE);
ctrlMode.SetFont(WinUtil::systemFont, FALSE);
ctrlSizeMode.SetFont(WinUtil::systemFont, FALSE);
ctrlFiletype.SetFont(WinUtil::systemFont, FALSE);
ctrlMode.AddString(CTSTRING(NORMAL));
ctrlMode.AddString(CTSTRING(AT_LEAST));
ctrlMode.AddString(CTSTRING(AT_MOST));
ctrlMode.SetCurSel(1);
ctrlSizeMode.AddString(CTSTRING(B));
ctrlSizeMode.AddString(CTSTRING(KiB));
ctrlSizeMode.AddString(CTSTRING(MiB));
ctrlSizeMode.AddString(CTSTRING(GiB));
if(initialSize == 0)
ctrlSizeMode.SetCurSel(2);
else
ctrlSizeMode.SetCurSel(0);
ctrlFiletype.AddString(CTSTRING(ANY));
ctrlFiletype.AddString(CTSTRING(AUDIO));
ctrlFiletype.AddString(CTSTRING(COMPRESSED));
ctrlFiletype.AddString(CTSTRING(DOCUMENT));
ctrlFiletype.AddString(CTSTRING(EXECUTABLE));
ctrlFiletype.AddString(CTSTRING(PICTURE));
ctrlFiletype.AddString(CTSTRING(VIDEO));
ctrlFiletype.AddString(CTSTRING(DIRECTORY));
ctrlFiletype.AddString(_T("TTH"));
ctrlFiletype.SetCurSel(SETTING(LAST_SEARCH_TYPE));
// Create listview columns
WinUtil::splitTokens(columnIndexes, SETTING(SEARCHFRAME_ORDER), COLUMN_LAST);
WinUtil::splitTokens(columnSizes, SETTING(SEARCHFRAME_WIDTHS), COLUMN_LAST);
for(int j=0; j<COLUMN_LAST; j++) {
int fmt = (j == COLUMN_SIZE || j == COLUMN_EXACT_SIZE) ? LVCFMT_RIGHT : LVCFMT_LEFT;
ctrlResults.InsertColumn(j, CTSTRING_I(columnNames[j]), fmt, columnSizes[j], j);
}
ctrlResults.SetColumnOrderArray(COLUMN_LAST, columnIndexes);
ctrlResults.SetBkColor(WinUtil::bgColor);
ctrlResults.SetTextBkColor(WinUtil::bgColor);
ctrlResults.SetTextColor(WinUtil::textColor);
ctrlResults.SetFont(WinUtil::systemFont, FALSE); // use Util::font instead to obey Appearace settings
ctrlHubs.InsertColumn(0, _T("Dummy"), LVCFMT_LEFT, LVSCW_AUTOSIZE, 0);
ctrlHubs.SetBkColor(WinUtil::bgColor);
ctrlHubs.SetTextBkColor(WinUtil::bgColor);
ctrlHubs.SetTextColor(WinUtil::textColor);
ctrlHubs.SetFont(WinUtil::systemFont, FALSE); // use Util::font instead to obey Appearace settings
initHubs();
targetDirMenu.CreatePopupMenu();
targetMenu.CreatePopupMenu();
resultsMenu.CreatePopupMenu();
resultsMenu.AppendMenu(MF_STRING, IDC_DOWNLOAD, CTSTRING(DOWNLOAD));
resultsMenu.AppendMenu(MF_POPUP, (UINT_PTR)(HMENU)targetMenu, CTSTRING(DOWNLOAD_TO));
resultsMenu.AppendMenu(MF_STRING, IDC_DOWNLOADDIR, CTSTRING(DOWNLOAD_WHOLE_DIR));
resultsMenu.AppendMenu(MF_POPUP, (UINT_PTR)(HMENU)targetDirMenu, CTSTRING(DOWNLOAD_WHOLE_DIR_TO));
resultsMenu.AppendMenu(MF_STRING, IDC_VIEW_AS_TEXT, CTSTRING(VIEW_AS_TEXT));
resultsMenu.AppendMenu(MF_SEPARATOR);
resultsMenu.AppendMenu(MF_STRING, IDC_SEARCH_ALTERNATES, CTSTRING(SEARCH_FOR_ALTERNATES));
resultsMenu.AppendMenu(MF_STRING, IDC_BITZI_LOOKUP, CTSTRING(LOOKUP_AT_BITZI));
resultsMenu.AppendMenu(MF_STRING, IDC_COPY_MAGNET, CTSTRING(COPY_MAGNET));
resultsMenu.AppendMenu(MF_SEPARATOR);
appendUserItems(resultsMenu);
resultsMenu.AppendMenu(MF_SEPARATOR);
resultsMenu.AppendMenu(MF_STRING, IDC_REMOVE, CTSTRING(REMOVE));
resultsMenu.SetMenuDefaultItem(IDC_DOWNLOAD);
UpdateLayout();
if(!initialString.empty()) {
lastSearches.push_back(initialString);
ctrlSearchBox.InsertString(0, initialString.c_str());
ctrlSearchBox.SetCurSel(0);
ctrlMode.SetCurSel(initialMode);
ctrlSize.SetWindowText(Text::toT(Util::toString(initialSize)).c_str());
ctrlFiletype.SetCurSel(initialType);
onEnter();
} else {
SetWindowText(CTSTRING(SEARCH));
}
bHandled = FALSE;
return 1;
}
void SearchFrame::onEnter() {
StringList clients;
// Change Default Settings If Changed
if (onlyTTH != BOOLSETTING(SEARCH_ONLY_TTH))
SettingsManager::getInstance()->set(SettingsManager::SEARCH_ONLY_TTH, onlyTTH);
if (onlyFree != BOOLSETTING(SEARCH_ONLY_FREE_SLOTS))
SettingsManager::getInstance()->set(SettingsManager::SEARCH_ONLY_FREE_SLOTS, onlyFree);
if (!initialType && ctrlFiletype.GetCurSel() != SETTING(LAST_SEARCH_TYPE))
SettingsManager::getInstance()->set(SettingsManager::LAST_SEARCH_TYPE, ctrlFiletype.GetCurSel());
if(!(ctrlSearch.GetWindowTextLength() > 0))
return;
int n = ctrlHubs.GetItemCount();
for(int i = 0; i < n; i++) {
if(ctrlHubs.GetCheckState(i)) {
clients.push_back(Text::fromT(ctrlHubs.getItemData(i)->url));
}
}
if(!clients.size())
return;
tstring s(ctrlSearch.GetWindowTextLength() + 1, _T('\0'));
ctrlSearch.GetWindowText(&s[0], s.size());
s.resize(s.size()-1);
tstring size(ctrlSize.GetWindowTextLength() + 1, _T('\0'));
ctrlSize.GetWindowText(&size[0], size.size());
size.resize(size.size()-1);
double lsize = Util::toDouble(Text::fromT(size));
switch(ctrlSizeMode.GetCurSel()) {
case 1:
lsize*=1024.0; break;
case 2:
lsize*=1024.0*1024.0; break;
case 3:
lsize*=1024.0*1024.0*1024.0; break;
}
int64_t llsize = (int64_t)lsize;
for(int i = 0; i != ctrlResults.GetItemCount(); i++) {
delete ctrlResults.getItemData(i);
}
ctrlResults.DeleteAllItems();
{
Lock l(cs);
search = StringTokenizer<tstring>(s, ' ').getTokens();
}
//strip out terms beginning with -
s.clear();
for (TStringList::const_iterator si = search.begin(); si != search.end(); ++si)
if ((*si)[0] != _T('-')) s += *si + _T(' '); //Shouldn't get 0-length tokens, so safely assume at least a first char.
s = s.substr(0, max(s.size(), static_cast<tstring::size_type>(1)) - 1);
SearchManager::SizeModes mode((SearchManager::SizeModes)ctrlMode.GetCurSel());
if(llsize == 0)
mode = SearchManager::SIZE_DONTCARE;
int ftype = ctrlFiletype.GetCurSel();
// Add new searches to the last-search dropdown list
if(find(lastSearches.begin(), lastSearches.end(), s) == lastSearches.end())
{
int i = max(SETTING(SEARCH_HISTORY)-1, 0);
if(ctrlSearchBox.GetCount() > i)
ctrlSearchBox.DeleteString(i);
ctrlSearchBox.InsertString(0, s.c_str());
while(lastSearches.size() > (TStringList::size_type)i) {
lastSearches.erase(lastSearches.begin());
}
lastSearches.push_back(s);
}
ctrlStatus.SetText(1, (TSTRING(SEARCHING_FOR) + s + _T("...")).c_str());
ctrlStatus.SetText(2, _T(""));
ctrlStatus.SetText(3, _T(""));
droppedResults = 0;
isHash = (ftype == SearchManager::TYPE_TTH);
SetWindowText((TSTRING(SEARCH) + _T(" - ") + s).c_str());
if(SearchManager::getInstance()->okToSearch()) {
SearchManager::getInstance()->search(clients, Text::fromT(s), llsize,
(SearchManager::TypeModes)ftype, mode, "manual");
if(BOOLSETTING(CLEAR_SEARCH)) // Only clear if the search was sent
ctrlSearch.SetWindowText(_T(""));
} else {
int32_t waitFor = SearchManager::getInstance()->timeToSearch();
AutoArray<TCHAR> buf(TSTRING(SEARCHING_WAIT).size() + 16);
_stprintf(buf, CTSTRING(SEARCHING_WAIT), waitFor);
ctrlStatus.SetText(1, buf);
ctrlStatus.SetText(2, _T(""));
ctrlStatus.SetText(3, _T(""));
SetWindowText((TSTRING(SEARCH) + _T(" - ") + tstring(buf)).c_str());
// Start the countdown timer
timerID = SetTimer(1, 1000);
}
}
void SearchFrame::on(SearchManagerListener::SR, SearchResult* aResult) throw() {
// Check that this is really a relevant search result...
{
Lock l(cs);
if(search.empty()) {
return;
}
if(isHash) {
if(aResult->getTTH() == NULL)
return;
if(Util::stricmp(Text::toT(aResult->getTTH()->toBase32()), search[0]) != 0)
return;
} else {
// match all here
for(TStringIter j = search.begin(); j != search.end(); ++j) {
if((*j->begin() != _T('-') && Util::findSubString(aResult->getUtf8() ? aResult->getFile() : Text::acpToUtf8(aResult->getFile()), Text::fromT(*j)) == -1) ||
(*j->begin() == _T('-') && j->size() != 1 && Util::findSubString(aResult->getUtf8() ? aResult->getFile() : Text::acpToUtf8(aResult->getFile()), Text::fromT(j->substr(1))) != -1)
)
{
droppedResults++;
PostMessage(WM_SPEAKER, FILTER_RESULT, NULL);
return;
}
}
}
}
// Reject results without free slots or tth if selected
// but always show directories
if( (onlyFree && aResult->getFreeSlots() < 1) ||
((onlyTTH && aResult->getTTH() == NULL) && (aResult->getType() != SearchResult::TYPE_DIRECTORY))
)
{
droppedResults++;
ctrlStatus.SetText(3, Text::toT(Util::toString(droppedResults) + ' ' + STRING(FILTERED)).c_str());
return;
}
SearchInfo* i = new SearchInfo(aResult);
PostMessage(WM_SPEAKER, ADD_RESULT, (LPARAM)i);
}
LRESULT SearchFrame::onTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
int32_t waitFor = SearchManager::getInstance()->timeToSearch();
if(waitFor > 0) {
AutoArray<TCHAR> buf(TSTRING(SEARCHING_WAIT).size() + 16);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -