summaryrefslogtreecommitdiff
path: root/src/modules/findadd/searchresults.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /src/modules/findadd/searchresults.cpp
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/findadd/searchresults.cpp')
-rw-r--r--src/modules/findadd/searchresults.cpp398
1 files changed, 398 insertions, 0 deletions
diff --git a/src/modules/findadd/searchresults.cpp b/src/modules/findadd/searchresults.cpp
new file mode 100644
index 0000000000..4c8b7cf46c
--- /dev/null
+++ b/src/modules/findadd/searchresults.cpp
@@ -0,0 +1,398 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include "findadd.h"
+
+enum {
+ COLUMNID_PROTO,
+ COLUMNID_HANDLE,
+ COLUMNID_NICK,
+ COLUMNID_FIRST,
+ COLUMNID_LAST,
+ COLUMNID_EMAIL,
+ NUM_COLUMNID
+};
+
+void SaveColumnSizes(HWND hwndResults)
+{
+ int columnOrder[NUM_COLUMNID];
+ int columnCount;
+ char szSetting[32];
+ int i;
+ struct FindAddDlgData *dat;
+
+ dat=(struct FindAddDlgData*)GetWindowLongPtr(GetParent(hwndResults),GWLP_USERDATA);
+ columnCount=Header_GetItemCount(ListView_GetHeader(hwndResults));
+ if (columnCount != NUM_COLUMNID) return;
+ ListView_GetColumnOrderArray(hwndResults,columnCount,columnOrder);
+ for(i=0; i < NUM_COLUMNID; i++) {
+ mir_snprintf(szSetting, SIZEOF(szSetting), "ColOrder%d", i);
+ DBWriteContactSettingByte(NULL,"FindAdd",szSetting,(BYTE)columnOrder[i]);
+ if(i>=columnCount) continue;
+ mir_snprintf(szSetting, SIZEOF(szSetting), "ColWidth%d", i);
+ DBWriteContactSettingWord(NULL,"FindAdd",szSetting,(WORD)ListView_GetColumnWidth(hwndResults,i));
+ }
+ DBWriteContactSettingByte(NULL,"FindAdd","SortColumn",(BYTE)dat->iLastColumnSortIndex);
+ DBWriteContactSettingByte(NULL,"FindAdd","SortAscending",(BYTE)dat->bSortAscending);
+}
+
+static const TCHAR *szColumnNames[] = { NULL, NULL, _T("Nick"), _T("First Name"), _T("Last Name"), _T("E-mail") };
+static int defaultColumnSizes[]={0,90,100,100,100,2000};
+void LoadColumnSizes(HWND hwndResults,const char *szProto)
+{
+ HDITEM hdi;
+ int columnOrder[NUM_COLUMNID];
+ int columnCount;
+ char szSetting[32];
+ int i;
+ FindAddDlgData *dat;
+ bool colOrdersValid;
+
+ defaultColumnSizes[COLUMNID_PROTO] = GetSystemMetrics(SM_CXSMICON) + 4;
+ dat = (FindAddDlgData*)GetWindowLongPtr(GetParent(hwndResults), GWLP_USERDATA);
+
+ columnCount = NUM_COLUMNID;
+ colOrdersValid = true;
+ for(i=0; i < NUM_COLUMNID; i++)
+ {
+ LVCOLUMN lvc;
+ if( i < columnCount )
+ {
+ int bNeedsFree = FALSE;
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+ if( szColumnNames[i] != NULL )
+ lvc.pszText = TranslateTS( szColumnNames[i] );
+ else if( i == COLUMNID_HANDLE )
+ {
+ if (szProto)
+ {
+ #if defined( _UNICODE )
+ bNeedsFree = TRUE;
+ lvc.pszText = mir_a2t((char*)CallProtoService(szProto,PS_GETCAPS,PFLAG_UNIQUEIDTEXT,0));
+ #else
+ lvc.pszText = (char*)CallProtoService(szProto,PS_GETCAPS,PFLAG_UNIQUEIDTEXT,0);
+ #endif
+ }
+ else
+ lvc.pszText = _T("ID");
+ }
+ else lvc.mask &= ~LVCF_TEXT;
+ mir_snprintf(szSetting, SIZEOF(szSetting), "ColWidth%d", i);
+ lvc.cx = DBGetContactSettingWord(NULL, "FindAdd", szSetting, defaultColumnSizes[i]);
+ ListView_InsertColumn(hwndResults, i, (LPARAM)&lvc);
+ #if defined( _UNICODE )
+ if (bNeedsFree)
+ mir_free(lvc.pszText);
+ #endif
+ }
+ mir_snprintf(szSetting, SIZEOF(szSetting), "ColOrder%d", i);
+ columnOrder[i] = DBGetContactSettingByte(NULL, "FindAdd", szSetting, -1);
+ if (columnOrder[i] == -1 || columnOrder[i] >= NUM_COLUMNID) colOrdersValid = false;
+ }
+
+ if (colOrdersValid)
+ ListView_SetColumnOrderArray(hwndResults, columnCount, columnOrder);
+
+ dat->iLastColumnSortIndex = DBGetContactSettingByte(NULL, "FindAdd", "SortColumn", COLUMNID_NICK);
+ if (dat->iLastColumnSortIndex >= columnCount) dat->iLastColumnSortIndex = COLUMNID_NICK;
+ dat->bSortAscending = DBGetContactSettingByte(NULL, "FindAdd", "SortAscending", TRUE);
+
+ hdi.mask = HDI_BITMAP | HDI_FORMAT;
+ hdi.fmt = HDF_LEFT | HDF_BITMAP | HDF_STRING | HDF_BITMAP_ON_RIGHT;
+ hdi.hbm = dat->bSortAscending ? dat->hBmpSortDown : dat->hBmpSortUp;
+ Header_SetItem(ListView_GetHeader(hwndResults), dat->iLastColumnSortIndex, &hdi);
+}
+
+static LPARAM ListView_GetItemLParam(HWND hwndList, int idx)
+{
+ LVITEM lv;
+ lv.iItem = idx;
+ lv.mask = LVIF_PARAM;
+ ListView_GetItem(hwndList,&lv);
+ return lv.lParam;
+}
+
+int CALLBACK SearchResultsCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ struct FindAddDlgData *dat=(struct FindAddDlgData*)GetWindowLongPtr((HWND) lParamSort, GWLP_USERDATA);
+ int sortMultiplier;
+ int sortCol;
+ struct ListSearchResult *lsr1, *lsr2;
+ HWND hList=GetDlgItem((HWND) lParamSort, IDC_RESULTS);
+
+ sortMultiplier=dat->bSortAscending?1:-1;
+ sortCol=dat->iLastColumnSortIndex;
+ if (!dat->bFlexSearchResult)
+ {
+ lsr1=(struct ListSearchResult*)ListView_GetItemLParam(hList, (int)lParam1);
+ lsr2=(struct ListSearchResult*)ListView_GetItemLParam(hList, (int)lParam2);
+
+ if ( lsr1 == NULL || lsr2 == NULL ) return 0;
+ switch(sortCol)
+ {
+ case COLUMNID_PROTO:
+ return lstrcmpA(lsr1->szProto, lsr2->szProto)*sortMultiplier;
+ case COLUMNID_HANDLE:
+ return lstrcmpi(lsr1->psr.id, lsr2->psr.id)*sortMultiplier;
+ case COLUMNID_NICK:
+ return lstrcmpi(lsr1->psr.nick, lsr2->psr.nick)*sortMultiplier;
+ case COLUMNID_FIRST:
+ return lstrcmpi(lsr1->psr.firstName, lsr2->psr.firstName)*sortMultiplier;
+ case COLUMNID_LAST:
+ return lstrcmpi(lsr1->psr.lastName, lsr2->psr.lastName)*sortMultiplier;
+ case COLUMNID_EMAIL:
+ return lstrcmpi(lsr1->psr.email, lsr2->psr.email)*sortMultiplier;
+ }
+ }
+ else
+ {
+ TCHAR szText1[100];
+ TCHAR szText2[100];
+ ListView_GetItemText(hList,(int)lParam1,sortCol,szText1,SIZEOF(szText1));
+ ListView_GetItemText(hList,(int)lParam2,sortCol,szText2,SIZEOF(szText2));
+ return _tcsicmp(szText1, szText2)*sortMultiplier;
+ }
+ return 0;
+}
+
+void FreeSearchResults(HWND hwndResults)
+{
+ LV_ITEM lvi;
+ struct ListSearchResult *lsr;
+ for(lvi.iItem=ListView_GetItemCount(hwndResults)-1;lvi.iItem>=0;lvi.iItem--) {
+ lvi.mask=LVIF_PARAM;
+ ListView_GetItem(hwndResults,&lvi);
+ lsr=(struct ListSearchResult*)lvi.lParam;
+ if(lsr==NULL) continue;
+ mir_free(lsr->psr.id);
+ mir_free(lsr->psr.email);
+ mir_free(lsr->psr.nick);
+ mir_free(lsr->psr.firstName);
+ mir_free(lsr->psr.lastName);
+ mir_free(lsr);
+ }
+ ListView_DeleteAllItems(hwndResults);
+ EnableResultButtons(GetParent(hwndResults),0);
+}
+
+// on its own thread
+static void BeginSearchFailed(void * arg)
+{
+ TCHAR buf[128];
+ if ( arg != NULL ) {
+ const TCHAR* protoName = (TCHAR*)arg;
+ mir_sntprintf(buf,SIZEOF(buf),
+ TranslateT("Could not start a search on '%s', there was a problem - is %s connected?"),
+ protoName,protoName);
+ mir_free((char*)arg);
+ }
+ else lstrcpyn(buf,TranslateT("Could not search on any of the protocols, are you online?"),SIZEOF(buf));
+ MessageBox(0,buf,TranslateT("Problem with search"),MB_OK | MB_ICONERROR);
+}
+
+int BeginSearch(HWND,struct FindAddDlgData *dat,const char *szProto,const char *szSearchService,DWORD requiredCapability,void *pvSearchParams)
+{
+ int i;
+ if ( szProto == NULL ) {
+ int failures = 0;
+ dat->searchCount = 0;
+ dat->search = (struct ProtoSearchInfo*)mir_calloc(sizeof(struct ProtoSearchInfo) * accounts.getCount());
+ for( i=0; i < accounts.getCount();i++) {
+ PROTOACCOUNT* pa = accounts[i];
+ if (!Proto_IsAccountEnabled(pa)) continue;
+ DWORD caps=(DWORD)CallProtoService(pa->szModuleName,PS_GETCAPS,PFLAGNUM_1,0);
+ if(!(caps&requiredCapability)) continue;
+ dat->search[dat->searchCount].hProcess = (HANDLE)CallProtoService(pa->szModuleName,szSearchService,0,(LPARAM)pvSearchParams);
+ dat->search[dat->searchCount].szProto = pa->szModuleName;
+ if ( dat->search[dat->searchCount].hProcess == NULL ) failures++;
+ else dat->searchCount++;
+ }
+ if(failures) {
+ //infuriatingly vague error message. fixme.
+ if(dat->searchCount==0) {
+ forkthread(BeginSearchFailed,0,NULL);
+ mir_free(dat->search);
+ dat->search=NULL;
+ return 1;
+ } }
+ }
+ else {
+ dat->search=(struct ProtoSearchInfo*)mir_alloc(sizeof(struct ProtoSearchInfo));
+ dat->searchCount=1;
+ dat->search[0].hProcess=(HANDLE)CallProtoService(szProto,szSearchService,0,(LPARAM)pvSearchParams);
+ dat->search[0].szProto=szProto;
+ if(dat->search[0].hProcess==NULL) {
+ //infuriatingly vague error message. fixme.
+ PROTOACCOUNT* pa = Proto_GetAccount(szProto);
+ forkthread(BeginSearchFailed, 0, mir_tstrdup(pa->tszAccountName));
+ mir_free(dat->search);
+ dat->search=NULL;
+ dat->searchCount=0;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// !!!!!!!! this code is dangerous like a hell
+void SetStatusBarSearchInfo(HWND hwndStatus,struct FindAddDlgData *dat)
+{
+ TCHAR str[256];
+
+ if (dat->searchCount != 0 ) {
+ int i;
+
+ lstrcpy( str, TranslateT("Searching"));
+ for( i=0; i < dat->searchCount; i++ ) {
+ PROTOACCOUNT* pa = Proto_GetAccount( dat->search[i].szProto );
+ if ( !pa )
+ continue;
+
+ lstrcat(str, i ? _T(",") : _T( " " ));
+ lstrcat(str, pa->tszAccountName );
+ } }
+ else lstrcpy(str, TranslateT("Idle"));
+
+ SendMessage( hwndStatus, SB_SETTEXT, 0, (LPARAM)str );
+}
+
+struct ProtoResultsSummary {
+ const char *szProto;
+ int count;
+};
+void SetStatusBarResultInfo(HWND hwndDlg)
+{
+ HWND hwndStatus=GetDlgItem(hwndDlg,IDC_STATUSBAR);
+ HWND hwndResults=GetDlgItem(hwndDlg,IDC_RESULTS);
+ LV_ITEM lvi;
+ struct ListSearchResult *lsr;
+ struct ProtoResultsSummary *subtotal=NULL;
+ int subtotalCount=0;
+ int i,total;
+ TCHAR str[256];
+
+ total=ListView_GetItemCount(hwndResults);
+ for(lvi.iItem=total-1;lvi.iItem>=0;lvi.iItem--) {
+ lvi.mask=LVIF_PARAM;
+ ListView_GetItem(hwndResults,&lvi);
+ lsr=(struct ListSearchResult*)lvi.lParam;
+ if(lsr==NULL) continue;
+ for(i=0;i<subtotalCount;i++) {
+ if(subtotal[i].szProto==lsr->szProto) {
+ subtotal[i].count++;
+ break;
+ }
+ }
+ if(i==subtotalCount) {
+ subtotal=(struct ProtoResultsSummary*)mir_realloc(subtotal,sizeof(struct ProtoResultsSummary)*(subtotalCount+1));
+ subtotal[subtotalCount].szProto=lsr->szProto;
+ subtotal[subtotalCount++].count=1;
+ }
+ }
+ if ( total != 0 ) {
+ TCHAR substr[64];
+ PROTOACCOUNT* pa = Proto_GetAccount( subtotal[0].szProto );
+ if ( pa == NULL )
+ return;
+
+ if ( subtotalCount == 1 ) {
+ if(total==1) mir_sntprintf( str, SIZEOF(str), TranslateT("1 %s user found"), pa->tszAccountName );
+ else mir_sntprintf( str, SIZEOF(str), TranslateT("%d %s users found"), total, pa->tszAccountName );
+ }
+ else {
+ mir_sntprintf( str, SIZEOF(str), TranslateT("%d users found ("),total);
+ for( i=0; i < subtotalCount; i++ ) {
+ if ( i ) {
+ if (( pa = Proto_GetAccount( subtotal[i].szProto )) == NULL )
+ return;
+ lstrcat( str, _T(", "));
+ }
+ mir_sntprintf( substr, SIZEOF(substr), _T("%d %s"), subtotal[i].count, pa->tszAccountName );
+ lstrcat( str, substr );
+ }
+ lstrcat( str, _T(")"));
+ }
+ mir_free(subtotal);
+ }
+ else lstrcpy(str, TranslateT("No users found"));
+ SendMessage(hwndStatus, SB_SETTEXT, 2, (LPARAM)str );
+}
+
+void CreateResultsColumns(HWND hwndResults,struct FindAddDlgData *dat,char *szProto)
+{
+ SaveColumnSizes(hwndResults);
+ while(ListView_DeleteColumn(hwndResults,0));
+ ListView_SetImageList(hwndResults,dat->himlComboIcons,LVSIL_SMALL);
+ LoadColumnSizes(hwndResults,szProto);
+}
+
+void ShowMoreOptionsMenu(HWND hwndDlg,int x,int y)
+{
+ struct FindAddDlgData *dat;
+ HMENU hPopupMenu,hMenu;
+ int commandId;
+ struct ListSearchResult *lsr;
+
+ dat=(struct FindAddDlgData*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+
+ { LVITEM lvi;
+ if(ListView_GetSelectedCount(GetDlgItem(hwndDlg,IDC_RESULTS))!=1) return;
+ lvi.mask=LVIF_PARAM;
+ lvi.iItem=ListView_GetNextItem(GetDlgItem(hwndDlg,IDC_RESULTS),-1,LVNI_ALL|LVNI_SELECTED);
+ ListView_GetItem(GetDlgItem(hwndDlg,IDC_RESULTS),&lvi);
+ lsr=(struct ListSearchResult*)lvi.lParam;
+ }
+
+ hMenu=LoadMenu(hMirandaInst,MAKEINTRESOURCE(IDR_CONTEXT));
+ hPopupMenu=GetSubMenu(hMenu,4);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)hPopupMenu,0);
+ commandId=TrackPopupMenu(hPopupMenu,TPM_RIGHTBUTTON|TPM_RETURNCMD,x,y,0,hwndDlg,NULL);
+ switch(commandId) {
+ case IDC_ADD:
+ { ADDCONTACTSTRUCT acs;
+
+ acs.handle=NULL;
+ acs.handleType=HANDLE_SEARCHRESULT;
+ acs.szProto=lsr->szProto;
+ acs.psr=&lsr->psr;
+ CallService(MS_ADDCONTACT_SHOW,(WPARAM)hwndDlg,(LPARAM)&acs);
+ break;
+ }
+ case IDC_DETAILS:
+ { HANDLE hContact;
+ hContact=(HANDLE)CallProtoService(lsr->szProto,PS_ADDTOLIST,PALF_TEMPORARY,(LPARAM)&lsr->psr);
+ CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)hContact,0);
+ break;
+ }
+ case IDC_SENDMESSAGE:
+ { HANDLE hContact;
+ hContact=(HANDLE)CallProtoService(lsr->szProto,PS_ADDTOLIST,PALF_TEMPORARY,(LPARAM)&lsr->psr);
+ CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)(const char*)NULL);
+ break;
+ }
+ }
+ DestroyMenu(hPopupMenu);
+ DestroyMenu(hMenu);
+}
+
+