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

dlgAddMatchFiles.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 dlgAddMatchFiles.cpp 00022 * Dialog for adding files by pattern matching. 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 #include <cstring> // for memcpy 00040 00041 #include <wx/config.h> 00042 #include <wx/filename.h> 00043 #include <wx/spinctrl.h> 00044 #include <wx/tokenzr.h> 00045 #include <wx/txtstrm.h> 00046 #include <wx/wfstream.h> 00047 00048 #include "dlgAddMatchFiles.hpp" 00049 #include "appprefs.hpp" 00050 #include "bytedisp.hpp" 00051 #include "comdefs.hpp" 00052 #include "fdftlmk.hpp" 00053 #include "fileutil.hpp" 00054 #include "slstview.hpp" 00055 #include "utils.hpp" 00056 00057 #include "compat.hpp" 00058 //--------------------------------------------------------------------------- 00059 00060 00061 /// The C++ standard namespace. 00062 using namespace std; 00063 00064 00065 //########################################################################### 00066 // The matching pattern 00067 //########################################################################### 00068 00069 00070 /** 00071 * Constructor. 00072 * 00073 * @param dir The directory. 00074 * @param pat The pattern. 00075 * @param dep The depth. 00076 */ 00077 dlgAddMatchFiles::MatchPattern::MatchPattern(const wxString& dir, 00078 const wxString& pat, const int dep) 00079 { 00080 setDirectory(dir); 00081 setPattern(pat); 00082 setDepth(dep); 00083 } 00084 //--------------------------------------------------------------------------- 00085 00086 00087 /** 00088 * Clones the source instance in this instance. 00089 * 00090 * @param source Source instance. 00091 */ 00092 void dlgAddMatchFiles::MatchPattern::clone(const MatchPattern& source) 00093 { 00094 if (this != &source) 00095 { 00096 this->directory = source.directory; 00097 this->pattern = source.pattern; 00098 this->depth = source.depth; 00099 } 00100 } 00101 //--------------------------------------------------------------------------- 00102 00103 00104 /** 00105 * Assignment operator. 00106 * 00107 * @param source Source instance. 00108 * @return A reference on the instance. 00109 */ 00110 dlgAddMatchFiles::MatchPattern& dlgAddMatchFiles::MatchPattern::operator=(const MatchPattern& source) 00111 { 00112 clone(source); 00113 return *this; 00114 } 00115 //--------------------------------------------------------------------------- 00116 00117 00118 /** 00119 * Gets the patterns. 00120 * 00121 * @return The patterns in a array of strings. 00122 */ 00123 wxArrayString dlgAddMatchFiles::MatchPattern::getPatterns() const 00124 { 00125 wxArrayString res; 00126 00127 wxStringTokenizer tkz(getPattern(), wxT(";"), wxTOKEN_STRTOK); 00128 while (tkz.HasMoreTokens()) 00129 res.Add(tkz.GetNextToken()); 00130 00131 return res; 00132 } 00133 //--------------------------------------------------------------------------- 00134 00135 00136 /** 00137 * Adds the given patterns to this pattern. 00138 * 00139 * @param patterns The patterns to add. 00140 */ 00141 void dlgAddMatchFiles::MatchPattern::addPatterns(const wxString& patterns) 00142 { 00143 wxArrayString pats; 00144 wxArrayString mine = getPatterns(); 00145 00146 // Tokenizes the given patterns. 00147 wxStringTokenizer tkz(patterns, wxT(";"), wxTOKEN_STRTOK); 00148 while (tkz.HasMoreTokens()) 00149 pats.Add(tkz.GetNextToken()); 00150 00151 // Merging 00152 wxString newPattern = getPattern(); 00153 size_t j; 00154 bool found; 00155 for (size_t i = 0; i < pats.GetCount(); i++) 00156 { 00157 j = 0; 00158 found = false; 00159 while (!found && j < mine.GetCount()) 00160 { 00161 if (::compareFileName(pats[i], mine[j]) == 0) 00162 found = true; 00163 j++; 00164 } 00165 if (!found) 00166 { 00167 if (mine.GetCount() > 0) 00168 newPattern += wxT(';'); 00169 newPattern += pats[i]; 00170 mine.Add(pats[i]); 00171 } 00172 } 00173 00174 setPattern(newPattern); 00175 } 00176 //--------------------------------------------------------------------------- 00177 00178 00179 /** 00180 * Remove the given patterns from this pattern. 00181 * 00182 * @param patterns Patterns to remove. 00183 */ 00184 void dlgAddMatchFiles::MatchPattern::removePatterns(const wxString& patterns) 00185 { 00186 wxArrayString pats; 00187 wxArrayString mine = getPatterns(); 00188 00189 // Tokenizes the given patterns. 00190 wxStringTokenizer tkz(patterns, wxT(";"), wxTOKEN_STRTOK); 00191 while (tkz.HasMoreTokens()) 00192 pats.Add(tkz.GetNextToken()); 00193 00194 // Removing to patterns 00195 size_t j; 00196 bool found; 00197 for (size_t i = 0; i < pats.GetCount(); i++) 00198 { 00199 j = 0; 00200 found = false; 00201 while (!found && j < mine.GetCount()) 00202 { 00203 if (::compareFileName(pats[i], mine[j]) == 0) 00204 { 00205 found = true; 00206 mine.Remove(j); 00207 } 00208 else 00209 j++; 00210 } 00211 } 00212 00213 // Creating the new pattern 00214 wxString newPattern; 00215 for (j = 0; j < mine.GetCount(); j++) 00216 { 00217 if (j > 0) 00218 newPattern += wxT(';'); 00219 newPattern += mine[j]; 00220 } 00221 00222 setPattern(newPattern); 00223 } 00224 //--------------------------------------------------------------------------- 00225 00226 00227 /** 00228 * Indicates if the pattern includes all the given patterns. 00229 * 00230 * @param patterns Patterns to check if they are in this pattern. 00231 * @return <CODE>true</CODE> if all the given patterns are in this pattern. 00232 * <CODE>false</CODE> otherwise. 00233 */ 00234 bool dlgAddMatchFiles::MatchPattern::isIncludingAllPatterns(const wxString& patterns) const 00235 { 00236 wxArrayString pats; 00237 wxArrayString mine = getPatterns(); 00238 00239 // Tokenizes the given patterns. 00240 wxStringTokenizer tkz(patterns, wxT(";"), wxTOKEN_STRTOK); 00241 while (tkz.HasMoreTokens()) 00242 pats.Add(tkz.GetNextToken()); 00243 00244 bool found = true; 00245 size_t i = 0, j; 00246 while (found && i < pats.GetCount()) 00247 { 00248 found = false; 00249 j = 0; 00250 while (!found && j < mine.GetCount()) 00251 { 00252 if (::compareFileName(pats[i], mine[j]) == 0) 00253 found = true; 00254 j++; 00255 } 00256 00257 i++; 00258 } 00259 00260 return found; 00261 } 00262 //--------------------------------------------------------------------------- 00263 00264 00265 /** 00266 * Compare the depths of this pattern and the given one. 00267 * 00268 * A depth of <CODE>0</CODE> is infinite (i.e. bigger that any other depth). 00269 * 00270 * @param cmp Pattern to compare the depth. 00271 * @return A number < 0 if <I>the depth of this pattern</I> < <I>the depth of 00272 * <CODE>cmp</CODE></I>, 0 if <I>the depth of this pattern</I> == 00273 * <I>the depth of <CODE>cmp</CODE></I>, > 0 if 00274 * <I>the depth of this pattern</I> > 00275 * <I>the depth of <CODE>cmp</CODE></I>. 00276 */ 00277 int dlgAddMatchFiles::MatchPattern::compareDepth(const MatchPattern& cmp) const 00278 { 00279 if (this->getDepth() == 0 && cmp.getDepth() == 0) 00280 return 0; 00281 else if (this->getDepth() == 0) 00282 return 1; 00283 else if (cmp.getDepth() == 0) 00284 return -1; 00285 else 00286 return this->getDepth() - cmp.getDepth(); 00287 } 00288 //--------------------------------------------------------------------------- 00289 00290 00291 /** 00292 * Compare two matching patterns. 00293 * 00294 * The matching patterns are equals if: 00295 * - They have the same depth. 00296 * - They have the same directory 00297 * - The first pattern includes all the patterns of the second. 00298 * - The second pattern includes all the patterns of the first. 00299 * 00300 * @param cmp Matching pattern to compare with this matching pattern. 00301 * @return <CODE>true</CODE> if the patterns are equals, <CODE>false</CODE> 00302 * otherwise. 00303 */ 00304 bool dlgAddMatchFiles::MatchPattern::operator==(const MatchPattern& cmp) const 00305 { 00306 return (this->compareDepth(cmp) == 0 && 00307 ::compareFileName(this->getDirectory(), cmp.getDirectory()) == 0 && 00308 this->isIncludingAllPatterns(cmp.getPattern()) && 00309 cmp.isIncludingAllPatterns(this->getPattern())); 00310 } 00311 //--------------------------------------------------------------------------- 00312 00313 00314 //########################################################################### 00315 // Array of matching patterns 00316 //########################################################################### 00317 00318 const size_t dlgAddMatchFiles::ArrayMatchPattern::ALLOC_NEW = 10; 00319 00320 /** 00321 * Default constructor. 00322 */ 00323 dlgAddMatchFiles::ArrayMatchPattern::ArrayMatchPattern() 00324 { 00325 patterns = NULL; 00326 allocated = 0; 00327 used = 0; 00328 alloc(ALLOC_NEW); 00329 } 00330 //--------------------------------------------------------------------------- 00331 00332 00333 /** 00334 * Constructor with an amount of allocated elements. 00335 * 00336 * @param count Number of patterns to allocate. 00337 */ 00338 dlgAddMatchFiles::ArrayMatchPattern::ArrayMatchPattern(size_t count) 00339 { 00340 patterns = NULL; 00341 allocated = 0; 00342 used = 0; 00343 alloc(count); 00344 } 00345 //--------------------------------------------------------------------------- 00346 00347 00348 /** 00349 * Clones the source instance in this instance. 00350 * 00351 * @param source Source instance. 00352 */ 00353 void dlgAddMatchFiles::ArrayMatchPattern::clone(const ArrayMatchPattern& source) 00354 { 00355 if (this != &source) 00356 { 00357 // Delete the current array. 00358 clear(); 00359 alloc(source.allocated); 00360 for (size_t i = 0; i < source.used; i++) 00361 patterns[i] = new MatchPattern(*(source.patterns[i])); 00362 this->used = source.used; 00363 } 00364 } 00365 //--------------------------------------------------------------------------- 00366 00367 00368 /** 00369 * Copy constructor. 00370 * 00371 * @param source Source instance. 00372 */ 00373 dlgAddMatchFiles::ArrayMatchPattern::ArrayMatchPattern(const ArrayMatchPattern& source) 00374 { 00375 patterns = NULL; 00376 allocated = 0; 00377 used = 0; 00378 clone(source); 00379 } 00380 //--------------------------------------------------------------------------- 00381 00382 00383 /** 00384 * Assignment operator. 00385 * 00386 * @param source Source instance. 00387 * @return A reference on the instance. 00388 */ 00389 dlgAddMatchFiles::ArrayMatchPattern& dlgAddMatchFiles::ArrayMatchPattern::operator=(const ArrayMatchPattern& source) 00390 { 00391 clone(source); 00392 return *this; 00393 } 00394 //--------------------------------------------------------------------------- 00395 00396 00397 /** 00398 * Destructor. 00399 */ 00400 dlgAddMatchFiles::ArrayMatchPattern::~ArrayMatchPattern() 00401 { 00402 clear(); 00403 } 00404 //--------------------------------------------------------------------------- 00405 00406 00407 /** 00408 * Adds a pattern to the array. 00409 * 00410 * - The pattern is added if there is no other pattern with the same directory 00411 * and same patterns and with a bigger depth. 00412 * - If a pattern is found with the same directory and the same patterns 00413 * (including) and a smallest depth, the depth of the existing pattern is 00414 * changed. 00415 * - If a pattern have the same directory and the same depth, the patterns 00416 * are merged. 00417 * 00418 * @param pattern Pattern to add. 00419 */ 00420 void dlgAddMatchFiles::ArrayMatchPattern::add(MatchPattern pattern) 00421 { 00422 bool found = false; 00423 size_t i = 0, l = getCount(); 00424 while (!found && i < l) 00425 { 00426 if (::compareFileName(pattern.getDirectory(), patterns[i]->getDirectory()) == 0) 00427 // The directories are the same, checking for (see above) 00428 if (patterns[i]->compareDepth(pattern) == 0 || 00429 (patterns[i]->compareDepth(pattern) >= 0 && 00430 patterns[i]->isIncludingAllPatterns(pattern.getPattern()))) 00431 // Merging the patterns. 00432 { 00433 patterns[i]->addPatterns(pattern.getPattern()); 00434 found = true; // don't add pattern to the array. 00435 } 00436 else if (patterns[i]->compareDepth(pattern) > 0) 00437 { 00438 pattern.removePatterns(patterns[i]->getPattern()); 00439 if (pattern.getPattern().IsEmpty()) 00440 // the pattern to add is now empty, don't add it to the array. 00441 found = true; 00442 } 00443 else if (patterns[i]->compareDepth(pattern) < 0) 00444 { 00445 patterns[i]->removePatterns(pattern.getPattern()); 00446 if (patterns[i]->getPattern().IsEmpty()) 00447 // adding the pattern at this position. 00448 { 00449 *(patterns[i]) = pattern; 00450 found = true; 00451 } 00452 } 00453 00454 i++; 00455 } 00456 00457 if (!found) 00458 // Adding the matching pattern to the array. 00459 { 00460 if (used == allocated) 00461 alloc(allocated + ALLOC_NEW); 00462 patterns[used] = new MatchPattern(pattern); 00463 used++; 00464 } 00465 } 00466 //--------------------------------------------------------------------------- 00467 00468 00469 /** 00470 * Preallocates memory for a given number of patterns. 00471 * 00472 * @param count Number of patterns to allocate. 00473 */ 00474 void dlgAddMatchFiles::ArrayMatchPattern::alloc(size_t count) 00475 { 00476 if (count <= allocated) 00477 // Do nothing, bye. 00478 return; 00479 00480 // Allocates a new array. 00481 pMatchPattern* pPatterns = new pMatchPattern[count]; 00482 allocated = count; 00483 00484 if (patterns == NULL) 00485 patterns = pPatterns; 00486 else // copy and delete the old array 00487 { 00488 // Copy only the used pointers, the rest is useless. 00489 memcpy(pPatterns, patterns, sizeof(pMatchPattern) * used); 00490 delete[] patterns; 00491 patterns = pPatterns; 00492 } 00493 } 00494 //--------------------------------------------------------------------------- 00495 00496 00497 /** 00498 * Empties the array. 00499 */ 00500 void dlgAddMatchFiles::ArrayMatchPattern::clear() 00501 { 00502 if (patterns != NULL) 00503 { 00504 // Deletes the elements of the array. 00505 for (size_t i = 0; i < used; i++) 00506 delete patterns[i]; 00507 00508 // Delete the array. 00509 delete[] patterns; 00510 patterns = NULL; 00511 } 00512 00513 // Sets the number of allocated elements and the number of used elements. 00514 allocated = 0; 00515 used = 0; 00516 } 00517 //--------------------------------------------------------------------------- 00518 00519 00520 /** 00521 * Gets the number of patterns in the array. 00522 * 00523 * @return The number of patterns in the array. 00524 */ 00525 size_t dlgAddMatchFiles::ArrayMatchPattern::getCount() const 00526 { 00527 return used; 00528 } 00529 //--------------------------------------------------------------------------- 00530 00531 /** 00532 * Gets the pattern at the given index. 00533 * 00534 * If the index is out of bounds, nothing special is done (and the program 00535 * will surely fail with a segmentation fault). 00536 * 00537 * @param index Index of the item to get. 00538 * @return A reference on the matching pattern. 00539 */ 00540 dlgAddMatchFiles::MatchPattern& dlgAddMatchFiles::ArrayMatchPattern::item(size_t index) const 00541 { 00542 return *(patterns[index]); 00543 } 00544 //--------------------------------------------------------------------------- 00545 00546 00547 /** 00548 * Gets the pattern at the given index. 00549 * 00550 * If the index is out of bounds, nothing special is done (and the program 00551 * will surely fail with a segmentation fault). 00552 * 00553 * @param index Index of the item to get. 00554 * @return A reference on the matching pattern. 00555 */ 00556 dlgAddMatchFiles::MatchPattern& dlgAddMatchFiles::ArrayMatchPattern::operator[](size_t index) const 00557 { 00558 return *(patterns[index]); 00559 } 00560 //--------------------------------------------------------------------------- 00561 00562 00563 00564 //########################################################################### 00565 // The list of patterns compare function 00566 //########################################################################### 00567 00568 /** 00569 * Function that compare two elements of the list of patterns of the multiple 00570 * check configuration dialog. 00571 * 00572 * @param item1 Data of the first item. This should be an unique identifier. 00573 * @param item2 Data of the second item. This should be an unique identifier. 00574 * @param sortData Adress of the instance of the 00575 * <CODE>wxSortableListView</CODE> that contains the data to 00576 * short. 00577 */ 00578 static int wxCALLBACK patternsListCmpFnct(long item1, long item2, long sortData) 00579 { 00580 // Get the ListView 00581 wxSortableListView* lv = wxDynamicCast(sortData, wxSortableListView); 00582 00583 // Can't get the listview -> no sort. 00584 if (lv == NULL) 00585 return item1 - item2; 00586 00587 // No sort. 00588 if (lv->GetSortOrder() == wxSortableListView::none) 00589 return item1 - item2; 00590 00591 // Get the strings for comparison 00592 wxListItem li1, li2; 00593 li1.SetMask(wxLIST_MASK_TEXT); 00594 li1.SetColumn(lv->GetColumnToSort()); 00595 li1.SetId(lv->FindItem(-1, item1)); 00596 lv->GetItem(li1); 00597 li2.SetMask(wxLIST_MASK_TEXT); 00598 li2.SetColumn(lv->GetColumnToSort()); 00599 li2.SetId(lv->FindItem(-1, item2)); 00600 lv->GetItem(li2); 00601 wxString s1 = li1.GetText(); 00602 wxString s2 = li2.GetText(); 00603 00604 // Compute the result to return 00605 int res; 00606 if (lv->GetColumnToSort() != 2) 00607 // Compare string (directory or patterns) 00608 { 00609 if (lv->GetSortOrder() == wxSortableListView::ascending) 00610 res = ::compareFileName(s1, s2); 00611 else 00612 res = ::compareFileName(s2, s1); 00613 } 00614 else // Compare integers (depth) 00615 { 00616 long i1, i2; 00617 s1.ToLong(&i1); 00618 s2.ToLong(&i2); 00619 res = (lv->GetSortOrder() == wxSortableListView::ascending) ? i1 - i2 : i2 -i1; 00620 } 00621 00622 return res; 00623 } 00624 //--------------------------------------------------------------------------- 00625 00626 00627 00628 //########################################################################### 00629 // A validator for the patterns' list 00630 //########################################################################### 00631 00632 /** 00633 * A validator for the patterns' list. 00634 * 00635 * Checks that the given list of file's names has one or more elements. 00636 * 00637 * If the list is empty, display a message. 00638 */ 00639 class dlgAddMatchFiles::PatternsListValidator : public wxValidator 00640 { 00641 protected: 00642 ArrayMatchPattern* value; ///< Adress of the array of strings where the value will be transfered. 00643 00644 // Clones the source instance in this instance. 00645 void clone(const PatternsListValidator& source); 00646 00647 // Returns the wxListView associated with the validator. 00648 wxSortableListView* GetSortableListView() const; 00649 00650 public: 00651 // Constructor. 00652 PatternsListValidator(ArrayMatchPattern* pValue); 00653 00654 // Copy constructor. 00655 PatternsListValidator(const PatternsListValidator& source); 00656 00657 // Assignment operator. 00658 PatternsListValidator& operator=(const PatternsListValidator& source); 00659 00660 // Returns a copy of the instance of the validator. 00661 virtual wxObject* Clone() const; 00662 00663 // Validates the value in the associated window. 00664 virtual bool Validate(wxWindow* parent); 00665 00666 // Transfers the value in the window to the validator. 00667 virtual bool TransferFromWindow(); 00668 00669 // Transfers the value associated with the validator to the window. 00670 virtual bool TransferToWindow(); 00671 }; 00672 //--------------------------------------------------------------------------- 00673 00674 00675 /** 00676 * Constructor. 00677 * 00678 * @param pValue Pointer on the array of strings where to value will be 00679 * transfered. 00680 */ 00681 dlgAddMatchFiles::PatternsListValidator::PatternsListValidator(ArrayMatchPattern* pValue) 00682 { 00683 value = pValue; 00684 } 00685 //--------------------------------------------------------------------------- 00686 00687 00688 /** 00689 * Clones the source instance in this instance. 00690 * 00691 * @param source Source instance. 00692 */ 00693 void dlgAddMatchFiles::PatternsListValidator::clone(const PatternsListValidator& source) 00694 { 00695 if (this != &source) 00696 { 00697 this->value = source.value; 00698 } 00699 } 00700 //--------------------------------------------------------------------------- 00701 00702 00703 /** 00704 * Copy constructor. 00705 * 00706 * @param source Source instance. 00707 */ 00708 dlgAddMatchFiles::PatternsListValidator::PatternsListValidator(const PatternsListValidator& source) 00709 { 00710 clone(source); 00711 } 00712 //--------------------------------------------------------------------------- 00713 00714 00715 /** 00716 * Assignment operator. 00717 * 00718 * @param source Source instance. 00719 * @return A reference on the instance. 00720 */ 00721 dlgAddMatchFiles::PatternsListValidator& dlgAddMatchFiles::PatternsListValidator::operator=(const PatternsListValidator& source) 00722 { 00723 clone(source); 00724 return *this; 00725 } 00726 //--------------------------------------------------------------------------- 00727 00728 00729 /** 00730 * Returns a copy of the instance of the validator. 00731 * 00732 * @return A copy of the instance of the validator. 00733 */ 00734 wxObject* dlgAddMatchFiles::PatternsListValidator::Clone() const 00735 { 00736 return new PatternsListValidator(*this); 00737 } 00738 //--------------------------------------------------------------------------- 00739 00740 00741 /** 00742 * Returns the <CODE>wxSortableListView</CODE> associated with the validator. 00743 * 00744 * @return The <CODE>wxSortableListView</CODE> associated with the validator or 00745 * <CODE>NULL</CODE> if the <CODE>wxSortableListView</CODE> associated with 00746 * the validator isn't a <CODE>wxSortableListView</CODE>. 00747 */ 00748 wxSortableListView* dlgAddMatchFiles::PatternsListValidator::GetSortableListView() const 00749 { 00750 wxWindow* win = GetWindow(); 00751 if (win == NULL) 00752 return NULL; 00753 if (!win->IsKindOf(CLASSINFO(wxSortableListView))) 00754 return NULL; 00755 00756 return wxDynamicCast(win, wxSortableListView); 00757 } 00758 //--------------------------------------------------------------------------- 00759 00760 00761 /** 00762 * Validates the value in the associated window. 00763 * 00764 * @param parent Parent window. 00765 */ 00766 bool dlgAddMatchFiles::PatternsListValidator::Validate(wxWindow* parent) 00767 { 00768 wxSortableListView* control = GetSortableListView(); 00769 if (control == NULL) 00770 return false; 00771 00772 if (control->GetItemCount() == 0) 00773 { 00774 ::wxMessageBox(_("Add a matching pattern at least."), _("Warning"), wxOK | wxICON_EXCLAMATION); 00775 return false; 00776 } 00777 else 00778 return true; 00779 } 00780 //--------------------------------------------------------------------------- 00781 00782 00783 /** 00784 * Transfers the value in the window to the validator. 00785 * 00786 * @return <CODE>true</CODE> on success, <CODE>false</CODE> otherwise. 00787 */ 00788 bool dlgAddMatchFiles::PatternsListValidator::TransferFromWindow() 00789 { 00790 wxSortableListView* control = GetSortableListView(); 00791 if (control == NULL || value == NULL) 00792 return false; 00793 else 00794 { 00795 wxString pattern, directory; 00796 long depth; 00797 wxListItem listItem; 00798 listItem.SetMask(wxLIST_MASK_TEXT); 00799 long item = control->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00800 while (item != -1) 00801 { 00802 // Read items info 00803 listItem.SetId(item); 00804 listItem.SetColumn(0); 00805 control->GetItem(listItem); 00806 directory = listItem.GetText(); 00807 listItem.SetColumn(1); 00808 control->GetItem(listItem); 00809 pattern = listItem.GetText(); 00810 listItem.SetColumn(2); 00811 control->GetItem(listItem); 00812 listItem.GetText().ToLong(&depth); 00813 value->add(MatchPattern(directory, pattern, depth)); 00814 00815 item = control->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00816 } 00817 00818 return true; 00819 } 00820 } 00821 //--------------------------------------------------------------------------- 00822 00823 00824 /** 00825 * Transfers the value associated with the validator to the window. 00826 * 00827 * return <CODE>true</CODE> on success, <CODE>false</CODE> otherwise. 00828 */ 00829 bool dlgAddMatchFiles::PatternsListValidator::TransferToWindow() 00830 { 00831 wxSortableListView* control = GetSortableListView(); 00832 if (control == NULL || value == NULL) 00833 return false; 00834 else 00835 { 00836 size_t s = value->getCount(); 00837 size_t i; 00838 wxListItem listItem; 00839 listItem.SetMask(wxLIST_MASK_TEXT); 00840 00841 for (i = 0; i < s; i++) 00842 { 00843 // Remove spaces at the beginning and the end of the pattern and directory. 00844 wxString directory = value->item(i).getDirectory().Strip(wxString::both); 00845 wxString patterns = value->item(i).getPattern().Strip(wxString::both); 00846 00847 // Checks the validity of the parameters 00848 if (directory.IsEmpty()) 00849 directory = wxT("."); 00850 if (patterns.IsEmpty()) 00851 patterns = wxT("*"); 00852 00853 // Remove the path separators at the end of the directory if needed 00854 while (!directory.IsEmpty() && directory.Last() == wxFileName::GetPathSeparator()) 00855 directory.RemoveLast(); 00856 00857 MatchPattern patternToAdd(directory, patterns, value->item(i).getDepth()); 00858 wxListItem listItem; 00859 listItem.SetMask(wxLIST_MASK_TEXT); 00860 MatchPattern p; 00861 long depth; 00862 00863 // Checks if the pattern isn't already is the list. 00864 long item = control->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00865 bool found = false; 00866 while (!found && item != -1) 00867 { 00868 listItem.SetId(item); 00869 listItem.SetColumn(0); 00870 control->GetItem(listItem); 00871 p.setDirectory(listItem.GetText()); 00872 listItem.SetColumn(1); 00873 control->GetItem(listItem); 00874 p.setPattern(listItem.GetText()); 00875 listItem.SetColumn(2); 00876 control->GetItem(listItem); 00877 listItem.GetText().ToLong(&depth); 00878 p.setDepth(depth); 00879 00880 if (patternToAdd == p) 00881 found = true; 00882 else 00883 item = control->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 00884 } 00885 if (!found) 00886 { 00887 long newItem = control->InsertItem(control->GetItemCount(), patternToAdd.getDirectory()); 00888 control->SetItem(newItem, 1, patternToAdd.getPattern()); 00889 control->SetItem(newItem, 2, wxString::Format(wxT("%d"), patternToAdd.getDepth())); 00890 control->SetItemData(newItem, getID()); 00891 } 00892 } 00893 control->SortItems(patternsListCmpFnct, reinterpret_cast<long>(control)); 00894 00895 return true; 00896 } 00897 } 00898 //--------------------------------------------------------------------------- 00899 00900 00901 00902 //########################################################################### 00903 // dlgAddMatchFiles methods 00904 //########################################################################### 00905 00906 IMPLEMENT_DYNAMIC_CLASS(dlgAddMatchFiles, wxDialog) 00907 00908 00909 // Static attributes of the dlgAddMatchFiles class. 00910 // Value for unique identifiers generation. 00911 long dlgAddMatchFiles::idGen = 0L; 00912 //--------------------------------------------------------------------------- 00913 00914 00915 /** 00916 * Creates a new dialog. 00917 */ 00918 dlgAddMatchFiles::dlgAddMatchFiles() : wxDialog() 00919 { 00920 matchPatterns = NULL; 00921 createControls(); 00922 setChecksumsFileName(wxFileName::GetCwd()); 00923 } 00924 //--------------------------------------------------------------------------- 00925 00926 00927 /** 00928 * Creates a new dialog. 00929 * 00930 * @param parent Parent of the dialog. 00931 * @param checksumsFileName Name of the checksums' file in which the matched 00932 * file will be added. 00933 */ 00934 dlgAddMatchFiles::dlgAddMatchFiles(wxWindow* parent, 00935 const wxString& checksumsFileName) : 00936 wxDialog(parent, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 00937 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) 00938 { 00939 matchPatterns = NULL; 00940 createControls(); 00941 00942 Fit(); 00943 00944 // Get the size of the window 00945 wxSize s; 00946 if (PreferenceValue::read(getConfigKey(prGUI_ADD_MATCH_FILES_WINDOW_SIZE), &s)) 00947 SetSize(s); 00948 00949 Centre(); 00950 00951 if (checksumsFileName.IsEmpty()) 00952 setChecksumsFileName(wxFileName::GetCwd()); 00953 else 00954 setChecksumsFileName(checksumsFileName); 00955 } 00956 //--------------------------------------------------------------------------- 00957 00958 00959 /** 00960 * Creates and initializes the controls of the dialog. 00961 */ 00962 void dlgAddMatchFiles::createControls() 00963 { 00964 // Creating a new array of matching patterns if necessary. 00965 if (matchPatterns == NULL) 00966 matchPatterns = new ArrayMatchPattern(); 00967 00968 // Creates the controls 00969 wxStaticBox* fraPatterns = new wxStaticBox(this, -1, _("List of the matc&hing patterns:")); 00970 lvwPatterns = new wxSortableListView(this, LVW_FILES, wxDefaultPosition, 00971 wxSize((this->GetParent()->GetSize().GetWidth() * 2) / 3, 00972 (this->GetParent()->GetSize().GetHeight() / 2)), 00973 wxLC_REPORT, PatternsListValidator(matchPatterns)); 00974 lvwPatterns->InsertColumn(0, _("Directory")); 00975 lvwPatterns->InsertColumn(1, _("Pattern")); 00976 lvwPatterns->InsertColumn(2, _("Depth")); 00977 00978 btnRemove = new wxButton(this, BTN_REMOVE, _("&Remove")); 00979 btnRemove->Disable(); 00980 wxButton* btnAddList = new wxButton(this, BTN_ADDLIST, _("Add li&st...")); 00981 wxButton* btnLoadList = new wxButton(this, BTN_LOADLIST, _("L&oad list...")); 00982 wxButton* btnSaveList = new wxButton(this, BTN_SAVELIST, _("Sa&ve list...")); 00983 const wxString rbxSortByChoices[] = { _("Directory"), _("Pattern"), _("Depth") }; 00984 rbxSortBy = new wxRadioBox(this, RBX_SORT_BY, _("Sort b&y:"), wxDefaultPosition, wxDefaultSize, 3, rbxSortByChoices, 1, wxRA_SPECIFY_COLS); 00985 const wxString rbxSortOrderChoices[] = { _("Ascending"), _("Descending"), _("Don't sort") }; 00986 rbxSortOrder = new wxRadioBox(this, RBX_SORT_ORDER, _("Sor&t order:"), wxDefaultPosition, wxDefaultSize, 3, rbxSortOrderChoices, 1, wxRA_SPECIFY_COLS); 00987 00988 wxStaticBox* fraAddingPattern = new wxStaticBox(this, -1, _("Add a mathing pattern to the li&st:")); 00989 wxStaticText* lblPattern = new wxStaticText(this, -1, _("Patter&n(s):")); 00990 cboPattern = new wxComboBox(this, CBO_PATTERN); 00991 wxStaticText* lblDirectory = new wxStaticText(this, -1, _("D&irectory:")); 00992 cboDirectory = new wxComboBox(this, CBO_DIRECTORY); 00993 wxButton* btnBrowse = new wxButton(this, BTN_BROWSE, _("&Browse...")); 00994 wxStaticText* lblDepth = new wxStaticText(this, -1, _("&Depth:")); 00995 spnDepth = new wxSpinCtrl(this, SPN_DEPTH, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS | wxSP_WRAP, 0, SHRT_MAX, 0); 00996 btnAddPattern = new wxButton(this, BTN_ADD_PATTERN, _("Add patt&ern")); 00997 00998 wxButton* btnAdd = new wxButton(this, BTN_ADD, _("&Add...")); 00999 btnAdd->SetDefault(); 01000 wxButton* btnCancel = new wxButton(this, wxID_CANCEL, _("Ca&ncel")); 01001 01002 01003 //------------------------------------------------------------------------- 01004 // Creates the dialog sizers 01005 01006 // Dialog sizer 01007 wxBoxSizer* dlgAddMatchFilesSizer2 = new wxBoxSizer(wxVERTICAL); 01008 this->SetSizer(dlgAddMatchFilesSizer2); 01009 wxBoxSizer* dlgAddMatchFilesSizer = new wxBoxSizer(wxVERTICAL); 01010 dlgAddMatchFilesSizer2->Add(dlgAddMatchFilesSizer, 1, wxALL | wxGROW, CONTROL_SPACE); 01011 01012 // List of patterns 01013 wxStaticBoxSizer* fraPatternsSizer2 = new wxStaticBoxSizer(fraPatterns, wxVERTICAL); 01014 dlgAddMatchFilesSizer->Add(fraPatternsSizer2, 1, wxGROW); 01015 wxBoxSizer* fraPatternsSizer = new wxBoxSizer(wxHORIZONTAL); 01016 fraPatternsSizer2->Add(fraPatternsSizer, 1, wxALL | wxGROW, CONTROL_SPACE / 2); 01017 01018 fraPatternsSizer->Add(lvwPatterns, 1, wxGROW); 01019 01020 wxBoxSizer* patternsListButtonsSizer = new wxBoxSizer(wxVERTICAL); 01021 patternsListButtonsSizer->Add(btnRemove, 0, wxGROW | wxTOP, CONTROL_SPACE); 01022 patternsListButtonsSizer->Add(btnAddList, 0, wxGROW | wxTOP, CONTROL_SPACE); 01023 patternsListButtonsSizer->Add(btnLoadList, 0, wxGROW | wxTOP, CONTROL_SPACE / 2); 01024 patternsListButtonsSizer->Add(btnSaveList, 0, wxGROW | wxTOP, CONTROL_SPACE / 2); 01025 patternsListButtonsSizer->Add(rbxSortBy, 0, wxGROW | wxTOP, CONTROL_SPACE); 01026 patternsListButtonsSizer->Add(rbxSortOrder, 0, wxGROW | wxTOP, CONTROL_SPACE / 2); 01027 fraPatternsSizer->Add(patternsListButtonsSizer, 0, wxLEFT | wxALIGN_TOP, CONTROL_SPACE); 01028 01029 // Add pattern section 01030 wxStaticBoxSizer* fraAddingPatternSizer2 = new wxStaticBoxSizer(fraAddingPattern, wxVERTICAL); 01031 dlgAddMatchFilesSizer->Add(fraAddingPatternSizer2, 0, wxGROW | wxTOP, CONTROL_SPACE); 01032 wxBoxSizer* fraAddingPatternSizer = new wxBoxSizer(wxVERTICAL); 01033 fraAddingPatternSizer2->Add(fraAddingPatternSizer, 0, wxALL | wxGROW, CONTROL_SPACE / 2); 01034 01035 wxFlexGridSizer* addPatternSizer = new wxFlexGridSizer(2, CONTROL_SPACE / 2, CONTROL_SPACE); 01036 fraAddingPatternSizer->Add(addPatternSizer, 0, wxTOP | wxGROW, CONTROL_SPACE / 2); 01037 addPatternSizer->AddGrowableCol(1); 01038 addPatternSizer->Add(lblPattern, 0, wxALIGN_CENTER_VERTICAL); 01039 addPatternSizer->Add(cboPattern, 1, wxALIGN_CENTER_VERTICAL | wxGROW); 01040 addPatternSizer->Add(lblDirectory, 0, wxALIGN_CENTER_VERTICAL); 01041 wxBoxSizer* searchDirSizer = new wxBoxSizer(wxHORIZONTAL); 01042 addPatternSizer->Add(searchDirSizer, 1, wxALIGN_CENTER_VERTICAL | wxGROW); 01043 searchDirSizer->Add(cboDirectory, 1, wxALIGN_CENTER_VERTICAL | wxGROW); 01044 searchDirSizer->Add(btnBrowse, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, CONTROL_SPACE); 01045 addPatternSizer->Add(lblDepth, 0, wxALIGN_CENTER_VERTICAL); 01046 wxFlexGridSizer* searchDepthSizer = new wxFlexGridSizer(2, 0, CONTROL_SPACE); 01047 searchDepthSizer->AddGrowableCol(0); 01048 addPatternSizer->Add(searchDepthSizer, 1, wxALIGN_CENTER_VERTICAL | wxGROW); 01049 searchDepthSizer->Add(spnDepth, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); 01050 searchDepthSizer->Add(btnAddPattern, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); 01051 01052 // Validation buttons sizer 01053 wxGridSizer* buttonsSizer = new wxGridSizer(2, 0, 2 * CONTROL_SPACE); 01054 buttonsSizer->Add(btnAdd); 01055 buttonsSizer->Add(btnCancel); 01056 dlgAddMatchFilesSizer->Add(buttonsSizer, 0, wxTOP | wxALIGN_RIGHT, (3 * CONTROL_SPACE) / 2); 01057 01058 // Set on the auto-layout feature 01059 this->SetAutoLayout(true); 01060 this->Layout(); 01061 01062 01063 //------------------------------------------------------------------------- 01064 // Initializes the controls 01065 for (int i = 1; i <= getHistoryMaxSize(); i++) 01066 { 01067 wxString pattern, directory; 01068 wxConfig::Get()->Read(getMatchPatternConfigKey(i), &pattern, wxEmptyString); 01069 wxConfig::Get()->Read(getDirectoryConfigKey(i), &directory, wxEmptyString); 01070 if (!pattern.IsEmpty()) 01071 cboPattern->Append(pattern.Strip(wxString::both)); 01072 if (!directory.IsEmpty()) 01073 cboDirectory->Append(directory.Strip(wxString::both)); 01074 } 01075 cboPattern->SetValue(wxEmptyString); 01076 cboDirectory->SetValue(wxEmptyString); 01077 01078 lvwPatterns->SetColumnWidth(0, wxConfig::Get()->Read(getConfigKey(prGUI_ADD_MATCH_FILES_DIRECTORY_WIDTH), wxLIST_AUTOSIZE_USEHEADER)); 01079 lvwPatterns->SetColumnWidth(1, wxConfig::Get()->Read(getConfigKey(prGUI_ADD_MATCH_FILES_PATTERN_WIDTH), wxLIST_AUTOSIZE_USEHEADER)); 01080 lvwPatterns->SetColumnWidth(2, wxConfig::Get()->Read(getConfigKey(prGUI_ADD_MATCH_FILES_DEPTH_WIDTH), wxLIST_AUTOSIZE_USEHEADER)); 01081 lvwPatterns->SetColumnToSort(wxConfig::Get()->Read(getConfigKey(prGUI_ADD_MATCH_FILES_SORT_BY), 0L)); 01082 lvwPatterns->SetSortOrder(static_cast<wxSortableListView::SortOrder>(wxConfig::Get()->Read(getConfigKey(prGUI_ADD_MATCH_FILES_SORT_ORDER), static_cast<long>(wxSortableListView::none)))); 01083 rbxSortBy->SetSelection(lvwPatterns->GetColumnToSort()); 01084 switch (lvwPatterns->GetSortOrder()) 01085 { 01086 case wxSortableListView::ascending : 01087 rbxSortOrder->SetSelection(0); 01088 break; 01089 case wxSortableListView::descending : 01090 rbxSortOrder->SetSelection(1); 01091 break; 01092 default : 01093 rbxSortOrder->SetSelection(2); 01094 } 01095 } 01096 //--------------------------------------------------------------------------- 01097 01098 01099 /** 01100 * Sets the title of the dialog. 01101 * 01102 * This method is called when the name of the checksums' file is modified. 01103 */ 01104 void dlgAddMatchFiles::setDialogTitle() 01105 { 01106 SetTitle(wxString::Format(_("Add matching files - %s"), getChecksumsFileName().c_str())); 01107 } 01108 //--------------------------------------------------------------------------- 01109 01110 01111 /** 01112 * The class descructor. 01113 */ 01114 dlgAddMatchFiles::~dlgAddMatchFiles() 01115 { 01116 if (matchPatterns != NULL) 01117 { 01118 delete matchPatterns; 01119 matchPatterns = NULL; 01120 } 01121 } 01122 //--------------------------------------------------------------------------- 01123 01124 01125 /** 01126 * Processes button Remove. 01127 * 01128 * @param event The event's parameters 01129 */ 01130 void dlgAddMatchFiles::btnRemoveClick(wxCommandEvent& event) 01131 { 01132 long item; 01133 01134 item = lvwPatterns->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01135 while (item != -1) 01136 { 01137 lvwPatterns->DeleteItem(item); 01138 item = lvwPatterns->GetNextItem(item - 1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); 01139 } 01140 } 01141 //--------------------------------------------------------------------------- 01142 01143 01144 /** 01145 * Gets the last directory used and the filter for the open or save dialog. 01146 * 01147 * @param configKey Configuration key for the last directory. 01148 * @param lastDirKey String that will contains the full configuration key for the last directory. 01149 * @param lastDir String that will contains the last directory. 01150 * @param fltMaker Filter that will contains the filters for the open or save dialog. 01151 */ 01152 void dlgAddMatchFiles::getLastDirectoryAndFilter(const wxString& configKey, wxString& lastDirKey, wxString& lastDir, wxFileDialogFilterMaker& fltMaker) 01153 { 01154 lastDirKey = dlgAddMatchFiles::getRootConfigKey() + configKey; 01155 01156 // Get the last directory used 01157 wxConfig::Get()->Read(lastDirKey, &lastDir, wxEmptyString); 01158 if (!::wxDirExists(lastDir)) 01159 { 01160 lastDir = AppPrefs::getUserDocumentsDirName(); 01161 if (lastDir.IsEmpty()) 01162 lastDir = ::wxGetCwd(); 01163 } 01164 01165 fltMaker.AddFilter(_("wxChecksums matching patterns files"), wxT("wpf")); 01166 fltMaker.AddFilter(_("All the files"), wxT("*")); 01167 } 01168 //--------------------------------------------------------------------------- 01169 01170 01171 /** 01172 * Reads a file of matching patterns. 01173 * 01174 * @param fileName Name of the file to read. 01175 * @param patterns Array of patterns in which the read patterns will be 01176 * stored. The array is not erased before adding patterns. 01177 */ 01178 void dlgAddMatchFiles::readMatchPatternsFile(const wxString& fileName, ArrayMatchPattern& patterns) 01179 { 01180 // Opens the file 01181 wxFileInputStream input(fileName); 01182 if (!input.Ok()) 01183 return; 01184 wxTextInputStream text(input); 01185 01186 // Reading the file 01187 wxString line; 01188 wxString directory; 01189 wxString pattern; 01190 long depth = -1; 01191 bool unknow; // unknow content 01192 wxString rest; // rest of the line 01193 01194 line = text.ReadLine(); 01195 while (!input.Eof()) 01196 { 01197 unknow = false; 01198 line.Trim(false).Trim(true); 01199 if (!line.IsEmpty()) 01200 if (line.GetChar(0) != wxT(';')) 01201 // This is not a comment 01202 { 01203 if (line.Length() >= 4) 01204 { 01205 // Reading the contents 01206 if (line.StartsWith(wxT("Di:"), &rest) && directory.IsEmpty() && 01207 pattern.IsEmpty() && depth == -1) 01208 // Reading a directory 01209 directory = rest; 01210 else if (line.StartsWith(wxT("Pa:"), &rest) && !directory.IsEmpty() && 01211 pattern.IsEmpty() && depth == -1) 01212 // Directory was read, reading the pattern 01213 pattern = rest; 01214 else if (line.StartsWith(wxT("De:"), &rest) && !directory.IsEmpty() && 01215 !pattern.IsEmpty() && depth == -1) 01216 // Directory and pattern were read, reading the depth 01217 { 01218 if (rest.ToLong(&depth)) 01219 { 01220 if (depth >= 0) 01221 // All is OK, add the pattern to the array 01222 { 01223 patterns.add(MatchPattern(directory, pattern, depth)); 01224 unknow = true; // say the content is unknow so all the parameters will be reinitialized 01225 } 01226 else // Bad value for the depth 01227 unknow = true; 01228 } 01229 else // Can't convert the string to long. 01230 unknow = true; 01231 } 01232 else // unknow content 01233 unknow = true; 01234 } // line too small, unknow content 01235 else 01236 unknow = true; 01237 01238 if (unknow) 01239 // Reinitializing reading variables 01240 { 01241 directory.Empty(); 01242 pattern.Empty(); 01243 depth = -1; 01244 } 01245 } 01246 01247 line = text.ReadLine(); 01248 } 01249 } 01250 //--------------------------------------------------------------------------- 01251 01252 01253 /** 01254 * Processes button Add List. 01255 * 01256 * @param event The event's parameters 01257 */ 01258 void dlgAddMatchFiles::btnAddListClick(wxCommandEvent& event) 01259 { 01260 wxString lastDir, lastDirKey; 01261 wxFileDialogFilterMaker fltMaker; 01262 getLastDirectoryAndFilter(wxT("LastAddListDirectory"), lastDirKey, lastDir, fltMaker); 01263 01264 // Show the open dialog 01265 wxFileDialog dlgOpen(this, _("Add a list of matching patterns"), 01266 lastDir, wxEmptyString, fltMaker.GetFilters(), 01267 wxOPEN | wxFILE_MUST_EXIST, wxDefaultPosition); 01268 01269 if (dlgOpen.ShowModal() == wxID_OK) 01270 { 01271 ArrayMatchPattern patterns; 01272 readMatchPatternsFile(dlgOpen.GetPath(), patterns); 01273 01274 // Add the matching patterns to the list 01275 for (size_t i = 0; i < patterns.getCount(); i++) 01276 addPatternToListView(patterns[i]); 01277 01278 // Save the last directory used 01279 wxConfig::Get()->Write(lastDirKey, dlgOpen.GetDirectory()); 01280 } 01281 } 01282 //--------------------------------------------------------------------------- 01283 01284 01285 /** 01286 * Processes button Load List. 01287 * 01288 * @param event The event's parameters 01289 */ 01290 void dlgAddMatchFiles::btnLoadListClick(wxCommandEvent& event) 01291 { 01292 wxString lastDir, lastDirKey; 01293 wxFileDialogFilterMaker fltMaker; 01294 getLastDirectoryAndFilter(wxT("LastLoadListDirectory"), lastDirKey, lastDir, fltMaker); 01295 01296 // Show the open dialog 01297 wxFileDialog dlgOpen(this, _("Load a list of matching patterns"), 01298 lastDir, wxEmptyString, fltMaker.GetFilters(), 01299 wxOPEN | wxFILE_MUST_EXIST, wxDefaultPosition); 01300 01301 if (dlgOpen.ShowModal() == wxID_OK) 01302 { 01303 ArrayMatchPattern patterns; 01304 readMatchPatternsFile(dlgOpen.GetPath(), patterns); 01305 01306 if (patterns.getCount() > 0) 01307 { 01308 // Clear the list only if there is some patterns to add. 01309 lvwPatterns->DeleteAllItems(); 01310 01311 // Add the matching patterns to the list 01312 for (size_t i = 0; i < patterns.getCount(); i++) 01313 addPatternToListView(patterns[i]); 01314 } 01315 01316 // Save the last directory used 01317 wxConfig::Get()->Write(lastDirKey, dlgOpen.GetDirectory()); 01318 } 01319 } 01320 //--------------------------------------------------------------------------- 01321 01322 01323 /** 01324 * Processes button Save List. 01325 * 01326 * @param event The event's parameters 01327 */ 01328 void dlgAddMatchFiles::btnSaveListClick(wxCommandEvent& event) 01329 { 01330 wxString lastDir, lastDirKey; 01331 wxFileDialogFilterMaker fltMaker; 01332 getLastDirectoryAndFilter(wxT("LastSaveListDirectory"), lastDirKey, lastDir, fltMaker); 01333 01334 // Show the open dialog 01335 wxFileDialog dlgSave(this, _("Save the list of matching patterns"), 01336 lastDir, wxEmptyString, fltMaker.GetFilters(), 01337 wxSAVE | wxOVERWRITE_PROMPT, wxDefaultPosition); 01338 01339 if (dlgSave.ShowModal() == wxID_OK) 01340 { 01341 wxFileOutputStream output(dlgSave.GetPath()); 01342 if (!output.Ok()) 01343 return; 01344 wxTextOutputStream text(output); 01345 01346 // Write header 01347 wxDateTime d = wxDateTime::Now(); 01348 text.WriteString(wxString::Format(wxT("; Generated by %s on %s at %s\n"), ::getAppName().c_str(), 01349 d.Format(wxT("%Y-%m-%d")).c_str(), d.Format(wxT("%H:%M:%S")).c_str())); 01350 01351 // Write patterns 01352 wxListItem listItem; 01353 listItem.SetMask(wxLIST_MASK_TEXT); 01354 long item = lvwPatterns->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 01355 while (item != -1) 01356 { 01357 text.WriteString(wxT(";\n")); 01358 listItem.SetId(item); 01359 listItem.SetColumn(0); 01360 lvwPatterns->GetItem(listItem); 01361 text.WriteString(wxT("Di:") + listItem.GetText() + wxT('\n')); 01362 listItem.SetColumn(1); 01363 lvwPatterns->GetItem(listItem); 01364 text.WriteString(wxT("Pa:") + listItem.GetText() + wxT('\n')); 01365 listItem.SetColumn(2); 01366 lvwPatterns->GetItem(listItem); 01367 text.WriteString(wxT("De:") + listItem.GetText() + wxT('\n')); 01368 01369 item = lvwPatterns->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 01370 } 01371 01372 // Save the last directory used 01373 wxConfig::Get()->Write(lastDirKey, dlgSave.GetDirectory()); 01374 } 01375 } 01376 //--------------------------------------------------------------------------- 01377 01378 01379 /** 01380 * Processes button Browse. 01381 * 01382 * @param event The event's parameters 01383 */ 01384 void dlgAddMatchFiles::btnBrowseClick(wxCommandEvent& event) 01385 { 01386 // Get the last directory used 01387 wxFileName fn(getChecksumsFileName()); 01388 wxString lastDir = fn.GetPath(wxPATH_GET_VOLUME); 01389 if (!::wxDirExists(lastDir)) 01390 { 01391 lastDir = AppPrefs::getUserDocumentsDirName(); 01392 if (lastDir.IsEmpty()) 01393 lastDir = ::wxGetCwd(); 01394 } 01395 01396 // Show the open dialog 01397 wxDirDialog dlgDir(this, _("Select the directory")); 01398 dlgDir.SetPath(lastDir); 01399 01400 if (dlgDir.ShowModal() == wxID_OK) 01401 { 01402 cboDirectory->SetValue(dlgDir.GetPath()); 01403 cboDirectory->SetFocus(); 01404 } 01405 } 01406 //--------------------------------------------------------------------------- 01407 01408 01409 /** 01410 * Adds a file or a directory or a match pattern to a combo box. 01411 * 01412 * @param cboBox The combobox. 01413 * @param maxLines The number of maximum lines in the combobox. 01414 */ 01415 void dlgAddMatchFiles::addLineToComboBox(wxComboBox* cboBox, const int maxLines) 01416 { 01417 wxString line = cboBox->GetValue().Strip(wxString::both); 01418 if (!line.IsEmpty()) 01419 { 01420 bool alreadyPresent = false; 01421 wxArrayString lines; 01422 int i = 0; 01423 while (!alreadyPresent && i < cboBox->GetCount()) 01424 { 01425 if (compareFileName(cboBox->GetString(i), line) == 0) 01426 alreadyPresent = true; 01427 else 01428 { 01429 lines.Add(cboBox->GetString(i)); 01430 i++; 01431 } 01432 } 01433 01434 if (!alreadyPresent) 01435 { 01436 cboBox->Freeze(); 01437 lines.Insert(line, 0); 01438 while (cboBox->GetCount() > 0) 01439 cboBox->Delete(0); 01440 int s = (lines.GetCount() < maxLines) ? lines.GetCount() : maxLines; 01441 for (i = 0; i < s; i++) 01442 cboBox->Append(lines[i]); 01443 cboBox->Thaw(); 01444 } 01445 } 01446 } 01447 //--------------------------------------------------------------------------- 01448 01449 01450 /** 01451 * Processes button Add pattern. 01452 * 01453 * @param event The event's parameters 01454 */ 01455 void dlgAddMatchFiles::btnAddPatternClick(wxCommandEvent& event) 01456 { 01457 unsigned int depth = (spnDepth->GetValue() > 0) ? static_cast<unsigned int>(spnDepth->GetValue()) : 0U; 01458 01459 MatchPattern mp(cboDirectory->GetValue().Strip(wxString::both), 01460 cboPattern->GetValue().Strip(wxString::both), 01461 depth); 01462 addPatternToListView(mp); 01463 01464 addLineToComboBox(cboPattern, getHistoryMaxSize()); 01465 addLineToComboBox(cboDirectory, getHistoryMaxSize()); 01466 01467 for (int i = 1; i <= getHistoryMaxSize(); i++) 01468 { 01469 wxString pattern = (cboPattern->GetCount() >= i) ? cboPattern->GetString(i - 1) : wxString(); 01470 wxString directory = (cboDirectory->GetCount() >= i) ? cboDirectory->GetString(i - 1) : wxString(); 01471 wxConfig::Get()->Write(getMatchPatternConfigKey(i), pattern); 01472 wxConfig::Get()->Write(getDirectoryConfigKey(i), directory); 01473 } 01474 } 01475 //--------------------------------------------------------------------------- 01476 01477 01478 /** 01479 * Event handler for the selection of an item. 01480 * 01481 * @param event Event parameters. 01482 */ 01483 void dlgAddMatchFiles::lvwPatternsSelectItem(wxListEvent& event) 01484 { 01485 btnRemove->Enable(); 01486 } 01487 //--------------------------------------------------------------------------- 01488 01489 01490 /** 01491 * Event handler for the deselection of an item. 01492 * 01493 * @param event Event parameters. 01494 */ 01495 void dlgAddMatchFiles::lvwPatternsDeselectItem(wxListEvent& event) 01496 { 01497 if (lvwPatterns->GetSelectedItemCount() == 0) 01498 btnRemove->Disable(); 01499 } 01500 //--------------------------------------------------------------------------- 01501 01502 01503 /** 01504 * Processes a selection of the column to sort. 01505 * 01506 * @param event Event parameters. 01507 */ 01508 void dlgAddMatchFiles::rbxSortBySelect(wxCommandEvent& event) 01509 { 01510 lvwPatterns->SetColumnToSort(event.GetInt()); 01511 lvwPatterns->SortItems(patternsListCmpFnct, reinterpret_cast<long>(lvwPatterns)); 01512 } 01513 //--------------------------------------------------------------------------- 01514 01515 01516 /** 01517 * Processes a selection of the sort order. 01518 * 01519 * @param event Event parameters. 01520 */ 01521 void dlgAddMatchFiles::rbxSortOrderSelect(wxCommandEvent& event) 01522 { 01523 switch (event.GetInt()) 01524 { 01525 case 0 : // ascending 01526 lvwPatterns->SetSortOrder(wxSortableListView::ascending); 01527 break; 01528 case 1 : // descending 01529 lvwPatterns->SetSortOrder(wxSortableListView::descending); 01530 break; 01531 case 2 : // none 01532 lvwPatterns->SetSortOrder(wxSortableListView::none); 01533 break; 01534 } 01535 lvwPatterns->SortItems(patternsListCmpFnct, reinterpret_cast<long>(lvwPatterns)); 01536 } 01537 //--------------------------------------------------------------------------- 01538 01539 01540 /** 01541 * Event handler for the enter key pressed on a search combo box. 01542 * 01543 * @param event Event parameters. 01544 */ 01545 void dlgAddMatchFiles::cboAddTextEnter(wxCommandEvent& event) 01546 { 01547 wxCommandEvent e(wxEVT_COMMAND_BUTTON_CLICKED, BTN_ADD_PATTERN); 01548 btnAddPattern->ProcessEvent(e); 01549 } 01550 //--------------------------------------------------------------------------- 01551 01552 01553 /** 01554 * Event handler for the key down event. 01555 * 01556 * @param event Event parameters. 01557 */ 01558 void dlgAddMatchFiles::lvwPatternsKeyDown(wxListEvent& event) 01559 { 01560 switch (event.GetKeyCode()) 01561 { 01562 case WXK_DELETE : { 01563 wxCommandEvent e(wxEVT_COMMAND_BUTTON_CLICKED, BTN_REMOVE); 01564 btnRemove->ProcessEvent(e); 01565 break; } 01566 default: 01567 event.Skip(); 01568 } 01569 } 01570 //--------------------------------------------------------------------------- 01571 01572 01573 /** 01574 * Processes a click on a header of a column of the list of patterns. 01575 * 01576 * @param event Event parameters. 01577 */ 01578 void dlgAddMatchFiles::lvwPatternsColumnClick(wxListEvent& event) 01579 { 01580 if (event.GetColumn() == lvwPatterns->GetColumnToSort()) 01581 lvwPatterns->SetSortOrder((lvwPatterns->GetSortOrder() == wxSortableListView::ascending) ? wxSortableListView::descending : wxSortableListView::ascending); 01582 else 01583 { 01584 lvwPatterns->SetSortOrder(wxSortableListView::ascending); 01585 lvwPatterns->SetColumnToSort(event.GetColumn()); 01586 } 01587 01588 rbxSortBy->SetSelection(event.GetColumn()); 01589 switch (lvwPatterns->GetSortOrder()) 01590 { 01591 case wxSortableListView::ascending : 01592 rbxSortOrder->SetSelection(0); 01593 break; 01594 case wxSortableListView::descending : 01595 rbxSortOrder->SetSelection(1); 01596 break; 01597 default : 01598 rbxSortOrder->SetSelection(2); 01599 } 01600 01601 lvwPatterns->SortItems(patternsListCmpFnct, reinterpret_cast<long>(lvwPatterns)); 01602 } 01603 //--------------------------------------------------------------------------- 01604 01605 01606 /** 01607 * Processes button Add. 01608 * 01609 * @param event The event's parameters 01610 */ 01611 void dlgAddMatchFiles::btnAddClick(wxCommandEvent& event) 01612 { 01613 if (Validate() && TransferDataFromWindow()) 01614 { 01615 // Save the preferences 01616 wxConfig::Get()->Write(getConfigKey(prGUI_ADD_MATCH_FILES_SORT_BY), lvwPatterns->GetColumnToSort()); 01617 wxConfig::Get()->Write(getConfigKey(prGUI_ADD_MATCH_FILES_SORT_ORDER), lvwPatterns->GetSortOrder()); 01618 wxConfig::Get()->Write(getConfigKey(prGUI_ADD_MATCH_FILES_DIRECTORY_WIDTH), lvwPatterns->GetColumnWidth(0)); 01619 wxConfig::Get()->Write(getConfigKey(prGUI_ADD_MATCH_FILES_PATTERN_WIDTH), lvwPatterns->GetColumnWidth(1)); 01620 wxConfig::Get()->Write(getConfigKey(prGUI_ADD_MATCH_FILES_DEPTH_WIDTH), lvwPatterns->GetColumnWidth(2)); 01621 wxSize s = GetSize(); 01622 wxConfig::Get()->Write(getConfigKey(prGUI_ADD_MATCH_FILES_WINDOW_SIZE), wxString::Format(wxT("%d,%d"), s.GetWidth(), s.GetHeight())); 01623 01624 // Close the dialog 01625 if (IsModal()) 01626 EndModal(wxID_OK); 01627 else 01628 { 01629 SetReturnCode(wxID_OK); 01630 this->Show(FALSE); 01631 } 01632 } 01633 } 01634 //--------------------------------------------------------------------------- 01635 01636 01637 /** 01638 * Add a pattern to the list view of patterns. 01639 * 01640 * If the pattern is already are in the list, it is not added. 01641 * 01642 * @param pattern Pattern to be added to the listview. 01643 */ 01644 void dlgAddMatchFiles::addPatternToListView(const MatchPattern& pattern) 01645 { 01646 // Remove spaces at the beginning and the end of the pattern and directory. 01647 wxString directory = pattern.getDirectory().Strip(wxString::both); 01648 wxString patterns = pattern.getPattern().Strip(wxString::both); 01649 01650 // Checks the validity of the parameters 01651 if (directory.IsEmpty()) 01652 directory = wxT("."); 01653 if (patterns.IsEmpty()) 01654 patterns = wxT("*"); 01655 01656 // Remove the path separators at the end of the directory if needed 01657 while (!directory.IsEmpty() && directory.Last() == wxFileName::GetPathSeparator()) 01658 directory.RemoveLast(); 01659 01660 MatchPattern patternToAdd(directory, patterns, pattern.getDepth()); 01661 wxListItem listItem; 01662 listItem.SetMask(wxLIST_MASK_TEXT); 01663 MatchPattern p; 01664 long depth; 01665 01666 // Checks if the pattern isn't already is the list. 01667 long item = lvwPatterns->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 01668 bool found = false; 01669 while (!found && item != -1) 01670 { 01671 listItem.SetId(item); 01672 listItem.SetColumn(0); 01673 lvwPatterns->GetItem(listItem); 01674 p.setDirectory(listItem.GetText()); 01675 listItem.SetColumn(1); 01676 lvwPatterns->GetItem(listItem); 01677 p.setPattern(listItem.GetText()); 01678 listItem.SetColumn(2); 01679 lvwPatterns->GetItem(listItem); 01680 listItem.GetText().ToLong(&depth); 01681 p.setDepth(depth); 01682 01683 if (patternToAdd == p) 01684 found = true; 01685 else 01686 item = lvwPatterns->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); 01687 } 01688 if (!found) 01689 { 01690 long newItem = lvwPatterns->InsertItem(lvwPatterns->GetItemCount(), patternToAdd.getDirectory()); 01691 lvwPatterns->SetItem(newItem, 1, patternToAdd.getPattern()); 01692 lvwPatterns->SetItem(newItem, 2, wxString::Format(wxT("%d"), patternToAdd.getDepth())); 01693 lvwPatterns->SetItemData(newItem, getID()); 01694 lvwPatterns->SortItems(patternsListCmpFnct, reinterpret_cast<long>(lvwPatterns)); 01695 } 01696 } 01697 //--------------------------------------------------------------------------- 01698 01699 01700 /** 01701 * Gets the choosed matching patterns. 01702 * 01703 * The given array of matching patterns is erased. 01704 * The matching array could contains directories with both relative and 01705 * absolute paths. 01706 * 01707 * @param patterns The array which will contain the patterns. 01708 */ 01709 void dlgAddMatchFiles::getMatchPatterns(ArrayMatchPattern& patterns) const 01710 { 01711 if (matchPatterns != NULL) 01712 patterns = *matchPatterns; 01713 } 01714 //--------------------------------------------------------------------------- 01715 01716 01717 /** 01718 * Gets the name of the checksums' file where the files will be added. 01719 * 01720 * @return The name of the checksums' file where the files will be added. 01721 */ 01722 wxString dlgAddMatchFiles::getChecksumsFileName() const 01723 { 01724 return checksumsFileName; 01725 } 01726 //--------------------------------------------------------------------------- 01727 01728 01729 /** 01730 * Sets the name of the checksums' file where the files will be added. 01731 * 01732 * @param fileName The name of the checksums' file where the files will be added. 01733 */ 01734 void dlgAddMatchFiles::setChecksumsFileName(const wxString& fileName) 01735 { 01736 checksumsFileName = fileName; 01737 setDialogTitle(); 01738 } 01739 //--------------------------------------------------------------------------- 01740 01741 01742 /** 01743 * Gets the root configuration key for parameters of this dialog. 01744 * 01745 * @return The root configuration key for parameters of this dialog. 01746 */ 01747 inline wxString dlgAddMatchFiles::getRootConfigKey() 01748 { 01749 return wxT("GUI/AddMatchingFilesDlg/"); 01750 } 01751 //--------------------------------------------------------------------------- 01752 01753 01754 /** 01755 * Gets the configuration key for the last match patterns to add. 01756 * 01757 * @param n The nth history configuration key to get. 01758 * @return The configuration key for the last match patterns to add. 01759 */ 01760 wxString dlgAddMatchFiles::getMatchPatternConfigKey(const int n) 01761 { 01762 if (n >= 1 && n <= getHistoryMaxSize()) 01763 return getRootConfigKey() + wxString::Format(wxT("History/MatchPattern%02d"), n); 01764 else 01765 return wxEmptyString; 01766 } 01767 //--------------------------------------------------------------------------- 01768 01769 01770 /** 01771 * Gets the configuration key for the last directories to add. 01772 * 01773 * @param n The nth history configuration key to get. 01774 * @return The configuration key for the last directories to add. 01775 */ 01776 wxString dlgAddMatchFiles::getDirectoryConfigKey(const int n) 01777 { 01778 if (n >= 1 && n <= getHistoryMaxSize()) 01779 return getRootConfigKey() + wxString::Format(wxT("History/Directory%02d"), n); 01780 else 01781 return wxEmptyString; 01782 } 01783 //--------------------------------------------------------------------------- 01784 01785 01786 /** 01787 * Get the maximum size of the history of the last match patterns and 01788 * directories to add. 01789 * 01790 * @return The maximum size of the history of the match patterns and 01791 * directories to add. 01792 */ 01793 inline int dlgAddMatchFiles::getHistoryMaxSize() 01794 { 01795 return 16; 01796 } 01797 //--------------------------------------------------------------------------- 01798 01799 01800 /** 01801 * Gets the configuration key corresponding to the given preference key. 01802 * 01803 * @param pk The preference key to get. 01804 * @return The configuration key corresponding to the given preference key or 01805 * an empty string if the preference key is invalid. 01806 */ 01807 wxString dlgAddMatchFiles::getConfigKey(const PreferencesKey pk) 01808 { 01809 wxString res = getRootConfigKey(); 01810 01811 switch (pk) 01812 { 01813 case prGUI_ADD_MATCH_FILES_SORT_BY : 01814 res += wxT("PatternsList/SortBy"); 01815 break; 01816 case prGUI_ADD_MATCH_FILES_SORT_ORDER : 01817 res += wxT("PatternsList/SortOrder"); 01818 break; 01819 case prGUI_ADD_MATCH_FILES_DIRECTORY_WIDTH : 01820 res += wxT("PatternsList/ColumnWidthDirectory"); 01821 break; 01822 case prGUI_ADD_MATCH_FILES_PATTERN_WIDTH : 01823 res += wxT("PatternsList/ColumnWidthPatterns"); 01824 break; 01825 case prGUI_ADD_MATCH_FILES_DEPTH_WIDTH : 01826 res += wxT("PatternsList/ColumnWidthDepth"); 01827 break; 01828 case prGUI_ADD_MATCH_FILES_WINDOW_SIZE : 01829 res += wxT("WindowSize"); 01830 break; 01831 default : 01832 res = wxEmptyString; 01833 } 01834 01835 return res; 01836 } 01837 //--------------------------------------------------------------------------- 01838 01839 01840 /** 01841 * Gets a new unique identifier. 01842 * 01843 * @return A new unique identifier. 01844 */ 01845 long dlgAddMatchFiles::getID() 01846 { 01847 return idGen++; 01848 } 01849 //--------------------------------------------------------------------------- 01850 01851 01852 01853 BEGIN_EVENT_TABLE(dlgAddMatchFiles, wxDialog) 01854 EVT_BUTTON(BTN_REMOVE, dlgAddMatchFiles::btnRemoveClick) 01855 EVT_BUTTON(BTN_ADDLIST, dlgAddMatchFiles::btnAddListClick) 01856 EVT_BUTTON(BTN_LOADLIST, dlgAddMatchFiles::btnLoadListClick) 01857 EVT_BUTTON(BTN_SAVELIST, dlgAddMatchFiles::btnSaveListClick) 01858 EVT_BUTTON(BTN_BROWSE, dlgAddMatchFiles::btnBrowseClick) 01859 EVT_BUTTON(BTN_ADD_PATTERN, dlgAddMatchFiles::btnAddPatternClick) 01860 EVT_LIST_ITEM_SELECTED(LVW_FILES, dlgAddMatchFiles::lvwPatternsSelectItem) 01861 EVT_LIST_ITEM_DESELECTED(LVW_FILES, dlgAddMatchFiles::lvwPatternsDeselectItem) 01862 EVT_LIST_DELETE_ITEM(LVW_FILES, dlgAddMatchFiles::lvwPatternsDeselectItem) 01863 EVT_LIST_KEY_DOWN(LVW_FILES, dlgAddMatchFiles::lvwPatternsKeyDown) 01864 EVT_LIST_COL_CLICK(LVW_FILES, dlgAddMatchFiles::lvwPatternsColumnClick) 01865 EVT_RADIOBOX(RBX_SORT_BY, dlgAddMatchFiles::rbxSortBySelect) 01866 EVT_RADIOBOX(RBX_SORT_ORDER, dlgAddMatchFiles::rbxSortOrderSelect) 01867 EVT_TEXT_ENTER(CBO_PATTERN, dlgAddMatchFiles::cboAddTextEnter) 01868 EVT_TEXT_ENTER(CBO_DIRECTORY, dlgAddMatchFiles::cboAddTextEnter) 01869 EVT_BUTTON(BTN_ADD, dlgAddMatchFiles::btnAddClick) 01870 END_EVENT_TABLE() 01871 //---------------------------------------------------------------------------

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