Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

lvwSums.cpp

Go to the documentation of this file.
00001 /* 00002 * wxChecksums 00003 * Copyright (C) 2003-2004 Julien Couot 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 */ 00019 00020 /** 00021 * \file lvwSums.cpp 00022 * A personalized listview to display information about checksums. 00023 */ 00024 00025 00026 //--------------------------------------------------------------------------- 00027 // For compilers that support precompilation, includes "wx.h". 00028 #include <wx/wxprec.h> 00029 00030 #ifdef __BORLANDC__ 00031 #pragma hdrstop 00032 #endif 00033 00034 #ifndef WX_PRECOMP 00035 // Include your minimal set of headers here, or wx.h 00036 #include <wx/wx.h> 00037 #endif 00038 00039 #if wxUSE_DRAG_AND_DROP 00040 #include <wx/dnd.h> 00041 #endif // wxUSE_DRAG_AND_DROP 00042 #include <wx/datetime.h> 00043 #include <wx/imaglist.h> 00044 00045 #include "lvwSums.hpp" 00046 #include "dlgAddMatchFiles.hpp" 00047 #include "dlgInvalidFiles.hpp" 00048 #include "dlgProgress.hpp" 00049 00050 #include "appprefs.hpp" 00051 #include "bytedisp.hpp" 00052 #include "checksumutil.hpp" 00053 #include "comdefs.hpp" 00054 #include "fileutil.hpp" 00055 #include "fdftlmk.hpp" 00056 #include "osdep.hpp" 00057 #include "sumfile.hpp" 00058 #include "utils.hpp" 00059 00060 #include "bitmaps/lvw_sums_notverified.xpm" 00061 #include "bitmaps/lvw_sums_verified.xpm" 00062 #include "bitmaps/lvw_sums_invalid.xpm" 00063 #include "bitmaps/lvw_sums_notfound.xpm" 00064 #include "bitmaps/hi16_action_fileadd.xpm" 00065 #include "bitmaps/hi16_action_directoryadd.xpm" 00066 #include "bitmaps/hi16_action_addmatchingfiles.xpm" 00067 #include "bitmaps/hi16_action_fileremove.xpm" 00068 00069 #include "compat.hpp" 00070 //--------------------------------------------------------------------------- 00071 00072 00073 /// The C++ standard namespace. 00074 using namespace std; 00075 00076 00077 /* 00078 * Defines a custom event for files dropping from the explorer or a file 00079 * manager. 00080 * 00081 * On Windows the Explorer waits that DndCheckSumListView::OnDropFiles() 00082 * return a value that could be long if the checksums are proceeded. 00083 * So DndCheckSumListView::OnDropFiles() post a EVT_DNDFILES_COMMAND 00084 * event and the checksums list adds itself the files. 00085 */ 00086 BEGIN_DECLARE_EVENT_TYPES() 00087 DECLARE_EVENT_TYPE(EVENT_DNDFILES_COMMAND, 10001) 00088 END_DECLARE_EVENT_TYPES() 00089 00090 DEFINE_EVENT_TYPE(EVENT_DNDFILES_COMMAND) 00091 00092 00093 /* 00094 * Defines a custom event for updating the dialog title. 00095 * Use this event when a child want the dialog title to be updated. 00096 */ 00097 DEFINE_LOCAL_EVENT_TYPE(EVENT_UPDATE_SUMS_FRAME_TITLE_COMMAND) 00098 00099 /* 00100 * Defines a custom event for updating the status bar. 00101 * Use this event when a child want the dialog status bar to be updated. 00102 */ 00103 DEFINE_LOCAL_EVENT_TYPE(EVENT_UPDATE_SUMS_FRAME_STATUSBAR_COMMAND) 00104 00105 /* 00106 * Defines a custom event for adding a file in the open recently file list. 00107 */ 00108 DEFINE_LOCAL_EVENT_TYPE(EVENT_OPEN_RECENT_ADD_FILE) 00109 00110 00111 //########################################################################### 00112 // A custom drop target which accepts files 00113 //########################################################################### 00114 #if wxUSE_DRAG_AND_DROP 00115 /** 00116 * Drop target which accepts files for the checksums list. 00117 */ 00118 class DndCheckSumListView : public wxFileDropTarget 00119 { 00120 public: 00121 // Constructor. 00122 DndCheckSumListView(ChecksumsListView *pOwner); 00123 00124 // Event handler for dropped file of the list. 00125 virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames); 00126 00127 private: 00128 ChecksumsListView* owner; ///< Owner list of this object. 00129 }; 00130 //--------------------------------------------------------------------------- 00131 00132 00133 /** 00134 * Constructor. 00135 * 00136 * @param pOwner Adress of the list which owns this drop target. 00137 */ 00138 DndCheckSumListView::DndCheckSumListView(ChecksumsListView *pOwner) 00139 { 00140 owner = pOwner; 00141 } 00142 //--------------------------------------------------------------------------- 00143 00144 00145 /** 00146 * Event handler for dropped file of the list. 00147 * 00148 * Posts an EVENT_DNDFILES_COMMAND event. The owner MUST register the 00149 * EVENT_DNDFILES_COMMAND event and delete the array pointed by the client data 00150 * member. 00151 * 00152 * @param x The x coordinate of the mouse. 00153 * @param y The y coordinate of the mouse. 00154 * @param filenames An array of filenames. 00155 */ 00156 bool DndCheckSumListView::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) 00157 { 00158 if (owner != NULL) 00159 { 00160 // owner->addFiles(filenames); // old method. Freeze explorer on Windows. 00161 00162 wxArrayString* f = new wxArrayString(filenames); 00163 00164 wxCommandEvent event(EVENT_DNDFILES_COMMAND); 00165 event.SetClientData(f); 00166 owner->AddPendingEvent(event); 00167 } 00168 00169 return true; 00170 } 00171 //--------------------------------------------------------------------------- 00172 00173 #endif // wxUSE_DRAG_AND_DROP 00174 00175 00176 00177 //########################################################################### 00178 // A progression updater for the ChecksumFileCalculator class 00179 //########################################################################### 00180 00181 /** 00182 * Displays the progression of the process of computing of a checksum. 00183 */ 00184 class ChecksumsListView::ChecksumProgress : public ::ChecksumProgress 00185 { 00186 protected: 00187 wxString fileName; ///< Name of the current file. 00188 wxString msg; ///< Message to display. 00189 BytesDisplayer current; ///< numbers of preceeded bytes. 00190 double dTotal; ///< Total of bytes to process. 00191 wxString sTotal; ///< Total of bytes to process. 00192 int p; ///< Progress in %. 00193 wxTimeSpan timeSpan; ///< Time between to updates of the progress dialog. 00194 wxDateTime lt; ///< Last saved time. 00195 wxDateTime ct; ///< Current time. 00196 dlgProgress* progress; ///< Progress dialog. 00197 int maxProgress; ///< Maximal value of the progress dialog. 00198 int maxProgressM1; ///< Maximal value of the progress dialog - 1. 00199 double maxProgressD; ///< Maximal value of the progress dialog (double). 00200 00201 /// Default constructor. Don't call it. 00202 ChecksumProgress() { init(); }; 00203 00204 // Initializes the instance. 00205 void init(); 00206 00207 public: 00208 // Constructor. 00209 ChecksumProgress(const wxString& message, const wxString& title, wxWindow* parent, const BytesDisplayer& total); 00210 00211 // Destructor. 00212 virtual ~ChecksumProgress(); 00213 00214 // Updates the progression of the computing of a checksum. 00215 virtual void update(size_t read, bool& canceled); 00216 00217 // Indicates that the process is finished (hides the progress dialog). 00218 void finished(); 00219 00220 // Gets the current file that is processed. 00221 wxString getFileName() const; 00222 00223 // Sets the current file that is processed. 00224 void setFileName(const wxString& curFileName); 00225 }; 00226 //--------------------------------------------------------------------------- 00227 00228 00229 /** 00230 * Initializes the instance. 00231 */ 00232 void ChecksumsListView::ChecksumProgress::init() 00233 { 00234 progress = NULL; 00235 } 00236 //--------------------------------------------------------------------------- 00237 00238 00239 /** 00240 * Constructor. 00241 * 00242 * @param message Message that will be displayed in the progress dialog. 00243 * It should have the following from : 00244 * "Proceeding %s, %s on %s read." 00245 * @param title Title of the progress dialog. 00246 * @param parent Parent of the progress dialog. 00247 * @param total Total of bytes to process. 00248 */ 00249 ChecksumsListView::ChecksumProgress::ChecksumProgress(const wxString& message, const wxString& title, wxWindow* parent, const BytesDisplayer& total) 00250 { 00251 init(); 00252 00253 msg = message; 00254 dTotal = total.toDouble(BytesDisplayer::byte); 00255 sTotal = total.toString(); 00256 maxProgress = SHRT_MAX; 00257 maxProgressM1 = maxProgress - 1; 00258 maxProgressD = static_cast<double>(maxProgress); 00259 timeSpan = wxTimeSpan(0, 0, 0, UPDATE_PROGRESS_DLG); 00260 lt = wxDateTime::UNow() - timeSpan; 00261 progress = new dlgProgress(title, _("Beginning..."), maxProgress, parent, 00262 wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME); 00263 } 00264 //--------------------------------------------------------------------------- 00265 00266 00267 /** 00268 * Destructor. 00269 */ 00270 ChecksumsListView::ChecksumProgress::~ChecksumProgress() 00271 { 00272 if (progress != NULL) 00273 { 00274 delete progress; 00275 progress = NULL; 00276 } 00277 } 00278 //--------------------------------------------------------------------------- 00279 00280 00281 /** 00282 * Updates the progression of the computing of a checksum. 00283 * 00284 * @param read Number of bytes read. 00285 * @param canceled Set it to <CODE>true</CODE> if the user want to cancel 00286 * the calculation. The caller should call it with its value 00287 * set to <CODE>false</CODE>. 00288 */ 00289 void ChecksumsListView::ChecksumProgress::update(size_t read, bool& canceled) 00290 { 00291 current += static_cast<unsigned long>(read); 00292 p = (dTotal != 0.0) ? static_cast<int>(current.toDouble(BytesDisplayer::byte) * maxProgressD / dTotal) : maxProgress; 00293 if (p >= maxProgress) 00294 p = maxProgressM1; 00295 ct = wxDateTime::UNow(); 00296 if (ct.IsLaterThan(lt)) 00297 { 00298 canceled = !progress->Update(p, wxString::Format(msg, fileName.c_str(), current.toString().c_str(), sTotal.c_str())); 00299 ::wxYield(); 00300 lt = ct + timeSpan; 00301 } 00302 00303 // Pause ? 00304 while (progress->isPaused()) 00305 ::wxYield(); 00306 } 00307 //--------------------------------------------------------------------------- 00308 00309 00310 /** 00311 * Indicates that the process is finished (hides the progress dialog). 00312 */ 00313 void ChecksumsListView::ChecksumProgress::finished() 00314 { 00315 progress->Update(maxProgress, _("Finished")); 00316 } 00317 //--------------------------------------------------------------------------- 00318 00319 00320 /** 00321 * Gets the current file that is processed. 00322 * 00323 * @return The current file that is processed. 00324 */ 00325 wxString ChecksumsListView::ChecksumProgress::getFileName() const 00326 { 00327 return fileName; 00328 } 00329 //--------------------------------------------------------------------------- 00330 00331 00332 /** 00333 * Sets the current file that is processed. 00334 * 00335 * @param curFileName New name of the current file which is processed. 00336 */ 00337 void ChecksumsListView::ChecksumProgress::setFileName(const wxString& curFileName) 00338 { 00339 fileName = curFileName; 00340 } 00341 //--------------------------------------------------------------------------- 00342 00343 00344 00345 //########################################################################### 00346 // ChecksumsListView methods 00347 //########################################################################### 00348 00349 IMPLEMENT_DYNAMIC_CLASS(ChecksumsListView, wxListView) 00350 00351 00352 /** 00353 * Default constructor. 00354 */ 00355 ChecksumsListView::ChecksumsListView() : wxListView() 00356 { 00357 init(); 00358 sumFile = NULL; 00359 } 00360 //--------------------------------------------------------------------------- 00361 00362 00363 /** 00364 * Constructor, creating and showing a list control. 00365 * 00366 * @param parent Parent window. Must not be <CODE>NULL</CODE>. 00367 * @param id Window identifier. A value of <CODE>-1</CODE> indicates a 00368 * default value. 00369 * @param checksumFile The checksum file linked with this listview. 00370 * @param pos Window position. 00371 * @param size Window size. If the default size <CODE>(-1, -1)</CODE> is 00372 * specified then the window is sized appropriately. 00373 * @param style Window style. See <I>wxListCtrl</I>. 00374 * @param validator Window validator. 00375 * @param name Window name. 00376 */ 00377 ChecksumsListView::ChecksumsListView(wxWindow* parent, wxWindowID id, 00378 SumFile* checksumFile, const wxPoint& pos, 00379 const wxSize& size, long style, 00380 const wxValidator& validator, 00381 const wxString& name) : 00382 wxListView(parent, id, pos, size, style, validator, name) 00383 { 00384 init(); 00385 sumFile = checksumFile; 00386 } 00387 //--------------------------------------------------------------------------- 00388 00389 00390 /** 00391 * Destructor. 00392 */ 00393 ChecksumsListView::~ChecksumsListView() 00394 { 00395 if (sumFile != NULL) 00396 { 00397 delete sumFile; 00398 sumFile = NULL; 00399 } 00400 } 00401 //--------------------------------------------------------------------------- 00402 00403 00404 /** 00405 * Initializes the list parameters. 00406 */ 00407 void ChecksumsListView::init() 00408 { 00409 // Creates an image list for this listview. 00410 // Order and index should corresponds to ChecksumData::State 00411 wxImageList* imlStateIcons = new wxImageList(16, 16); 00412 imlStateIcons->Add(wxIcon(lvw_sums_notverified_xpm)); 00413 imlStateIcons->Add(wxIcon(lvw_sums_verified_xpm)); 00414 imlStateIcons->Add(wxIcon(lvw_sums_invalid_xpm)); 00415 imlStateIcons->Add(wxIcon(lvw_sums_notfound_xpm)); 00416 00417 setColumnToSort(0, NONE); 00418 AssignImageList(imlStateIcons, wxIMAGE_LIST_SMALL); 00419 00420 #if wxUSE_DRAG_AND_DROP 00421 SetDropTarget(new DndCheckSumListView(this)); 00422 #endif // wxUSE_DRAG_AND_DROP 00423 00424 columns[0] = FILE_NAME; 00425 columns[1] = DIRECTORY; 00426 columns[2] = CHECKSUM_VALUE; 00427 columns[3] = STATE; 00428 InsertColumn(0, getColumnName(columns[0]), wxLIST_FORMAT_LEFT); 00429 InsertColumn(1, getColumnName(columns[1]), wxLIST_FORMAT_LEFT); 00430 InsertColumn(2, getColumnName(columns[2]), wxLIST_FORMAT_LEFT); 00431 InsertColumn(3, getColumnName(columns[3]), wxLIST_FORMAT_LEFT); 00432 } 00433 //--------------------------------------------------------------------------- 00434 00435 00436 /** 00437 * Gets to sort order. 00438 * 00439 * @return The sort order. 00440 */ 00441 ChecksumsListView::SortOrder ChecksumsListView::getSortOrder() const 00442 { 00443 return sortOrder; 00444 } 00445 //--------------------------------------------------------------------------- 00446 00447 00448 /** 00449 * Sets the sort order. 00450 * 00451 * @param newSortOrder New sort order. Must be <CODE>ASCENDING</CODE> or 00452 * <CODE>DESCENDING</CODE>. If other value is given, 00453 * <CODE>ASCENDING</CODE> is assumed by default. 00454 */ 00455 void ChecksumsListView::setSortOrder(const SortOrder newSortOrder) 00456 { 00457 switch (newSortOrder) 00458 { 00459 case NONE : 00460 case ASCENDING : 00461 case DESCENDING : 00462 sortOrder = newSortOrder; 00463 break; 00464 default : 00465 sortOrder = NONE; 00466 } 00467 } 00468 //--------------------------------------------------------------------------- 00469 00470 00471 /** 00472 * Gets the column to be sorted 00473 * 00474 * @return The column to be sorted. 00475 */ 00476 int ChecksumsListView::getColumnToSort() const 00477 { 00478 return colToSort; 00479 } 00480 //--------------------------------------------------------------------------- 00481 00482 00483 /** 00484 * Sets the column to be sorted. 00485 * 00486 * @param col The column with witch the sort will be done. If the given 00487 * column is invalid, the first column of the list will be taken. 00488 */ 00489 void ChecksumsListView::setColumnToSort(const int col) 00490 { 00491 if (col >= 0 && col < GetColumnCount()) 00492 colToSort = col; 00493 else 00494 colToSort = 0; 00495 } 00496 //--------------------------------------------------------------------------- 00497 00498 00499 /** 00500 * Sets the column to be sorted. 00501 * 00502 * @param col The column with witch the sort will be done. 00503 * @param newSortOrder New sort order. 00504 * @see getSortOrder(), setColumnToSort(int) 00505 */ 00506 void ChecksumsListView::setColumnToSort(const int col, const SortOrder newSortOrder) 00507 { 00508 setColumnToSort(col); 00509 setSortOrder(newSortOrder); 00510 } 00511 //--------------------------------------------------------------------------- 00512 00513 00514 /** 00515 * List compare function. 00516 * 00517 * <B>Warning &nbsp;:</B> this is a quick&dirty fonction, where a pointer 00518 * on a ChecksumsListView class is passed in a parameter with the long type. 00519 * 00520 * @param item1 data on the first item. 00521 * @param item2 data on the second item. 00522 * @param sortData adress of the wallpaper list (yerk !) 00523 */ 00524 static int wxCALLBACK SumListCompareFnct(long item1, long item2, long sortData) 00525 { 00526 ChecksumsListView* pList = reinterpret_cast<ChecksumsListView*>(sortData); 00527 00528 // Gets the checksum data of the items 00529 ChecksumData cd1 = pList->getSumFile()->getChecksumData(item1); 00530 ChecksumData cd2 = pList->getSumFile()->getChecksumData(item2); 00531 00532 // Gets the sort parameters 00533 int colToSort = pList->getColumnToSort(); 00534 ChecksumsListView::SortOrder sortOrder = pList->getSortOrder(); 00535 00536 // Compare the items. 00537 if (sortOrder == ChecksumsListView::NONE) 00538 // Compare the keys 00539 return item1 - item2; 00540 00541 int res; 00542 ChecksumsListView::Columns cols[LVW_SUMS_NBCOLS]; 00543 pList->getColumns(cols); 00544 switch (cols[colToSort]) 00545 { 00546 case ChecksumsListView::FILE_NAME : 00547 res = ::compareFileName(cd1.getFileName().GetFullName(), cd2.getFileName().GetFullName()); 00548 break; 00549 case ChecksumsListView::DIRECTORY : { 00550 wxFileName fn1 = cd1.getFileName(); 00551 wxFileName fn2 = cd2.getFileName(); 00552 wxFileName sumFileName = pList->getSumFile()->getFileName(); 00553 00554 if (AppPrefs::get()->readBool(prGUI_MAIN_SUMS_DIRSINABSOLUTEPATH)) 00555 { 00556 if (fn1.IsRelative()) 00557 fn1.MakeAbsolute(sumFileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00558 if (fn2.IsRelative()) 00559 fn2.MakeAbsolute(sumFileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00560 } 00561 else 00562 { 00563 if (fn1.IsAbsolute()) 00564 fn1.MakeRelativeTo(sumFileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00565 if (fn2.IsAbsolute()) 00566 fn2.MakeRelativeTo(sumFileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00567 } 00568 res = ::compareFileName(fn1.GetPath(wxPATH_GET_VOLUME), fn2.GetPath(wxPATH_GET_VOLUME)); } 00569 break; 00570 case ChecksumsListView::CHECKSUM_VALUE : 00571 res = cd1.getChecksum().Cmp(cd2.getChecksum()); 00572 break; 00573 case ChecksumsListView::STATE : 00574 res = static_cast<int>(cd1.getState()) - static_cast<int>(cd2.getState()); 00575 break; 00576 } 00577 00578 if (sortOrder == ChecksumsListView::DESCENDING) 00579 res = -res; 00580 00581 return res; 00582 } 00583 //--------------------------------------------------------------------------- 00584 00585 00586 /** 00587 * Sort the list. 00588 */ 00589 void ChecksumsListView::sort() 00590 { 00591 if (this->getSumFile() != NULL) 00592 { 00593 wxBusyCursor wait; 00594 this->Freeze(); 00595 this->SortItems(SumListCompareFnct, reinterpret_cast<long>(this)); 00596 this->Thaw(); 00597 } 00598 } 00599 //--------------------------------------------------------------------------- 00600 00601 00602 /** 00603 * Gets a pointer on the checksum file. 00604 * 00605 * @return A pointer on the checksum file. 00606 */ 00607 SumFile* ChecksumsListView::getSumFile() const 00608 { 00609 return sumFile; 00610 } 00611 //--------------------------------------------------------------------------- 00612 00613 00614 /** 00615 * Sets the checksum file. 00616 * 00617 * - Deletes the old checksums' file instance in memory. 00618 * - Deletes all the items. 00619 * - Creates new item from the given checksums file if not <CODE>NULL</CODE>. 00620 * 00621 * @param pSumFile A pointer on the new checksums file. 00622 * @remarks The given <CODE>SumFile*</CODE> instance will be deleted by this 00623 * class. 00624 */ 00625 void ChecksumsListView::setSumFile(SumFile* pSumFile) 00626 { 00627 // If sums file is the same do nothing. 00628 if (sumFile == pSumFile) 00629 return; 00630 00631 if (sumFile != NULL) 00632 delete sumFile; 00633 00634 this->DeleteAllItems(); 00635 sumFile = pSumFile; 00636 if (sumFile != NULL) 00637 { 00638 MChecksumDataKeys keys; 00639 sumFile->getChecksumDataKeys(keys); 00640 size_t i, l = keys.GetCount(); 00641 for (i = 0; i < l; i++) 00642 addChecksum(keys[i], _("Not verified")); 00643 } 00644 00645 // Sort the list. 00646 sort(); 00647 } 00648 //--------------------------------------------------------------------------- 00649 00650 00651 /** 00652 * Selects all the items. 00653 */ 00654 void ChecksumsListView::selectAll() 00655 { 00656 int state; 00657 long item = this->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00658 while (item != -1) 00659 { 00660 state = this->GetItemState(item, wxLIST_STATE_SELECTED); 00661 if (!(state & wxLIST_STATE_SELECTED)) 00662 this->SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); 00663 item = this->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00664 } 00665 } 00666 //--------------------------------------------------------------------------- 00667 00668 00669 /** 00670 * Inverts the selection. 00671 */ 00672 void ChecksumsListView::invertSelection() 00673 { 00674 int state; 00675 long item = this->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00676 while (item != -1) 00677 { 00678 state = this->GetItemState(item, wxLIST_STATE_SELECTED); 00679 state = ~state; 00680 this->SetItemState(item, state, wxLIST_STATE_SELECTED); 00681 item = this->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00682 } 00683 } 00684 //--------------------------------------------------------------------------- 00685 00686 00687 /** 00688 * Open a dialog to select the files to add to the list. 00689 */ 00690 void ChecksumsListView::selectFilesToAdd() 00691 { 00692 if (this->getSumFile() != NULL) 00693 { 00694 // Show the open dialog 00695 wxFileDialogFilterMaker fltMaker; 00696 fltMaker.AddFilter(_("All the files"), wxT("*")); 00697 00698 wxFileDialog dlgOpen(this, _("Select the files to be added"), 00699 wxEmptyString, wxEmptyString, fltMaker.GetFilters(), 00700 wxOPEN | wxHIDE_READONLY | wxMULTIPLE | wxFILE_MUST_EXIST, wxDefaultPosition); 00701 wxFileName direct(wxFileName(sumFile->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00702 if (direct.DirExists()) 00703 dlgOpen.SetDirectory(direct.GetFullPath()); 00704 00705 if (dlgOpen.ShowModal() == wxID_OK) 00706 { 00707 wxArrayString files; 00708 dlgOpen.GetPaths(files); 00709 this->addFiles(files); 00710 } 00711 } 00712 } 00713 //--------------------------------------------------------------------------- 00714 00715 00716 /** 00717 * Open a dialog to select the directories to add to the list. 00718 */ 00719 void ChecksumsListView::selectDirectoriesToAdd() 00720 { 00721 if (this->getSumFile() != NULL) 00722 { 00723 // Show the open dialog 00724 wxDirDialog dlgDir(this, _("Select the directory")); 00725 wxFileName direct(wxFileName(sumFile->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00726 if (direct.DirExists()) 00727 dlgDir.SetPath(direct.GetFullPath()); 00728 00729 if (dlgDir.ShowModal() == wxID_OK) 00730 { 00731 wxArrayString files; 00732 files.Add(dlgDir.GetPath()); 00733 this->addFiles(files); 00734 } 00735 } 00736 } 00737 //--------------------------------------------------------------------------- 00738 00739 00740 /** 00741 * Open a dialog to select files to add from matching patterns. 00742 */ 00743 void ChecksumsListView::selectMatchingFilesToAdd() 00744 { 00745 if (this->getSumFile() != NULL) 00746 { 00747 dlgAddMatchFiles dlg(this, this->getSumFile()->getFileName()); 00748 if (dlg.ShowModal() == wxID_OK) 00749 { 00750 // Gets the patterns 00751 size_t i; 00752 dlgAddMatchFiles::ArrayMatchPattern patterns; 00753 dlg.getMatchPatterns(patterns); 00754 00755 if (patterns.getCount() > 0) 00756 { 00757 wxFileName checksum(getSumFile()->getFileName()); 00758 dlgAddMatchFiles::ArrayMatchPattern pats; 00759 for (i = 0; i < patterns.getCount(); i++) 00760 { 00761 // Get a beautiful directory name and remove some possible multiple 00762 // same patterns. 00763 wxFileName fn(patterns[i].getDirectory() + wxFileName::GetPathSeparator()); 00764 if (fn.IsRelative()) 00765 // Make it absolute 00766 { 00767 fn.MakeAbsolute(checksum.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00768 pats.add(dlgAddMatchFiles::MatchPattern(fn.GetPath(wxPATH_GET_VOLUME), patterns[i].getPattern(), patterns[i].getDepth())); 00769 } 00770 else 00771 { 00772 fn.MakeRelativeTo(checksum.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00773 fn.MakeAbsolute(checksum.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00774 pats.add(dlgAddMatchFiles::MatchPattern(fn.GetPath(wxPATH_GET_VOLUME), patterns[i].getPattern(), patterns[i].getDepth())); 00775 } 00776 } 00777 00778 wxArrayString files; 00779 BytesDisplayer bs; 00780 bool cont = true; 00781 i = 0; 00782 while (cont && i < pats.getCount()) 00783 { 00784 wxArrayString lFiles; 00785 lFiles.Add(pats[i].getDirectory()); 00786 cont = ::getFilesInSubdirectories(lFiles, files, bs, 00787 pats[i].getPattern(), 00788 pats[i].getDepth()); 00789 i++; 00790 } 00791 if (cont) 00792 addFiles(files); 00793 } 00794 } 00795 } 00796 } 00797 //--------------------------------------------------------------------------- 00798 00799 00800 /** 00801 * Adds files to the list of checksums. 00802 * 00803 * This function will search recursively files in subdirectories. 00804 * All the files and all the directories that are provided in the array 00805 * must be in absolute path. 00806 * 00807 * @param files A list of files and directories to add. 00808 */ 00809 void ChecksumsListView::addFiles(const wxArrayString& files) 00810 { 00811 if (this->getSumFile() == NULL || files.IsEmpty()) 00812 return; 00813 00814 // No log 00815 wxLogNull logNo; 00816 00817 // Search the files in the subdirectories. 00818 wxArrayString allFiles; 00819 BytesDisplayer total; 00820 if (!::getFilesInSubdirectories(files, allFiles, total)) 00821 return; 00822 00823 if (allFiles.IsEmpty()) 00824 // No files to add, exiting 00825 return; 00826 00827 this->Freeze(); 00828 00829 // Adds the checksums 00830 InvalidFilesContainer invalidFiles; // all the invalid files. 00831 wxString sumFilePath = wxFileName(getSumFile()->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); 00832 Checksum* c = sumFile->getChecksumCalculator(); // checksum calculator 00833 wxFileName fn; // name of the current file 00834 ChecksumFileCalculator::State retState; // state returned by the checksum' calculator. 00835 wxString calcSumValue; // Calculated checksum's value 00836 bool cont = true; // continue ? 00837 00838 // Removes the files that are already in the list. 00839 // wxArrayString in; 00840 cont = removeFilesInList(allFiles/*, &in*/); 00841 00842 /* if (in.GetCount() > 0) // For debug only 00843 { 00844 for (size_t i = 0; i < in.GetCount(); i++) 00845 invalidFiles[in[i]] = _("Already in the list"); 00846 }*/ 00847 00848 // Show the progress dialog 00849 ChecksumProgress progressUpdater(_("Computing the checkum of %s\n%s on %s read."), _("Computing the checksums"), this, total); 00850 ChecksumFileCalculator cfc(c, &progressUpdater); 00851 size_t i = 0; 00852 size_t l = allFiles.GetCount(); 00853 while (i < l && cont) 00854 { 00855 wxString& curFile = allFiles[i]; 00856 fn = curFile; 00857 00858 // Compute the checksum. 00859 progressUpdater.setFileName(fn.GetFullName()); 00860 retState = cfc.calculate(curFile, calcSumValue); 00861 00862 switch (retState) 00863 { 00864 case ChecksumFileCalculator::Ok : // Checksum has been calculated (and corresponds for the check method). 00865 { 00866 fn.MakeRelativeTo(sumFilePath); 00867 ChecksumData d(fn, calcSumValue, ChecksumData::Verified); 00868 long k = this->getSumFile()->addChecksumData(d); 00869 this->addChecksum(k, _("OK")); 00870 } 00871 break; 00872 00873 case ChecksumFileCalculator::ReadError : // Error while reading the stream. 00874 invalidFiles[curFile] = _("Error while reading the file"); 00875 break; 00876 00877 case ChecksumFileCalculator::FileNotFound : // The file has been not found. 00878 invalidFiles[curFile] = _("File not found"); 00879 break; 00880 00881 case ChecksumFileCalculator::CantOpenFile : // Can't open the stream. 00882 invalidFiles[curFile] = _("File cannot be open"); 00883 break; 00884 00885 case ChecksumFileCalculator::CanceledByUser : // User has canceled the calculation. 00886 cont = false; 00887 break; 00888 } 00889 00890 i++; 00891 } 00892 delete c; 00893 progressUpdater.finished(); 00894 00895 this->Thaw(); 00896 00897 // Sort the list 00898 sort(); 00899 00900 if (!invalidFiles.empty()) 00901 { 00902 dlgInvalidFiles dlg(this, _("Invalid files"), 00903 _("The following files were not added to the list of the checksums:"), invalidFiles); 00904 dlg.ShowModal(); 00905 } 00906 } 00907 //--------------------------------------------------------------------------- 00908 00909 00910 /** 00911 * Compare function for <CODE>removeFilesInList</CODE>. 00912 * 00913 * For internal use only. 00914 * For more information, see <CODE>wxArrayString::Sort</CODE> in the wxWidgets 00915 * documentation. 00916 */ 00917 static int removeFilesInListCompare(const wxString& first, const wxString& second) 00918 { 00919 return ::compareFileName(first, second); 00920 } 00921 //--------------------------------------------------------------------------- 00922 00923 00924 /** 00925 * Removes the files that are already in the listview. 00926 * 00927 * @param files List of files to be checked. The files already present in 00928 * the listview will be removed list of <CODE>files</CODE>. 00929 * @param in Pointer on an array string where the files already present in 00930 * the listview will be stored. Could be <CODE>NULL</CODE>. 00931 * @return <CODE>true</CODE> if the user hasn't canceled. 00932 */ 00933 bool ChecksumsListView::removeFilesInList(wxArrayString& files, wxArrayString* in) 00934 { 00935 if (sumFile->getChecksumDataCount() == 0 && files.IsEmpty()) 00936 return true; 00937 00938 wxArrayString lFiles; // Files in the listview 00939 wxFileName fn; 00940 bool cont = true; 00941 wxString sumFilePath = wxFileName(sumFile->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); 00942 MChecksumData::const_iterator it = sumFile->getChecksumDataBegin(); 00943 MChecksumData::const_iterator end = sumFile->getChecksumDataEnd(); 00944 00945 // Get the files in the list 00946 lFiles.Alloc(sumFile->getChecksumDataCount() + files.GetCount()); 00947 while (it != end) 00948 { 00949 fn = it->second.getFileName(); 00950 if (!fn.IsAbsolute()) 00951 fn.MakeAbsolute(sumFilePath); 00952 lFiles.Add(fn.GetFullPath()); 00953 it++; 00954 } 00955 00956 dlgProgress dlgProgress(_("Checking for duplicate files"), _("Beginning..."), 100, this, 00957 wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME); 00958 00959 lFiles.Sort(removeFilesInListCompare); 00960 00961 wxTimeSpan timeSpan(0, 0, 0, UPDATE_PROGRESS_DLG); 00962 wxDateTime lt = wxDateTime::UNow() - timeSpan; // last saved time 00963 wxDateTime ct; // current time 00964 00965 // Search for the present files 00966 size_t i = 0; 00967 int r, a, b; 00968 while (cont && i < files.GetCount()) 00969 { 00970 fn = files[i]; 00971 fn.Normalize(wxPATH_NORM_ALL, sumFilePath); 00972 wxString s = fn.GetFullPath(); 00973 00974 int c = -1; 00975 a = 0; 00976 b = lFiles.GetCount() - 1; 00977 r = (a + b) / 2; 00978 00979 while ((a < b) && (r >= 0) && (r < lFiles.GetCount()) && ((c = ::compareFileName(s, lFiles[r])) != 0)) 00980 { 00981 if (c < 0) 00982 b = r - 1; 00983 else 00984 a = r + 1; 00985 00986 r = (a + b) / 2; 00987 } 00988 if ((r >= 0) && (r < lFiles.GetCount()) && ::compareFileName(s, lFiles[r]) == 0) 00989 { 00990 if (in != NULL) 00991 in->Add(s); 00992 files.Remove(i); 00993 } 00994 else 00995 { 00996 // To avoid to add files likes /dir1/dir2/file1 and /dir1/dir2/../dir2/file1 00997 if (r < 0) r = 0; 00998 if (!lFiles.IsEmpty() && r >= lFiles.GetCount()) r = lFiles.GetCount() - 1; 00999 while (r > 0 && ::compareFileName(s, lFiles[r]) < 0) 01000 r--; 01001 while (r < lFiles.GetCount() && ::compareFileName(s, lFiles[r]) >= 0) 01002 r++; 01003 lFiles.Insert(s, r); 01004 01005 /* Reference for debugging 01006 lFiles.Add(s); 01007 lFiles.Sort(removeFilesInListCompare); */ 01008 01009 i++; 01010 } 01011 01012 // Upadate the progress dialog 01013 ct = wxDateTime::UNow(); 01014 if (ct.IsLaterThan(lt)) 01015 { 01016 int p; // progress value (0-100) 01017 lt = ct + timeSpan; 01018 size_t fc = files.GetCount(); 01019 if (fc > 0) 01020 p = static_cast<int>((static_cast<double>(i) / static_cast<double>(fc)) * 100.0); 01021 else 01022 p = 100; 01023 if (p >= 100) p = 99; 01024 cont = dlgProgress.Update(p, wxString::Format(_("Checking %s"), s.c_str())); 01025 ::wxYield(); 01026 } 01027 01028 // Pause ? 01029 while (dlgProgress.isPaused()) 01030 ::wxYield(); 01031 } 01032 01033 files.Shrink(); 01034 01035 dlgProgress.Update(100, wxString::Format(_("Finished."), files[i].c_str())); 01036 01037 return cont; 01038 } 01039 //--------------------------------------------------------------------------- 01040 01041 01042 /** 01043 * Indicates if the specified file is present in the list. 01044 * 01045 * The given file name must be an absolute path. 01046 * 01047 * @param fileName File name to test the presence in the list. 01048 * @return <CODE>true</CODE> if the file is present in the list, 01049 * <CODE>false</CODE> otherwise. 01050 */ 01051 bool ChecksumsListView::isInList(const wxString& fileName) 01052 { 01053 bool found = false; 01054 wxFileName fn; 01055 wxString sumFilePath = wxFileName(sumFile->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); 01056 01057 MChecksumData::const_iterator it = sumFile->getChecksumDataBegin(); 01058 MChecksumData::const_iterator end = sumFile->getChecksumDataEnd(); 01059 01060 while (!found && it != end) 01061 { 01062 fn = it->second.getFileName(); 01063 fn.MakeAbsolute(sumFilePath); 01064 if (::compareFileName(fn.GetFullPath(), fileName) == 0) 01065 found = true; 01066 else 01067 it++; 01068 } 01069 01070 return found; 01071 } 01072 //--------------------------------------------------------------------------- 01073 01074 01075 /** 01076 * Adds a checksum in the list. 01077 * 01078 * @param key Key of the item in the file of checksums. 01079 * @param stateMsg Information about the state. 01080 * @return The index of the new item. 01081 */ 01082 long ChecksumsListView::addChecksum(const long key, const wxString& stateMsg) 01083 { 01084 int p = this->GetItemCount(); 01085 01086 // Create the item and set its data as the key of corresponding ChecksumData 01087 InsertItem(p, wxT(""), 0); 01088 SetItemData(p, key); 01089 01090 // Sets the item text and picture 01091 setChecksum(p, stateMsg); 01092 ChecksumData cd = sumFile->getChecksumData(key); 01093 setChecksumState(p, cd.getState(), stateMsg); 01094 01095 return p; 01096 } 01097 //--------------------------------------------------------------------------- 01098 01099 01100 /** 01101 * Sets an item. 01102 * 01103 * This function doesn't set the item picture and the data associated with 01104 * the item. 01105 * 01106 * @param item Item to set. 01107 * @param stateMsg Information about the state. 01108 */ 01109 void ChecksumsListView::setChecksum(long item, const wxString& stateMsg) 01110 { 01111 wxFileName fn; 01112 ChecksumData cd = sumFile->getChecksumData(this->GetItemData(item)); 01113 01114 for (int i = 0; i < LVW_SUMS_NBCOLS; i++) 01115 switch (columns[i]) 01116 { 01117 case FILE_NAME : 01118 SetItem(item, i, cd.getFileName().GetFullName()); 01119 break; 01120 case DIRECTORY : 01121 fn = cd.getFileName(); 01122 if (AppPrefs::get()->readBool(prGUI_MAIN_SUMS_DIRSINABSOLUTEPATH)) 01123 { 01124 if (fn.IsRelative()) 01125 fn.MakeAbsolute(wxFileName(sumFile->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 01126 } 01127 else 01128 { 01129 if (fn.IsAbsolute()) 01130 fn.MakeRelativeTo(wxFileName(sumFile->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 01131 } 01132 SetItem(item, i, fn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 01133 break; 01134 case CHECKSUM_VALUE : 01135 if (AppPrefs::get()->readBool(prGUI_MAIN_SUMS_UPPERCASE)) 01136 SetItem(item, i, cd.getChecksum().Upper()); 01137 else 01138 SetItem(item, i, cd.getChecksum().Lower()); 01139 break; 01140 case STATE : 01141 SetItem(item, i, stateMsg); 01142 break; 01143 } 01144 01145 } 01146 //--------------------------------------------------------------------------- 01147 01148 01149 /** 01150 * Sets the state of a checksum 01151 * 01152 * @param item Item which to state should be modified. 01153 * @param state New state of the checksum corresponding to the item. 01154 * @param msg Information about the state. 01155 */ 01156 void ChecksumsListView::setChecksumState(long item, const ChecksumData::State state, const wxString& msg) 01157 { 01158 long key = GetItemData(item); 01159 ChecksumData d = sumFile->getChecksumData(key); 01160 sumFile->setChecksumState(key, state); 01161 01162 // Find the column of the state 01163 int stateCol = -1; 01164 for (int i = 0; (i < LVW_SUMS_NBCOLS) && (stateCol == -1); i++) 01165 if (columns[i] == STATE) 01166 stateCol = i; 01167 01168 SetItem(item, stateCol, msg); 01169 SetItem(item, 0, GetItemText(item), state); 01170 } 01171 //--------------------------------------------------------------------------- 01172 01173 01174 /** 01175 * Removes the selected checksums from the list. 01176 */ 01177 void ChecksumsListView::removeSelectedChecksums() 01178 { 01179 if (this->getSumFile() != NULL) 01180 { 01181 long item; 01182 01183 item = this->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01184 while (item != -1) 01185 { 01186 sumFile->removeChecksumData(this->GetItemData(item)); 01187 this->DeleteItem(item); 01188 item = this->GetNextItem(item - 1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01189 } 01190 } 01191 } 01192 //--------------------------------------------------------------------------- 01193 01194 01195 /** 01196 * Gets the total of each state in the list of checksums. 01197 * 01198 * @param onlySelected If <CODE>true</CODE> gets the state of the selected 01199 * checksums/files. If <CODE>false</CODE> gets the state 01200 * of all the files. 01201 * @return An array that contains the total of each state in the list of 01202 * checksums or an empty array if there is no checksum file opened. 01203 */ 01204 wxArrayInt ChecksumsListView::getStates(const bool onlySelected) const 01205 { 01206 wxArrayInt states; 01207 01208 if (this->getSumFile() != NULL) 01209 { 01210 ChecksumData d; 01211 const int state = onlySelected ? wxLIST_STATE_SELECTED : wxLIST_STATE_DONTCARE; 01212 01213 states.Add(0, CD_STATE_COUNT); 01214 01215 long item = this->GetNextItem(-1, wxLIST_NEXT_ALL, state); 01216 while (item != -1) 01217 { 01218 d = this->getSumFile()->getChecksumData(this->GetItemData(item)); 01219 states[static_cast<size_t>(d.getState())]++; 01220 01221 item = this->GetNextItem(item, wxLIST_NEXT_ALL, state); 01222 } 01223 } 01224 01225 return states; 01226 } 01227 //--------------------------------------------------------------------------- 01228 01229 01230 /** 01231 * Sums up the total of each state in the list of checksums. 01232 * 01233 * @param onlySelected If <CODE>true</CODE> gets the state of the selected 01234 * checksums/files. If <CODE>false</CODE> gets the state 01235 * of all the files. 01236 * @return A string which contains a sum up of the total of each state in the 01237 * list of checksums or an empty string if there is no checksum file 01238 * opened. 01239 */ 01240 wxString ChecksumsListView::sumUpStates(const bool onlySelected) const 01241 { 01242 wxString res; 01243 01244 if (this->getSumFile() != NULL) 01245 { 01246 wxArrayInt states = getStates(onlySelected); 01247 int itemsCount = onlySelected ? this->GetSelectedItemCount() : this->GetItemCount(); 01248 01249 if (itemsCount == 1) 01250 res = _("1 file was checked. "); 01251 else 01252 res.Printf(_("%d files were checked. "), itemsCount); 01253 01254 if (states[ChecksumData::Verified] == itemsCount) 01255 res += _("All are ok."); 01256 else if (states[ChecksumData::Invalid] == itemsCount) 01257 res += _("All are invalid."); 01258 else if (states[ChecksumData::NotFound] == itemsCount) 01259 res += _("All cannot be opened."); 01260 else 01261 { 01262 if (states[ChecksumData::Verified] == 0) 01263 res += _("None is ok"); 01264 else if (states[ChecksumData::Verified] == 1) 01265 res += _("1 is ok"); 01266 else 01267 res += wxString::Format(_("%d are ok"), states[ChecksumData::Verified]); 01268 01269 if (states[ChecksumData::Invalid] == 1) 01270 res += _(", 1 is invalid"); 01271 else if (states[ChecksumData::Invalid] > 1) 01272 res += wxString::Format(_(", %d are invalid"), states[ChecksumData::Invalid]); 01273 01274 if (states[ChecksumData::NotFound] == 1) 01275 res += _(", 1 can't be opened"); 01276 else if (states[ChecksumData::NotFound] > 1) 01277 res += wxString::Format(_(", %d can't be opened"), states[ChecksumData::NotFound]); 01278 01279 res += wxT('.'); 01280 } 01281 } 01282 01283 return res; 01284 } 01285 //--------------------------------------------------------------------------- 01286 01287 01288 /** 01289 * Open a checksum file. 01290 * 01291 * @param fileName Name of the file to open. 01292 * @return <CODE>true</CODE> if the has has been opened successfully, 01293 * <CODE>false</CODE> otherwise. 01294 */ 01295 bool ChecksumsListView::openChecksumFile(const wxFileName& fileName) 01296 { 01297 SumFile* sf = ::openChecksumFile(fileName); 01298 01299 if (sf != NULL) 01300 { 01301 // Assign the read file to this list 01302 this->setSumFile(sf); 01303 01304 // Update the main dialog title 01305 wxCommandEvent event(EVENT_UPDATE_SUMS_FRAME_TITLE_COMMAND); 01306 this->GetParent()->ProcessEvent(event); 01307 01308 // Auto check ? 01309 if (AppPrefs::get()->readBool(prGUI_AUTO_CHECK_ON_OPEN)) 01310 this->check(); 01311 01312 // Adds the file in the recently open files history 01313 wxCommandEvent event2(EVENT_OPEN_RECENT_ADD_FILE); 01314 event2.SetString(fileName.GetFullPath()); 01315 this->GetParent()->ProcessEvent(event2); 01316 01317 return true; 01318 } 01319 else 01320 { 01321 ::wxMessageBox(wxString::Format(_("'%s' cannot be read."), fileName.GetFullPath().c_str()), _("Open a checksums' file"), wxOK | wxICON_EXCLAMATION); 01322 return false; 01323 } 01324 } 01325 //--------------------------------------------------------------------------- 01326 01327 01328 /** 01329 * Checks the files. 01330 */ 01331 void ChecksumsListView::check() 01332 { 01333 if (this->getSumFile() == NULL) 01334 return; // no file is open 01335 01336 wxLogNull logNo; // No log 01337 ChecksumData d; // a checksum data 01338 wxFileName fn; // name of the current file 01339 wxCOff_t fs; // rest of the file size to read 01340 BytesDisplayer total; // total of bytes to process 01341 const int state = (this->GetSelectedItemCount() > 0) ? wxLIST_STATE_SELECTED : wxLIST_STATE_DONTCARE; 01342 01343 // Get the number of bytes to read. 01344 long item = this->GetNextItem(-1, wxLIST_NEXT_ALL, state); 01345 while (item != -1) 01346 { 01347 d = this->getSumFile()->getChecksumData(this->GetItemData(item)); 01348 fn = d.getFileName(); 01349 if (!fn.IsAbsolute()) 01350 fn.MakeAbsolute(wxFileName(this->getSumFile()->getFileName()).GetPath(wxPATH_GET_VOLUME)); 01351 if ((fs = wxCGetFileLength(fn.GetFullPath())) != static_cast<wxCOff_t>(wxInvalidOffset)) 01352 total += static_cast<double>(fs); 01353 01354 item = this->GetNextItem(item, wxLIST_NEXT_ALL, state); 01355 } 01356 01357 // Check the checksums 01358 Checksum* c = sumFile->getChecksumCalculator(); // checksum calculator 01359 ChecksumFileCalculator::State retState; // state returned by the checksum' calculator. 01360 bool cont = true; // continue ? 01361 01362 // Show the progress dialog 01363 ChecksumProgress progressUpdater(_("Checking %s\n%s on %s read."), _("Checking the files"), this, total); 01364 ChecksumFileCalculator cfc(c, &progressUpdater); 01365 item = this->GetNextItem(-1, wxLIST_NEXT_ALL, state); 01366 while (item != -1 && cont) 01367 { 01368 // Get the name of the next file to check. 01369 d = this->getSumFile()->getChecksumData(this->GetItemData(item)); 01370 fn = d.getFileName(); 01371 if (!fn.IsAbsolute()) 01372 fn.MakeAbsolute(wxFileName(this->getSumFile()->getFileName()).GetPath(wxPATH_GET_VOLUME)); 01373 01374 // Check the file. 01375 progressUpdater.setFileName(fn.GetFullName()); 01376 retState = cfc.check(fn.GetFullPath(), d.getChecksum()); 01377 01378 switch (retState) 01379 { 01380 case ChecksumFileCalculator::Ok : // Checksum has been calculated (and corresponds for the check method). 01381 this->setChecksumState(item, ChecksumData::Verified, _("OK")); 01382 break; 01383 01384 case ChecksumFileCalculator::Invalid : // Checksum has been verified and not corresponds. 01385 this->setChecksumState(item, ChecksumData::Invalid, _("Checksums differ")); 01386 break; 01387 01388 case ChecksumFileCalculator::ReadError : // Error while reading the stream. 01389 this->setChecksumState(item, ChecksumData::NotFound, _("Error while reading the file")); 01390 break; 01391 01392 case ChecksumFileCalculator::FileNotFound : // The file has been not found. 01393 this->setChecksumState(item, ChecksumData::NotFound, _("File not found")); 01394 break; 01395 01396 case ChecksumFileCalculator::CantOpenFile : // Can't open the stream. 01397 this->setChecksumState(item, ChecksumData::NotFound, _("File cannot be open")); 01398 break; 01399 01400 case ChecksumFileCalculator::CanceledByUser : // User has canceled the calculation. 01401 cont = false; 01402 break; 01403 } 01404 01405 item = this->GetNextItem(item, wxLIST_NEXT_ALL, state); 01406 } 01407 delete c; 01408 progressUpdater.finished(); 01409 01410 // Sort the list 01411 sort(); 01412 01413 // Display the result 01414 if (cont && AppPrefs::get()->readBool(prGUI_DLG_SUMUP_CHECK)) 01415 ::wxMessageBox(this->sumUpStates(), _("Checking checksums"), wxOK | wxICON_INFORMATION); 01416 01417 // Update the main dialog status bar 01418 wxCommandEvent event(EVENT_UPDATE_SUMS_FRAME_STATUSBAR_COMMAND); 01419 event.SetString(this->sumUpStates(this->GetSelectedItemCount() != 0)); 01420 event.SetInt(0); 01421 this->GetParent()->ProcessEvent(event); 01422 } 01423 //--------------------------------------------------------------------------- 01424 01425 01426 /** 01427 * Recomputes the checksums. 01428 */ 01429 void ChecksumsListView::recompute() 01430 { 01431 if (this->getSumFile() == NULL || this->GetSelectedItemCount() == 0) 01432 return; // no file is open or no file is selected 01433 01434 wxLogNull logNo; // No log 01435 ChecksumData d; // a checksum data 01436 wxFileName fn; // name of the current file 01437 wxCOff_t fs; // rest of the file size to read 01438 BytesDisplayer total; // total of bytes to process 01439 01440 // Get the number of bytes to read. 01441 long item = this->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01442 while (item != -1) 01443 { 01444 d = this->getSumFile()->getChecksumData(this->GetItemData(item)); 01445 fn = d.getFileName(); 01446 if (!fn.IsAbsolute()) 01447 fn.MakeAbsolute(wxFileName(this->getSumFile()->getFileName()).GetPath(wxPATH_GET_VOLUME)); 01448 if ((fs = wxCGetFileLength(fn.GetFullPath())) != static_cast<wxCOff_t>(wxInvalidOffset)) 01449 total += static_cast<double>(fs); 01450 01451 item = this->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01452 } 01453 01454 // Recompute the checksums 01455 Checksum* c = sumFile->getChecksumCalculator(); // checksum calculator 01456 ChecksumFileCalculator::State retState; // state returned by the checksum' calculator. 01457 wxString calcSumValue; // Calculated checksum's value. 01458 bool cont = true; // continue ? 01459 01460 // Show the progress dialog 01461 ChecksumProgress progressUpdater(_("Recomputing the checkum of %s\n%s on %s read."), _("Recomputing the checksums"), this, total); 01462 ChecksumFileCalculator cfc(c, &progressUpdater); 01463 item = this->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01464 while (item != -1 && cont) 01465 { 01466 d = this->getSumFile()->getChecksumData(this->GetItemData(item)); 01467 fn = d.getFileName(); 01468 if (!fn.IsAbsolute()) 01469 fn.MakeAbsolute(wxFileName(this->getSumFile()->getFileName()).GetPath(wxPATH_GET_VOLUME)); 01470 01471 // Recompute the checksum. 01472 progressUpdater.setFileName(fn.GetFullName()); 01473 retState = cfc.calculate(fn.GetFullPath(), calcSumValue); 01474 01475 switch (retState) 01476 { 01477 case ChecksumFileCalculator::Ok : // Checksum has been calculated (and corresponds for the check method). 01478 this->setChecksumState(item, ChecksumData::Verified, _("OK")); 01479 if (calcSumValue.CmpNoCase(d.getChecksum()) != 0) 01480 // changes the checksum value 01481 { 01482 ChecksumData cd = this->getSumFile()->getChecksumData(this->GetItemData(item)); 01483 cd.setChecksum(calcSumValue); 01484 this->getSumFile()->setChecksumData(this->GetItemData(item), cd); 01485 this->setChecksum(item, _("OK")); 01486 } 01487 break; 01488 01489 case ChecksumFileCalculator::ReadError : // Error while reading the stream. 01490 this->setChecksumState(item, ChecksumData::NotFound, _("Error while reading the file")); 01491 break; 01492 01493 case ChecksumFileCalculator::FileNotFound : // The file has been not found. 01494 this->setChecksumState(item, ChecksumData::NotFound, _("File not found")); 01495 break; 01496 01497 case ChecksumFileCalculator::CantOpenFile : // Can't open the stream. 01498 this->setChecksumState(item, ChecksumData::NotFound, _("File cannot be open")); 01499 break; 01500 01501 case ChecksumFileCalculator::CanceledByUser : // User has canceled the calculation. 01502 cont = false; 01503 break; 01504 } 01505 01506 item = this->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01507 } 01508 delete c; 01509 progressUpdater.finished(); 01510 01511 // Sort the list 01512 sort(); 01513 } 01514 //--------------------------------------------------------------------------- 01515 01516 01517 /** 01518 * Reformats the list. 01519 */ 01520 void ChecksumsListView::reformat() 01521 { 01522 reformat(NULL); 01523 } 01524 //--------------------------------------------------------------------------- 01525 01526 01527 #if defined(__WXMSW__) 01528 /** 01529 * Event handler for the context menu demand. 01530 * 01531 * @param event event parameters. 01532 */ 01533 void ChecksumsListView::OnContextMenu(wxContextMenuEvent& event) 01534 { 01535 ShowContextMenu(ScreenToClient(event.GetPosition())); 01536 } 01537 //--------------------------------------------------------------------------- 01538 #else 01539 /** 01540 * Event handler for the context menu demand. 01541 * 01542 * @param event event parameters. 01543 */ 01544 void ChecksumsListView::OnRightUp(wxMouseEvent& event) 01545 { 01546 ShowContextMenu(event.GetPosition()); 01547 } 01548 //--------------------------------------------------------------------------- 01549 #endif // defined(__WXMSW__) 01550 01551 01552 /** 01553 * Shows the context menu. 01554 * 01555 * @param p Position of the context menu. 01556 */ 01557 void ChecksumsListView::ShowContextMenu(const wxPoint& p) 01558 { 01559 if (sumFile != NULL) 01560 { 01561 // Initializes the popup-menu 01562 wxMenu pmnFonds; 01563 wxMenuItem* itpFilesAdd = new wxMenuItem(&pmnFonds, ITP_FILESADD, wxString(_("&Add files..."))); 01564 itpFilesAdd->SetBitmap(wxBitmap(hi16_action_fileadd_xpm)); 01565 wxMenuItem* itpDirectoriesAdd = new wxMenuItem(&pmnFonds, ITP_DIRECTORIESADD, wxString(_("A&dd directories..."))); 01566 itpDirectoriesAdd->SetBitmap(wxBitmap(hi16_action_directoryadd_xpm)); 01567 wxMenuItem* itpAddMatchingFiles = new wxMenuItem(&pmnFonds, ITP_ADDMATCHINGFILES, wxString(_("Add &matching files..."))); 01568 itpAddMatchingFiles->SetBitmap(wxBitmap(hi16_action_addmatchingfiles_xpm)); 01569 wxMenuItem* itpRemove = new wxMenuItem(&pmnFonds, ITP_REMOVE, wxString(_("&Remove"))); 01570 itpRemove->SetBitmap(wxBitmap(hi16_action_fileremove_xpm)); 01571 01572 pmnFonds.Append(itpFilesAdd); 01573 pmnFonds.Append(itpDirectoriesAdd); 01574 pmnFonds.Append(itpAddMatchingFiles); 01575 pmnFonds.Append(itpRemove); 01576 01577 // Check for the remove menu 01578 if (this->GetSelectedItemCount() == 0) 01579 itpRemove->Enable(false); 01580 01581 PopupMenu(&pmnFonds, p); 01582 } 01583 } 01584 //--------------------------------------------------------------------------- 01585 01586 01587 /** 01588 * Event handler a pop-up menu click on 'Add files...'. 01589 * 01590 * @param event event parameters. 01591 */ 01592 void ChecksumsListView::itpAddFilesClick(wxCommandEvent& event) 01593 { 01594 this->selectFilesToAdd(); 01595 } 01596 //--------------------------------------------------------------------------- 01597 01598 01599 /** 01600 * Event handler a pop-up menu click on 'Add directories...'. 01601 * 01602 * @param event event parameters. 01603 */ 01604 void ChecksumsListView::itpAddDirectoriesClick(wxCommandEvent& event) 01605 { 01606 this->selectDirectoriesToAdd(); 01607 } 01608 //--------------------------------------------------------------------------- 01609 01610 01611 /** 01612 * Event handler a pop-up menu click on 'Add matching files...'. 01613 * 01614 * @param event event parameters. 01615 */ 01616 void ChecksumsListView::itpAddMatchingFilesClick(wxCommandEvent& event) 01617 { 01618 this->selectMatchingFilesToAdd(); 01619 } 01620 //--------------------------------------------------------------------------- 01621 01622 01623 /** 01624 * Event handler a pop-up menu click on 'Remove'. 01625 * 01626 * @param event event parameters. 01627 */ 01628 void ChecksumsListView::itpRemoveClick(wxCommandEvent& event) 01629 { 01630 this->removeSelectedChecksums(); 01631 } 01632 //--------------------------------------------------------------------------- 01633 01634 01635 /** 01636 * Processes a drop of files on the list. 01637 * 01638 * @param event event parameters. 01639 */ 01640 void ChecksumsListView::DnDFiles(wxCommandEvent& event) 01641 { 01642 // Get the files list 01643 wxArrayString* f = reinterpret_cast<wxArrayString*>(event.GetClientData()); 01644 01645 // Add the files in the list or open a file 01646 if (f != NULL) 01647 { 01648 if (this->getSumFile() == NULL) 01649 { 01650 size_t i = 0; 01651 while (i < f->GetCount() && !(this->openChecksumFile((*f)[i]))) 01652 i++; 01653 } 01654 else // add the files in the list 01655 { 01656 this->addFiles(*f); 01657 01658 // Update the main dialog title 01659 wxCommandEvent event(EVENT_UPDATE_SUMS_FRAME_TITLE_COMMAND); 01660 this->GetParent()->ProcessEvent(event); 01661 } 01662 } 01663 01664 // Delete the array created by DndCheckSumListView::OnDropFiles() 01665 if (f != NULL) 01666 delete f; 01667 } 01668 //--------------------------------------------------------------------------- 01669 01670 01671 /** 01672 * Gets the columns. 01673 * 01674 * @param cols Array that will contain the columns. 01675 */ 01676 void ChecksumsListView::getColumns(Columns cols[LVW_SUMS_NBCOLS]) 01677 { 01678 for (int i = 0; i < LVW_SUMS_NBCOLS; i++) 01679 cols[i] = columns[i]; 01680 } 01681 //--------------------------------------------------------------------------- 01682 01683 01684 /** 01685 * Sets the columns. 01686 * 01687 * @param newColumns The new columns order. 01688 * @return <CODE>true</CODE> if the order of the columns has been changed, 01689 * <CODE>false</CODE> otherwise. 01690 */ 01691 bool ChecksumsListView::setColumns(Columns newColumns[LVW_SUMS_NBCOLS]) 01692 { 01693 int i = 0; 01694 int j; 01695 bool OK = true; 01696 bool hasChanged = false; 01697 Columns oldColumns[LVW_SUMS_NBCOLS]; 01698 01699 // Checks values of the given array. 01700 while (OK && i < LVW_SUMS_NBCOLS) 01701 { 01702 if (newColumns[i] != FILE_NAME && newColumns[i] != DIRECTORY && 01703 newColumns[i] != CHECKSUM_VALUE && newColumns[i] != STATE) 01704 OK = false; 01705 01706 i++; 01707 } 01708 01709 // Checks that all the values are unique 01710 i = 0; 01711 while (OK && i < LVW_SUMS_NBCOLS) 01712 { 01713 j = i + 1; 01714 while (j < LVW_SUMS_NBCOLS) 01715 { 01716 if (newColumns[i] == newColumns[j]) 01717 OK = false; 01718 j++; 01719 } 01720 i++; 01721 } 01722 01723 // Copy the array 01724 if (OK) 01725 for (i = 0; i < LVW_SUMS_NBCOLS; i++) 01726 { 01727 oldColumns[i] = columns[i]; 01728 if (columns[i] != newColumns[i]) 01729 { 01730 hasChanged = true; 01731 columns[i] = newColumns[i]; 01732 } 01733 } 01734 01735 // Reformat the list 01736 if (OK && hasChanged) 01737 { 01738 reformat(oldColumns); 01739 return true; 01740 } 01741 return false; 01742 } 01743 //--------------------------------------------------------------------------- 01744 01745 01746 /** 01747 * Reformats the list. 01748 * 01749 * @param oldColumns Old order of the columns. <CODE>NULL</CODE> if the order 01750 * has not changed. 01751 */ 01752 void ChecksumsListView::reformat(Columns oldColumns[LVW_SUMS_NBCOLS]) 01753 { 01754 wxBusyCursor wait; 01755 this->Freeze(); 01756 01757 // Sets the text of the headers of the columns 01758 if (oldColumns != NULL) 01759 { 01760 wxListItem colitem; 01761 colitem.SetMask(wxLIST_MASK_TEXT); 01762 for (int i = 0; i < LVW_SUMS_NBCOLS; i++) 01763 { 01764 this->GetColumn(i, colitem); 01765 colitem.SetText(getColumnName(columns[i])); 01766 this->SetColumn(i, colitem); 01767 } 01768 } 01769 01770 wxString state; 01771 int i; 01772 wxListItem li; 01773 Columns* refTab = (oldColumns == NULL) ? columns : oldColumns; 01774 01775 // Find the column of the state 01776 int stateCol = -1; 01777 for (i = 0; (i < LVW_SUMS_NBCOLS) && (stateCol == -1); i++) 01778 if (refTab[i] == STATE) 01779 stateCol = i; 01780 01781 li.SetMask(wxLIST_MASK_TEXT); 01782 long item = this->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 01783 while (item != -1) 01784 { 01785 // Get necessary data. 01786 li.SetId(item); 01787 li.SetColumn(stateCol); 01788 this->GetItem(li); 01789 state = li.GetText(); 01790 01791 // Sets the item data 01792 setChecksum(item, state); 01793 01794 item = this->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 01795 } 01796 01797 this->Thaw(); 01798 01799 // Sort the list 01800 sort(); 01801 } 01802 //--------------------------------------------------------------------------- 01803 01804 01805 /** 01806 * Gets the name of a column. 01807 * 01808 * @param col The column which the name will be returned. 01809 * @return The name of a column. 01810 */ 01811 wxString ChecksumsListView::getColumnName(const Columns col) 01812 { 01813 wxString res; 01814 switch (col) 01815 { 01816 case FILE_NAME : 01817 res = _("File name"); 01818 break; 01819 case DIRECTORY : 01820 res = _("Directory"); 01821 break; 01822 case CHECKSUM_VALUE : 01823 res = _("Checksum value"); 01824 break; 01825 case STATE : 01826 res = _("State"); 01827 break; 01828 default : 01829 res = wxT(""); 01830 } 01831 return res; 01832 } 01833 //--------------------------------------------------------------------------- 01834 01835 01836 BEGIN_EVENT_TABLE(ChecksumsListView, wxListView) 01837 EVT_MENU(ITP_FILESADD, ChecksumsListView::itpAddFilesClick) 01838 EVT_MENU(ITP_DIRECTORIESADD, ChecksumsListView::itpAddDirectoriesClick) 01839 EVT_MENU(ITP_ADDMATCHINGFILES, ChecksumsListView::itpAddMatchingFilesClick) 01840 EVT_MENU(ITP_REMOVE, ChecksumsListView::itpRemoveClick) 01841 EVT_CUSTOM(EVENT_DNDFILES_COMMAND, -1, ChecksumsListView::DnDFiles) 01842 01843 #if defined(__WXMSW__) 01844 EVT_CONTEXT_MENU(ChecksumsListView::OnContextMenu) 01845 #else 01846 EVT_RIGHT_UP(ChecksumsListView::OnRightUp) 01847 #endif // defined(__WXMSW__) 01848 END_EVENT_TABLE() 01849 //---------------------------------------------------------------------------

Generated on Sun May 30 13:37:45 2004 for wxChecksums by doxygen 1.3.7