searchprogram.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2003, 2004, 2005 Martin Fuchs
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 
00020  //
00021  // Explorer clone
00022  //
00023  // dialogs/searchprogram.cpp
00024  //
00025  // Explorer dialogs
00026  //
00027  // Martin Fuchs, 02.10.2003
00028  //
00029 
00030 
00031 #include <precomp.h>
00032 
00033 #include "../resource.h"
00034 
00035 #include "searchprogram.h"
00036 
00037 
00038 int CollectProgramsThread::Run()
00039 {
00040     try {
00041         collect_programs(SpecialFolderPath(CSIDL_COMMON_PROGRAMS, _hwnd));
00042     } catch(COMException&) {
00043     }
00044 
00045     if (_alive)
00046         try {
00047             collect_programs(SpecialFolderPath(CSIDL_PROGRAMS, _hwnd));
00048         } catch(COMException&) {
00049         }
00050 
00051     if (_alive)
00052         _cache_valid = true;
00053 
00054     return 0;
00055 }
00056 
00057 void CollectProgramsThread::collect_programs(const ShellPath& path)
00058 {
00059     ShellDirectory* dir = new ShellDirectory(GetDesktopFolder(), path, 0);
00060     _dirs.push(dir);
00061 
00062     dir->smart_scan(SORT_NONE);
00063 
00064     for(Entry*entry=dir->_down; _alive && entry; entry=entry->_next) {
00065         if (entry->_shell_attribs & SFGAO_HIDDEN)
00066             continue;
00067 
00068         if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00069             collect_programs(entry->create_absolute_pidl());
00070         else if (entry->_shell_attribs & SFGAO_LINK)
00071             if (_alive)
00072                 _callback(entry, _para);
00073     }
00074 }
00075 
00076 void CollectProgramsThread::free_dirs()
00077 {
00078     while(!_dirs.empty()) {
00079         ShellDirectory* dir = _dirs.top();
00080         dir->free_subentries();
00081         _dirs.pop();
00082     }
00083 }
00084 
00085 
00086 #ifdef _MSC_VER
00087 #pragma warning(disable: 4355)
00088 #endif
00089 
00090 FindProgramDlg::FindProgramDlg(HWND hwnd)
00091  :  super(hwnd),
00092     _list_ctrl(GetDlgItem(hwnd, IDC_PROGRAMS_FOUND)),
00093     _thread(collect_programs_callback, hwnd, this),
00094     _sort(_list_ctrl, CompareFunc/*, (LPARAM)this*/)
00095 {
00096     TCHAR szTemp[256];
00097     const size_t nChars = sizeof(szTemp)/sizeof(*szTemp);
00098     SetWindowIcon(hwnd, IDI_SEARCH);
00099 
00100     _resize_mgr.Add(IDC_FILTER,         RESIZE_X);
00101     _resize_mgr.Add(IDC_CHECK_ENTRIES,  MOVE_X);
00102     _resize_mgr.Add(IDC_PROGRAMS_FOUND, RESIZE);
00103 
00104     _resize_mgr.Resize(+520, +300);
00105 
00106     _haccel = LoadAccelerators(g_Globals._hInstance, MAKEINTRESOURCE(IDA_SEARCH_PROGRAM));
00107 
00108     (void)ListView_SetImageList(_list_ctrl, g_Globals._icon_cache.get_sys_imagelist(), LVSIL_SMALL);
00109 
00110     LV_COLUMN column = {LVCF_FMT|LVCF_WIDTH|LVCF_TEXT, LVCFMT_LEFT, 250};
00111 
00112     LoadString(g_Globals._hInstance, IDS_NAMECOLUMN, szTemp, nChars);
00113     column.pszText = szTemp;
00114     ListView_InsertColumn(_list_ctrl, 0, &column);
00115 
00116     column.cx = 300;
00117     LoadString(g_Globals._hInstance, IDS_PATHCOLUMN, szTemp, nChars);
00118     column.pszText = szTemp;
00119     ListView_InsertColumn(_list_ctrl, 1, &column);
00120 
00121     column.cx = 400;
00122     LoadString(g_Globals._hInstance, IDS_MENUCOLUMN, szTemp, nChars);
00123     column.pszText = szTemp;
00124     ListView_InsertColumn(_list_ctrl, 2, &column);
00125 
00126     ListView_SetExtendedListViewStyleEx(_list_ctrl, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
00127 
00128     _common_programs = SpecialFolderFSPath(CSIDL_COMMON_PROGRAMS, hwnd);
00129     if (!_common_programs.empty())
00130         _common_programs.append(_T("\\"));
00131 
00132     _user_programs = SpecialFolderFSPath(CSIDL_PROGRAMS, hwnd);
00133     if (!_user_programs.empty())
00134         _user_programs.append(_T("\\"));
00135 
00136     CenterWindow(hwnd);
00137 
00138     Refresh();
00139 
00140     register_pretranslate(hwnd);
00141 }
00142 
00143 FindProgramDlg::~FindProgramDlg()
00144 {
00145     _thread.Stop();
00146 
00147     unregister_pretranslate(_hwnd);
00148 }
00149 
00150 
00151 void FindProgramDlg::Refresh(bool delete_cache)
00152 {
00153     WaitCursor wait;
00154 
00155     _thread.Stop();
00156 
00157     TCHAR buffer[1024];
00158     GetWindowText(GetDlgItem(_hwnd, IDC_FILTER), buffer, COUNTOF(buffer));
00159     CharLower(buffer);
00160     _lwr_filter = buffer;
00161 
00162     HiddenWindow hide_listctrl(_list_ctrl);
00163 
00164     ListView_DeleteAllItems(_list_ctrl);
00165 
00166     if (delete_cache || !_thread._cache_valid) {
00167         _thread.free_dirs();
00168         _thread.Start();
00169     } else {
00170         for(FPDCache::const_iterator it=_cache.begin(); it!=_cache.end(); ++it)
00171             add_entry(*it);
00172     }
00173 }
00174 
00175 void FindProgramDlg::collect_programs_callback(Entry* entry, void* param)
00176 {
00177     FindProgramDlg* pThis = (FindProgramDlg*) param;
00178 
00179     IShellLink* pShellLink;
00180     HRESULT hr = entry->GetUIObjectOf(pThis->_hwnd, IID_IShellLink, (LPVOID*)&pShellLink);
00181 
00182     if (SUCCEEDED(hr)) {
00183         ShellLinkPtr shell_link(pShellLink);
00184 
00185         shell_link->Release();
00186 
00187         /*hr = pShellLink->Resolve(pThis->_hwnd, SLR_NO_UI);
00188         if (SUCCEEDED(hr))*/ {
00189             WIN32_FIND_DATA wfd;
00190             TCHAR path[MAX_PATH];
00191 
00192             hr = pShellLink->GetPath(path, COUNTOF(path)-1, &wfd, SLGP_UNCPRIORITY);
00193 
00194             if (SUCCEEDED(hr)) {
00195                 TCHAR entry_path[MAX_PATH];
00196 
00197                 entry->get_path(entry_path, COUNTOF(entry_path));
00198 
00199                 String menu_path;
00200 
00201                 int len = pThis->_common_programs.size();
00202 
00203                 if (len && !_tcsnicmp(entry_path, pThis->_common_programs, len))
00204                     menu_path = ResString(IDS_ALL_USERS) + (String(entry_path)+len);
00205                 else if ((len=pThis->_user_programs.size()) && !_tcsnicmp(entry_path, pThis->_user_programs, len))
00206                     menu_path = String(entry_path)+len;
00207 
00208                  // store info in cache
00209                 FPDEntry new_entry;
00210 
00211                 new_entry._entry = entry;
00212                 new_entry._menu_path = menu_path;
00213                 new_entry._path = path;
00214                 new_entry._idxIcon = I_IMAGECALLBACK;
00215 
00216                 pThis->_cache.push_front(new_entry);
00217                 FPDEntry& cache_entry = pThis->_cache.front();
00218 
00219                 Lock lock(pThis->_thread._crit_sect);
00220 
00221                  // resolve deadlocks while executing Thread::Stop()
00222                 if (!pThis->_thread.is_alive())
00223                     return;
00224 
00225                 pThis->add_entry(cache_entry);
00226             }
00227         }
00228     }
00229 }
00230 
00231 void FindProgramDlg::add_entry(const FPDEntry& cache_entry)
00232 {
00233     String lwr_path = cache_entry._path;
00234     String lwr_name = cache_entry._entry->_display_name;
00235 
00236     lwr_path.toLower();
00237     lwr_name.toLower();
00238 
00239     if (_lwr_filter.empty())
00240         if (_tcsstr(lwr_name, _T("uninstal")) || _tcsstr(lwr_name, _T("deinstal"))) // filter out deinstallation links
00241             return;
00242 
00243     if (!_tcsstr(lwr_path, _lwr_filter) && !_tcsstr(lwr_name, _lwr_filter))
00244         return;
00245 
00246     LV_ITEM item = {LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM, INT_MAX};
00247 
00248     item.pszText = cache_entry._entry->_display_name;
00249     item.iImage = cache_entry._idxIcon;
00250     item.lParam = (LPARAM) &cache_entry;
00251     item.iItem = ListView_InsertItem(_list_ctrl, &item);    // We could use the information in _sort to enable manual sorting while populating the list.
00252 
00253     item.mask = LVIF_TEXT;
00254 
00255     item.iSubItem = 1;
00256     item.pszText = (LPTSTR)(LPCTSTR)cache_entry._path;
00257     ListView_SetItem(_list_ctrl, &item);
00258 
00259     item.iSubItem = 2;
00260     item.pszText = (LPTSTR)(LPCTSTR)cache_entry._menu_path;
00261     ListView_SetItem(_list_ctrl, &item);
00262 }
00263 
00264 LRESULT FindProgramDlg::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00265 {
00266     switch(nmsg) {
00267       case WM_CLOSE:
00268         (void)ListView_SetImageList(_list_ctrl, 0, LVSIL_SMALL);    // detach system image list
00269         goto def;
00270 
00271       case PM_TRANSLATE_MSG: {
00272         MSG* pmsg = (MSG*) lparam;
00273 
00274         if (TranslateAccelerator(_hwnd, _haccel, pmsg))
00275             return TRUE;
00276 
00277         return FALSE;}
00278 
00279       default: def:
00280         return super::WndProc(nmsg, wparam, lparam);
00281     }
00282 
00283     return 0;
00284 }
00285 
00286 int FindProgramDlg::Command(int id, int code)
00287 {
00288     if (code == BN_CLICKED) {
00289         switch(id) {
00290           case ID_REFRESH:
00291             Refresh(true);
00292             break;
00293 
00294           case IDOK:
00295             LaunchSelected();
00296             break;
00297 
00298           case IDC_CHECK_ENTRIES:
00299             CheckEntries();
00300             break;
00301 
00302           default:
00303             return super::Command(id, code);
00304         }
00305 
00306         return 0;
00307     }
00308     else if (code == EN_CHANGE) {
00309         switch(id) {
00310           case IDC_FILTER:
00311             Refresh();
00312             break;
00313         }
00314 
00315         return 0;
00316     }
00317 
00318     return 1;
00319 }
00320 
00321 void FindProgramDlg::LaunchSelected()
00322 {
00323     Lock lock(_thread._crit_sect);
00324 
00325     int count = ListView_GetSelectedCount(_list_ctrl);
00326 
00327     if (count > 1)
00328         if (MessageBox(_hwnd, ResString(IDS_LAUNCH_MANY_PROGRAMS), ResString(IDS_TITLE), MB_OKCANCEL) != IDOK)
00329             return;
00330 
00331     for(int idx=-1; (idx=ListView_GetNextItem(_list_ctrl, idx, LVNI_SELECTED))!=-1; ) {
00332         LPARAM lparam = ListView_GetItemData(_list_ctrl, idx);
00333 
00334         if (lparam) {
00335             FPDEntry& cache_entry = *(FPDEntry*)lparam;
00336             cache_entry._entry->launch_entry(_hwnd);
00337         }
00338     }
00339 }
00340 
00341 int FindProgramDlg::Notify(int id, NMHDR* pnmh)
00342 {
00343     switch(pnmh->code) {
00344       case LVN_GETDISPINFO: {
00345         LV_DISPINFO* pDispInfo = (LV_DISPINFO*) pnmh;
00346 
00347         if (pnmh->hwndFrom == _list_ctrl) {
00348             if (pDispInfo->item.mask & LVIF_IMAGE) {
00349                 FPDEntry& cache_entry = *(FPDEntry*)pDispInfo->item.lParam;
00350                 Entry* entry = cache_entry._entry;
00351 
00352                 if (entry->_icon_id == ICID_UNKNOWN)
00353                     entry->_icon_id = entry->extract_icon(ICF_SYSCACHE);
00354 
00355                 pDispInfo->item.iImage = g_Globals._icon_cache.get_icon(entry->_icon_id).get_sysiml_idx();
00356                 pDispInfo->item.mask |= LVIF_DI_SETITEM;
00357 
00358                 return 1;
00359             }
00360         }}
00361         break;
00362 
00363       case NM_DBLCLK:
00364         if (pnmh->hwndFrom == _list_ctrl)
00365             LaunchSelected();
00366         /*{
00367             Lock lock(_thread._crit_sect);
00368 
00369             LPNMLISTVIEW pnmv = (LPNMLISTVIEW) pnmh;
00370             LPARAM lparam = ListView_GetItemData(pnmh->hwndFrom, pnmv->iItem);
00371 
00372             if (lparam) {
00373                 FPDEntry& cache_entry = *(FPDEntry*)lparam;
00374                 cache_entry._entry->launch_entry(_hwnd);
00375             }
00376         }*/
00377         break;
00378 
00379       case HDN_ITEMCLICK: {
00380         WaitCursor wait;
00381         NMHEADER* phdr = (NMHEADER*)pnmh;
00382 
00383         if (GetParent(pnmh->hwndFrom) == _list_ctrl) {
00384             if (_thread._cache_valid) { // disable manual sorting while populating the list
00385                 _sort.toggle_sort(phdr->iItem);
00386                 _sort.sort();
00387             }
00388         }
00389         break;}
00390     }
00391 
00392     return 0;
00393 }
00394 
00395 int CALLBACK FindProgramDlg::CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort)
00396 {
00397     ListSort* sort = (ListSort*)lparamSort;
00398 
00399     FPDEntry& a = *(FPDEntry*)lparam1;
00400     FPDEntry& b = *(FPDEntry*)lparam2;
00401 
00402     int cmp = 0;
00403 
00404     switch(sort->_sort_crit) {
00405       case 0:
00406         cmp = _tcsicoll(a._entry->_display_name, b._entry->_display_name);
00407         break;
00408 
00409       case 1:
00410         cmp = _tcsicoll(a._path, b._path);
00411         break;
00412 
00413       case 2:
00414         cmp = _tcsicoll(a._menu_path, b._menu_path);
00415     }
00416 
00417     return sort->_direction? -cmp: cmp;
00418 }
00419 
00420 void FindProgramDlg::CheckEntries()
00421 {
00422     ///@todo check all entries for existing targets, display a list of not working entries and ask the user for permission to delete them
00423 }

ROS Explorer Source Code Documentation
generated on 02.01.2013 by doxygen

ROS Explorer Homepage