📄 searchpage.cpp
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.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.
*/
//---------------------------------------------------------------------------
#include <vcl.h>
#include <KCeasy.h>
#pragma hdrstop
#include "SearchPage.h"
#include "MagnetDialog.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "VirtualTrees"
#pragma link "VirtualTrees"
#pragma resource "*.dfm"
TSearchForm *SearchForm;
//---------------------------------------------------------------------------
// tokens we replace with space in search queries. note the lack of the
// apostrophe, we let the plugin handle that.
const char BAD_QUERY_TOKENS[] = " \t\r\n\"碻&,.;:?!*()[]/\\-_|";
// max number of items on search history
const int MAX_QUERY_HISTORY_SIZE = 100;
//---------------------------------------------------------------------------
__fastcall TSearchForm::TSearchForm(TComponent* Owner)
: TForm(Owner)
{
TranslateComponent(this);
NetworkTree->NodeDataSize = sizeof(TNetworkNodeData);
// The TStrings implementation of TComboBox seems to suffer from
// overflows if the length of an entry exceeds 1065 bytes. TStringList
// appears to work fine in this regard so we use it to parse the config
// data and then filter it before passing it to TComboBox.
QueryCombo->Items->BeginUpdate();
QueryCombo->Clear();
TStrings* HistoryStrings = new TStringList();
HistoryStrings->CommaText = Config->GetValue("search/history").c_str();
for(int i = 0; i < HistoryStrings->Count; i++) {
if(HistoryStrings->Strings[i].Length() < 256)
QueryCombo->Items->Add(HistoryStrings->Strings[i]);
}
QueryCombo->Items->EndUpdate();
delete HistoryStrings;
ResultTabCtrl->Tabs->Clear();
ResultTabPanel->Visible = false;
}
void __fastcall TSearchForm::Release()
{
NetworkTree->Clear();
// save search history
if(Config->GetValueInt("search/erase_history_on_exit"))
Config->SetValue("search/history","");
else
Config->SetValue("search/history",SearchForm->QueryCombo->Items->CommaText.c_str());
// delete all result pages
for(int i=0; i < ResultTabCtrl->Tabs->Count; i++)
((TSearchResultForm*)ResultTabCtrl->Tabs->Objects[i])->Release();
ResultTabCtrl->Tabs->Clear();
TForm::Release();
}
//---------------------------------------------------------------------------
bool __fastcall TSearchForm::EngineCallback(TCallbackInfo* CbInfo)
{
switch(CbInfo->Code) {
case CbcStateChange:
if(Engine->IsOnline()) {
QueryCombo->Text = "";
StartSearchBtn->Enabled = true;
// populate realms
RealmRadioGroup->Items->BeginUpdate();
RealmRadioGroup->Items->Clear();
// TRANSLATOR: Search realm selection
RealmRadioGroup->Items->AddObject(_("Everything"), (TObject*)SRAny);
// TRANSLATOR: Search realm selection
RealmRadioGroup->Items->AddObject(_("Audio"), (TObject*)SRAudio);
// TRANSLATOR: Search realm selection
RealmRadioGroup->Items->AddObject(_("Video"), (TObject*)SRVideo);
// TRANSLATOR: Search realm selection
RealmRadioGroup->Items->AddObject(_("Images"), (TObject*)SRImage);
// TRANSLATOR: Search realm selection
RealmRadioGroup->Items->AddObject(_("Documents"), (TObject*)SRDocument);
if(Config->GetValueInt("search/enable_hash_realm")) {
// TRANSLATOR: Search realm selection
RealmRadioGroup->Items->AddObject(_("Files by Hash"), (TObject*)SRSource);
}
if(Config->GetValueInt("search/enable_torrent_realm")) {
// TRANSLATOR: Search realm selection
RealmRadioGroup->Items->AddObject(_("Torrents on OpenFT"), (TObject*)SRTorrent);
}
RealmRadioGroup->Items->EndUpdate();
// load realm
TSearchRealm Realm = TSearch::StringToRealm(Config->GetValue("search/realm").c_str());
int i = RealmRadioGroup->Items->IndexOfObject((TObject*)Realm);
if(i == -1)
RealmRadioGroup->ItemIndex = 0;
else
RealmRadioGroup->ItemIndex = i;
NetworkTree->Clear();
TVirtualNode* Node = NetworkTree->AddChild(NULL);
TNetworkNodeData* NodeData = (TNetworkNodeData*)NetworkTree->GetNodeData(Node);
NodeData->Network = NULL;
// TRANSLATOR: Network selection when searching.
NodeData->Name = _("All Networks");
NodeData->ImageIndex = MainForm->IconManager->GetNetworkIconIndex("All Networks");
NetworkTree->CheckType[Node] = ctCheckBox;
NetworkTree->CheckState[Node] = csUncheckedNormal;
// HACK HACK: Reset group height
NetworkGroup->Height = NetworkGroup->Constraints->MinHeight;
} else if(Engine->IsOffline()) {
// delete all result pages
for(int i=0; i < ResultTabCtrl->Tabs->Count; i++)
((TSearchResultForm*)ResultTabCtrl->Tabs->Objects[i])->Release();
ResultTabCtrl->Tabs->Clear();
// hide tab control
ResultTabCtrl->Visible = false;
}
break;
case CbcNetworksUpdate: {
// we really only need to do this once on the first event since networks never change
NetworkTree->BeginUpdate();
TNetworks* Nets = (TNetworks*)CbInfo->Data1;
Nets->Lock();
TNetworks::TNetworkIterator itr = Nets->GetBegin();
for(; itr != Nets->GetEnd(); ++itr) {
// add item if network not already in tree view
TVirtualNode* Node;
for(Node = NetworkTree->GetFirst(); Node; Node=NetworkTree->GetNextSibling(Node))
if(((TNetworkNodeData*)NetworkTree->GetNodeData(Node))->Network == *itr)
break;
if(!Node) {
Node = NetworkTree->AddChild(NULL);
TNetworkNodeData* NodeData = (TNetworkNodeData*)NetworkTree->GetNodeData(Node);
NodeData->Network = *itr;
NodeData->Name = NodeData->Network->GetName().c_str();
NodeData->ImageIndex = MainForm->IconManager->GetNetworkIconIndex(NodeData->Network->GetName());
NetworkTree->CheckType[Node] = ctCheckBox;
Node->CheckState = (Config->GetValueInt("search/all_networks") ||
Config->GetValue("search/networks").find(NodeData->Name.c_str()) != -1)
? csCheckedNormal : csUncheckedNormal;
// HACK HACK: increase group height
NetworkGroup->Height += NetworkTree->DefaultNodeHeight;
}
}
Nets->Release();
// if all networks are selected, select 'all networks' as well
bool AllChecked = true;
TVirtualNode* Node = NetworkTree->GetFirst();
if((Node = NetworkTree->GetNextSibling(Node))) {
for(; Node; Node=NetworkTree->GetNextSibling(Node))
if(Node->CheckState != csCheckedNormal)
AllChecked = false;
}
NetworkTree->GetFirst()->CheckState = AllChecked ? csCheckedNormal : csUncheckedNormal;
NetworkTree->EndUpdate();
break;
}
}
// call all result panes
for(int i=0; i < ResultTabCtrl->Tabs->Count; i++)
((TSearchResultForm*)ResultTabCtrl->Tabs->Objects[i])->EngineCallback(CbInfo);
return false;
}
void __fastcall TSearchForm::PageActivated()
{
if(LeftPanel->Visible)
QueryCombo->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TSearchForm::NetworkTreeGetText(TBaseVirtualTree *Sender,
PVirtualNode Node, TColumnIndex Column, TVSTTextType TextType,
WideString &CellText)
{
if(TextType != ttNormal || Column != -1)
return;
TNetworkNodeData* NodeData = (TNetworkNodeData*)Sender->GetNodeData(Node);
CellText = NodeData->Name;
// add number of users / connect status
if (NodeData->Network) {
WideString Status;
if (Config->GetValueInt("gui/show_network_stats"))
Status = FormatNumber(NodeData->Network->GetUsers(),NULL,-1).c_str();
else
// TRANSLATOR: Network status on search page
Status = NodeData->Network->IsConnected() ? _("Connected") : _("Connecting...");
CellText += WideString(" (") + Status + ")";
}
}
void __fastcall TSearchForm::NetworkTreeGetImageIndex(
TBaseVirtualTree *Sender, PVirtualNode Node, TVTImageKind Kind,
TColumnIndex Column, bool &Ghosted, int &ImageIndex)
{
if((Kind != ikNormal && Kind != ikSelected) || Column != -1)
return;
TNetworkNodeData* NodeData = (TNetworkNodeData*)Sender->GetNodeData(Node);
ImageIndex = NodeData->ImageIndex;
}
void __fastcall TSearchForm::NetworkTreeChecked(TBaseVirtualTree *Sender,
PVirtualNode Node)
{
NetworkTree->BeginUpdate();
string Networks;
if(Node == NetworkTree->GetFirst()) {
if(Node->CheckState == csCheckedNormal) {
// save selected networks and check all nodes
for(Node = NetworkTree->GetNextSibling(Node); Node; Node=NetworkTree->GetNextSibling(Node)) {
if(Node->CheckState == csCheckedNormal)
Networks += ((TNetworkNodeData*)NetworkTree->GetNodeData(Node))->Network->GetName() + ",";
Node->CheckState = csCheckedNormal;
}
Config->SetValueInt("search/all_networks", 1);
Config->SetValue("search/networks",Networks);
} else {
// restore networks
Config->SetValueInt("search/all_networks", 0);
Networks = Config->GetValue("search/networks");
for(Node = NetworkTree->GetNextSibling(Node); Node; Node=NetworkTree->GetNextSibling(Node)) {
Node->CheckState = Networks.find(((TNetworkNodeData*)NetworkTree->GetNodeData(Node))->Name.c_str()) != -1
? csCheckedNormal : csUncheckedNormal;
}
}
} else {
// if all networks are selected, select 'all networks' as well otherwise don't
bool AllChecked = true;
if((Node = NetworkTree->GetNextSibling(NetworkTree->GetFirst()))) {
for(; Node; Node=NetworkTree->GetNextSibling(Node))
if(Node->CheckState != csCheckedNormal)
AllChecked = false;
}
NetworkTree->GetFirst()->CheckState = AllChecked ? csCheckedNormal : csUncheckedNormal;
Config->SetValueInt("search/all_networks", AllChecked);
// save selected networks
for(Node = NetworkTree->GetNextSibling(NetworkTree->GetFirst()); Node; Node=NetworkTree->GetNextSibling(Node)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -