diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:05:30 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:05:30 +0200 |
commit | c0fce877c478ddbf71a1b651c789e5ea00a00144 (patch) | |
tree | de01b0ae8fd296bd24fbca54a80f2f0ba071d461 /library | |
parent | 3.3 (diff) | |
download | FreeFileSync-c0fce877c478ddbf71a1b651c789e5ea00a00144.tar.gz FreeFileSync-c0fce877c478ddbf71a1b651c789e5ea00a00144.tar.bz2 FreeFileSync-c0fce877c478ddbf71a1b651c789e5ea00a00144.zip |
3.4
Diffstat (limited to 'library')
30 files changed, 623 insertions, 270 deletions
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp index cba76f57..a04548a3 100644 --- a/library/CustomGrid.cpp +++ b/library/CustomGrid.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "customGrid.h" #include "../shared/systemConstants.h" #include "resources.h" @@ -217,7 +223,7 @@ public: virtual int GetNumberCols() { - return columnPositions.size(); + return static_cast<int>(columnPositions.size()); } virtual wxString GetColLabelValue( int col ) @@ -270,6 +276,8 @@ protected: return _("<Directory>"); case xmlAccess::DATE: //date return wxEmptyString; + case xmlAccess::EXTENSION: //file extension + return wxEmptyString; } } else @@ -291,6 +299,8 @@ protected: return FreeFileSync::includeNumberSeparator(fileObj->getFileSize<side>().ToString()); case xmlAccess::DATE: //date return FreeFileSync::utcTimeToLocalString(fileObj->getLastWriteTime<side>(), fileObj->getFullName<side>()); + case xmlAccess::EXTENSION: //file extension + return zToWx(fileObj->getExtension<side>()); } } } @@ -492,6 +502,10 @@ CustomGrid::CustomGrid(wxWindow *parent, isLeading(false), m_marker(-1, ASCENDING) { + SetLayoutDirection(wxLayout_LeftToRight); // + GetGridWindow()->SetLayoutDirection(wxLayout_LeftToRight); //avoid mirroring this dialog in RTL languages like Hebrew or Arabic + GetGridColLabelWindow()->SetLayoutDirection(wxLayout_LeftToRight); // + //set color of selections wxColour darkBlue(40, 35, 140); SetSelectionBackground(darkBlue); @@ -525,6 +539,7 @@ void CustomGrid::initSettings(CustomGridLeft* gridLeft, Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(CustomGrid::onGridAccess), NULL, this); Connect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(CustomGrid::onGridAccess), NULL, this); Connect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(CustomGrid::onGridAccess), NULL, this); + Connect(wxEVT_SET_FOCUS, wxEventHandler(CustomGrid::onGridAccess), NULL, this); //used by grid text-search GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); GetGridWindow()->Connect(wxEVT_RIGHT_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); @@ -600,149 +615,139 @@ void execGridCommands(wxEvent& event, wxGrid* grid) const int cursorOldPos = std::max(std::min(grid->GetGridCursorRow(), grid->GetNumberRows() - 1), 0); const int cursorOldColumn = std::max(std::min(grid->GetGridCursorCol(), grid->GetNumberCols() - 1), 0); - if (keyEvent->ShiftDown()) + const bool shiftPressed = keyEvent->ShiftDown(); + const bool altPressed = keyEvent->AltDown(); + const bool ctrlPressed = keyEvent->ControlDown(); + const bool noModPressed = !shiftPressed && !altPressed && !ctrlPressed; + const int keyCode = keyEvent->GetKeyCode(); + + + //SHIFT + X + if (shiftPressed && keyCode == WXK_UP) { - //support for shift + PageUp and shift + PageDown - switch (keyEvent->GetKeyCode()) - { - case WXK_UP: //move grid cursor also - { - const int cursorNewPos = std::max(cursorOldPos - 1, 0); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - } + const int cursorNewPos = std::max(cursorOldPos - 1, 0); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); return; //no event.Skip() - - case WXK_DOWN: //move grid cursor also - { - const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - } + } + else if (shiftPressed && keyCode == WXK_DOWN) + { + const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); return; //no event.Skip() - - case WXK_LEFT: //move grid cursor also - { - const int cursorColumn = std::max(cursorOldColumn - 1, 0); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - } + } + else if (shiftPressed && keyCode == WXK_LEFT) + { + const int cursorColumn = std::max(cursorOldColumn - 1, 0); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); return; //no event.Skip() - - case WXK_RIGHT: //move grid cursor also - { - const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - } + } + else if (shiftPressed && keyCode == WXK_RIGHT) + { + const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); return; //no event.Skip() - - - case WXK_PAGEUP: - case WXK_NUMPAD_PAGEUP: - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - } + } + else if (shiftPressed && (keyCode == WXK_PAGEUP || keyCode == WXK_NUMPAD_PAGEUP)) + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); return; //no event.Skip() - - case WXK_PAGEDOWN: - case WXK_NUMPAD_PAGEDOWN: - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - } + } + else if (shiftPressed && (keyCode == WXK_PAGEDOWN || keyCode == WXK_NUMPAD_PAGEDOWN)) + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); return; //no event.Skip() - - case WXK_HOME: - case WXK_NUMPAD_HOME: - { - const int cursorNewPos = 0; - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - } + } + else if (shiftPressed && (keyCode == WXK_HOME || keyCode == WXK_NUMPAD_HOME)) + { + const int cursorNewPos = 0; + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); return; //no event.Skip() - - case WXK_END: - case WXK_NUMPAD_END: - { - const int cursorNewPos = grid->GetNumberRows() - 1; - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - } + } + else if (shiftPressed && (keyCode == WXK_END || keyCode == WXK_NUMPAD_END)) + { + const int cursorNewPos = grid->GetNumberRows() - 1; + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); return; //no event.Skip() + } - } + //CTRL + X + else if (ctrlPressed && keyCode == WXK_LEFT) + { + grid->SetGridCursor(grid->GetGridCursorRow(), 0); + grid->MakeCellVisible(grid->GetGridCursorRow(), 0); + return; //no event.Skip() } - else if (keyEvent->AltDown()) - ; - else if (keyEvent->ControlDown()) - ; - else //button without additonal control keys pressed + else if (ctrlPressed && keyCode == WXK_RIGHT) { - switch (keyEvent->GetKeyCode()) - { - case WXK_UP: //move grid cursor also - { - const int cursorNewPos = std::max(cursorOldPos - 1, 0); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - } + grid->SetGridCursor(grid->GetGridCursorRow(), grid->GetNumberCols() - 1); + grid->MakeCellVisible(grid->GetGridCursorRow(), grid->GetNumberCols() - 1); return; //no event.Skip() - case WXK_DOWN: //move grid cursor also - { - const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - } + } + else if ((ctrlPressed && keyCode == WXK_UP) || + ((noModPressed || ctrlPressed) && (keyCode == WXK_HOME || keyCode == WXK_NUMPAD_HOME))) + { + grid->SetGridCursor(0, grid->GetGridCursorCol()); + grid->MakeCellVisible(0, grid->GetGridCursorCol()); return; //no event.Skip() + } + else if ((ctrlPressed && keyCode == WXK_DOWN) || + ((noModPressed || ctrlPressed) && (keyCode == WXK_END || keyCode == WXK_NUMPAD_END))) + { + grid->SetGridCursor(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); + grid->MakeCellVisible(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); + return; //no event.Skip() + } - case WXK_LEFT: //move grid cursor also - { - const int cursorColumn = std::max(cursorOldColumn - 1, 0); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - } + //button without additonal control keys pressed + else if (noModPressed && keyCode == WXK_UP) + { + const int cursorNewPos = std::max(cursorOldPos - 1, 0); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); return; //no event.Skip() - case WXK_RIGHT: //move grid cursor also - { - const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - } + } + else if (noModPressed && keyCode == WXK_DOWN) + { + const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); return; //no event.Skip() - - - case WXK_PAGEUP: - case WXK_NUMPAD_PAGEUP: - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - } + } + else if (noModPressed && keyCode == WXK_LEFT) + { + const int cursorColumn = std::max(cursorOldColumn - 1, 0); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); return; //no event.Skip() - - case WXK_PAGEDOWN: - case WXK_NUMPAD_PAGEDOWN: - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - } + } + else if (noModPressed && keyCode == WXK_RIGHT) + { + const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); + return; //no event.Skip() + } + else if ((noModPressed || ctrlPressed) && (keyCode == WXK_PAGEUP || keyCode == WXK_NUMPAD_PAGEUP)) + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); + return; //no event.Skip() + } + else if ((noModPressed || ctrlPressed) && (keyCode == WXK_PAGEDOWN || keyCode == WXK_NUMPAD_PAGEDOWN)) + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); return; //no event.Skip() - - case WXK_HOME: - case WXK_NUMPAD_HOME: - grid->SetGridCursor(0, grid->GetGridCursorCol()); - grid->MakeCellVisible(0, grid->GetGridCursorCol()); - return; //no event.Skip() - - case WXK_END: - case WXK_NUMPAD_END: - grid->SetGridCursor(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); - grid->MakeCellVisible(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); - return; //no event.Skip() - } } } @@ -1128,6 +1133,12 @@ xmlAccess::ColumnAttributes CustomGridRim::getDefaultColumnAttributes() newEntry.width = 113; defaultColumnSettings.push_back(newEntry); + newEntry.type = xmlAccess::EXTENSION; + newEntry.visible = false; + newEntry.position = 6; + newEntry.width = 60; + defaultColumnSettings.push_back(newEntry); + return defaultColumnSettings; } @@ -1177,10 +1188,10 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) if (i < attr.size()) newEntry = attr[i]; - else + else //fix corrupted data: { - newEntry.type = xmlAccess::FILENAME; - newEntry.visible = true; + newEntry.type = static_cast<xmlAccess::ColumnTypes>(xmlAccess::COLUMN_TYPE_COUNT); //sort additional rows to the end + newEntry.visible = false; newEntry.position = i; newEntry.width = 100; } @@ -1189,7 +1200,7 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) std::sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByType); for (unsigned int i = 0; i < xmlAccess::COLUMN_TYPE_COUNT; ++i) //just be sure that each type exists only once - columnSettings[i].type = xmlAccess::ColumnTypes(i); + columnSettings[i].type = static_cast<xmlAccess::ColumnTypes>(i); std::sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionOnly); for (unsigned int i = 0; i < xmlAccess::COLUMN_TYPE_COUNT; ++i) //just be sure that positions are numbered correctly @@ -1248,6 +1259,8 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType) return _("Size"); case xmlAccess::DATE: return _("Date"); + case xmlAccess::EXTENSION: + return _("Extension"); } return wxEmptyString; //dummy @@ -1418,6 +1431,9 @@ IconUpdater::IconUpdater(CustomGridLeft* leftGrid, CustomGridRight* rightGrid) : } +IconUpdater::~IconUpdater() {} //non-inline destructor for std::auto_ptr to work with forward declaration + + void IconUpdater::loadIconsAsynchronously(wxEvent& event) //loads all (not yet) drawn icons { std::vector<Zstring> iconsLeft; @@ -1576,13 +1592,16 @@ CustomGridMiddle::CustomGridMiddle(wxWindow *parent, toolTip(new CustomTooltip) { //connect events for dynamic selection of sync direction - GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridMiddle::OnMouseMovement), NULL, this); - GetGridWindow()->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(CustomGridMiddle::OnLeaveWindow), NULL, this); - GetGridWindow()->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseUp), NULL, this); - GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseDown), NULL, this); + GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridMiddle::OnMouseMovement), NULL, this); + GetGridWindow()->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(CustomGridMiddle::OnLeaveWindow), NULL, this); + GetGridWindow()->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseUp), NULL, this); + GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseDown), NULL, this); } +CustomGridMiddle::~CustomGridMiddle() {} //non-inline destructor for std::auto_ptr to work with forward declaration + + bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) { gridDataTable = new CustomGridTableMiddle; @@ -1999,12 +2018,3 @@ const wxBitmap& FreeFileSync::getSyncOpImage(SyncOperation syncOp) return wxNullBitmap; //dummy } - - - - - - - - - diff --git a/library/CustomGrid.h b/library/CustomGrid.h index 2b78a6c3..7a0d1b10 100644 --- a/library/CustomGrid.h +++ b/library/CustomGrid.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef CUSTOMGRID_H_INCLUDED #define CUSTOMGRID_H_INCLUDED @@ -67,7 +73,7 @@ public: enum SortDirection { ASCENDING, - DESCENDING, + DESCENDING }; typedef std::pair<SortColumn, SortDirection> SortMarker; @@ -111,6 +117,7 @@ class IconUpdater : private wxEvtHandler //update file icons periodically: use S { public: IconUpdater(CustomGridLeft* leftGrid, CustomGridRight* rightGrid); + ~IconUpdater(); //non-inline destructor for std::auto_ptr to work with forward declaration private: void loadIconsAsynchronously(wxEvent& event); //loads all (not yet) drawn icons @@ -240,6 +247,8 @@ public: long style = wxWANTS_CHARS, const wxString& name = wxGridNameStr); + ~CustomGridMiddle(); //non-inline destructor for std::auto_ptr to work with forward declaration + virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); void enableSyncPreview(bool value); diff --git a/library/Recycler/Recycler_Vista.vcproj b/library/Recycler_Vista/Recycler_Vista.vcproj index 65ab6609..65ab6609 100644 --- a/library/Recycler/Recycler_Vista.vcproj +++ b/library/Recycler_Vista/Recycler_Vista.vcproj diff --git a/library/Recycler/dllmain.cpp b/library/Recycler_Vista/dllmain.cpp index 834b4f88..7db39bff 100644 --- a/library/Recycler/dllmain.cpp +++ b/library/Recycler_Vista/dllmain.cpp @@ -1,4 +1,9 @@ -// dllmain.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung. +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #define WIN32_LEAN_AND_MEAN #include <windows.h> diff --git a/library/Recycler/recycler.cpp b/library/Recycler_Vista/recycler.cpp index b551d4d0..7858267b 100644 --- a/library/Recycler/recycler.cpp +++ b/library/Recycler_Vista/recycler.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "recycler.h" #define WIN32_LEAN_AND_MEAN diff --git a/library/Recycler/recycler.h b/library/Recycler_Vista/recycler.h index 59bec9dc..697221c3 100644 --- a/library/Recycler/recycler.h +++ b/library/Recycler_Vista/recycler.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef RECYCLER_DLL_H #define RECYCLER_DLL_H diff --git a/library/ShadowCopy/dllmain.cpp b/library/ShadowCopy/dllmain.cpp index 834b4f88..7db39bff 100644 --- a/library/ShadowCopy/dllmain.cpp +++ b/library/ShadowCopy/dllmain.cpp @@ -1,4 +1,9 @@ -// dllmain.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung. +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #define WIN32_LEAN_AND_MEAN #include <windows.h> diff --git a/library/ShadowCopy/shadow.cpp b/library/ShadowCopy/shadow.cpp index 0693815f..b15bd4f9 100644 --- a/library/ShadowCopy/shadow.cpp +++ b/library/ShadowCopy/shadow.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "shadow.h" #define WIN32_LEAN_AND_MEAN diff --git a/library/ShadowCopy/shadow.h b/library/ShadowCopy/shadow.h index e25c6a32..cc82e8e0 100644 --- a/library/ShadowCopy/shadow.h +++ b/library/ShadowCopy/shadow.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef SHADOWCOPY_H #define SHADOWCOPY_H diff --git a/library/binary.cpp b/library/binary.cpp new file mode 100644 index 00000000..bc5ba814 --- /dev/null +++ b/library/binary.cpp @@ -0,0 +1,122 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#include "binary.h" +#include <boost/scoped_array.hpp> +#include <wx/intl.h> +#include "../shared/stringConv.h" + +#ifdef FFS_WIN +#include "../shared/longPathPrefix.h" +#include <wx/msw/wrapwin.h> //includes "windows.h" +#include <boost/shared_ptr.hpp> + +#elif defined FFS_LINUX +#include <wx/ffile.h> +#endif + + +bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback* callback) +{ + const size_t BUFFER_SIZE = 512 * 1024; //512 kb seems to be the perfect buffer size + static boost::scoped_array<unsigned char> memory1(new unsigned char[BUFFER_SIZE]); + static boost::scoped_array<unsigned char> memory2(new unsigned char[BUFFER_SIZE]); + +#ifdef FFS_WIN + const HANDLE hFile1 = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename1).c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (hFile1 == INVALID_HANDLE_VALUE) + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); + + boost::shared_ptr<void> dummy1(hFile1, &::CloseHandle); + + const HANDLE hFile2 = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename2).c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (hFile2 == INVALID_HANDLE_VALUE) + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); + + boost::shared_ptr<void> dummy2(hFile2, &::CloseHandle); + + wxLongLong bytesCompared; + DWORD length1 = 0; + do + { + if (!::ReadFile( + hFile1, //__in HANDLE hFile, + memory1.get(), //__out LPVOID lpBuffer, + BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead, + &length1, //__out_opt LPDWORD lpNumberOfBytesRead, + NULL)) //__inout_opt LPOVERLAPPED lpOverlapped + throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); + + DWORD length2 = 0; + if (!::ReadFile( + hFile2, //__in HANDLE hFile, + memory2.get(), //__out LPVOID lpBuffer, + BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead, + &length2, //__out_opt LPDWORD lpNumberOfBytesRead, + NULL)) //__inout_opt LPOVERLAPPED lpOverlapped + throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); + + if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0) + return false; + + bytesCompared += length1 * 2; + + //send progress updates + callback->updateCompareStatus(bytesCompared); + } + while (length1 == BUFFER_SIZE); + + return true; + + +#elif defined FFS_LINUX + wxFFile file1(::fopen(filename1.c_str(), DefaultStr("rb,type=record,noseek"))); //utilize UTF-8 filename + if (!file1.IsOpened()) + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); + + wxFFile file2(::fopen(filename2.c_str(), DefaultStr("rb,type=record,noseek"))); //utilize UTF-8 filename + if (!file2.IsOpened()) + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); + + wxLongLong bytesCompared; + do + { + const size_t length1 = file1.Read(memory1.get(), BUFFER_SIZE); + if (file1.Error()) + throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); + + const size_t length2 = file2.Read(memory2.get(), BUFFER_SIZE); + if (file2.Error()) + throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); + + if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0) + return false; + + bytesCompared += length1 * 2; + + //send progress updates + callback->updateCompareStatus(bytesCompared); + } + while (!file1.Eof()); + + if (!file2.Eof()) //highly unlikely, but theoretically possible! (but then again, not in this context where both files have same size...) + return false; + + return true; +#endif +} diff --git a/library/binary.h b/library/binary.h new file mode 100644 index 00000000..c4e9c928 --- /dev/null +++ b/library/binary.h @@ -0,0 +1,28 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef BINARY_H_INCLUDED +#define BINARY_H_INCLUDED + +#include "../shared/zstring.h" +#include <wx/longlong.h> +#include "../shared/fileError.h" + +namespace FreeFileSync +{ + +//callback functionality for status updates while comparing +class CompareCallback +{ +public: + virtual ~CompareCallback() {} + virtual void updateCompareStatus(const wxLongLong& totalBytesTransferred) = 0; +}; + +bool filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback* callback); //throw FileError +} + +#endif // BINARY_H_INCLUDED diff --git a/library/detectRenaming.cpp b/library/detectRenaming.cpp index d2b4a62c..bd25874b 100644 --- a/library/detectRenaming.cpp +++ b/library/detectRenaming.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "detectRenaming.h" #include <map> #include <vector> diff --git a/library/detectRenaming.h b/library/detectRenaming.h index 82cb543e..ecfa0344 100644 --- a/library/detectRenaming.h +++ b/library/detectRenaming.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef DETECTRENAMING_H_INCLUDED #define DETECTRENAMING_H_INCLUDED diff --git a/library/errorLogging.cpp b/library/errorLogging.cpp index 9424a6c5..7e73f005 100644 --- a/library/errorLogging.cpp +++ b/library/errorLogging.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "errorLogging.h" #include <wx/datetime.h> #include <wx/intl.h> diff --git a/library/errorLogging.h b/library/errorLogging.h index 24b4a992..6b27e1c1 100644 --- a/library/errorLogging.h +++ b/library/errorLogging.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef ERRORLOGGING_H_INCLUDED #define ERRORLOGGING_H_INCLUDED @@ -23,20 +29,16 @@ public: return errorCount; } - const std::vector<wxString>& getFormattedMessages() const + typedef std::vector<wxString> MessageEntry; + const MessageEntry& getFormattedMessages() const { return formattedMessages; } - size_t messageCount() - { - return formattedMessages.size(); - } - private: wxString assembleMessage(const wxString& prefix, const wxString& message); - std::vector<wxString> formattedMessages; //list of non-resolved errors and warnings + MessageEntry formattedMessages; //list of non-resolved errors and warnings int errorCount; }; } diff --git a/library/filter.cpp b/library/filter.cpp index 25877513..b1b67b86 100644 --- a/library/filter.cpp +++ b/library/filter.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "filter.h" #include "../shared/zstring.h" #include <wx/string.h> diff --git a/library/filter.h b/library/filter.h index ea725291..6ec5a3d5 100644 --- a/library/filter.h +++ b/library/filter.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef FFS_FILTER_H_INCLUDED #define FFS_FILTER_H_INCLUDED diff --git a/library/iconBuffer.cpp b/library/iconBuffer.cpp index 21f85372..338f53df 100644 --- a/library/iconBuffer.cpp +++ b/library/iconBuffer.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "iconBuffer.h" #include <wx/thread.h> #include <wx/bitmap.h> @@ -56,7 +62,7 @@ struct CmpFilenameWin { bool operator()(const Zstring& a, const Zstring& b) const { - return a.CmpNoCase(b) < 0; + return a.cmpFileName(b) < 0; } }; @@ -83,10 +89,43 @@ bool isPriceyExtension(const Zstring& extension) } //################################################################################################################################################ + +class IconBuffer::IconHolder //handle HICON ownership WITHOUT ref-counting to allow a deep-copy (in contrast to wxIcon) +{ +public: + IconHolder(HICON handle = 0) : handle_(handle) {} + + ~IconHolder() + { + if (handle_ != 0) + ::DestroyIcon(handle_); + } + + HICON clone() const //copy HICON, caller needs to take ownership! + { + return handle_ != 0 ? ::CopyIcon(handle_) : 0; + } + + void swap(IconHolder& other) //throw() + { + std::swap(handle_, other.handle_); + } + +private: + IconHolder(const IconHolder&); + IconHolder& operator=(const IconHolder&); + + HICON handle_; +}; + + +//--------------------------------------------------------------------------------------------------- typedef std::vector<DefaultChar> BasicString; //simple thread safe string class: std::vector is guaranteed to not use reference counting, Effective STL, item 13 +//avoid reference-counted objects as shared data: NOT THREADSAFE!!! (implicitly shared variables: ref-count + c-string) +//--------------------------------------------------------------------------------------------------- -class WorkerThread : public wxThread +class IconBuffer::WorkerThread : public wxThread { public: WorkerThread(IconBuffer* iconBuff); @@ -116,7 +155,7 @@ private: }; -WorkerThread::WorkerThread(IconBuffer* iconBuff) : +IconBuffer::WorkerThread::WorkerThread(IconBuffer* iconBuff) : wxThread(wxTHREAD_JOINABLE), threadHasMutex(false), threadExitIsRequested(false), @@ -141,7 +180,7 @@ WorkerThread::WorkerThread(IconBuffer* iconBuff) : } -void WorkerThread::setWorkload(const std::vector<Zstring>& load) //(re-)set new workload of icons to be retrieved +void IconBuffer::WorkerThread::setWorkload(const std::vector<Zstring>& load) //(re-)set new workload of icons to be retrieved { wxCriticalSectionLocker dummy(lockWorkload); @@ -154,7 +193,7 @@ void WorkerThread::setWorkload(const std::vector<Zstring>& load) //(re-)set new } -void WorkerThread::quitThread() +void IconBuffer::WorkerThread::quitThread() { { wxMutexLocker dummy(threadIsListening); //wait until thread is in waiting state @@ -165,7 +204,7 @@ void WorkerThread::quitThread() } -wxThread::ExitCode WorkerThread::Entry() +wxThread::ExitCode IconBuffer::WorkerThread::Entry() { try { @@ -196,9 +235,9 @@ wxThread::ExitCode WorkerThread::Entry() } -void WorkerThread::doWork() +void IconBuffer::WorkerThread::doWork() { - FileName fileName; //don't use Zstring: reference-counted objects are NOT THREADSAFE!!! e.g. double deletion might happen + Zstring fileName; //do work: get the file icon. while (true) @@ -207,11 +246,11 @@ void WorkerThread::doWork() wxCriticalSectionLocker dummy(lockWorkload); if (workload.empty()) break; //enter waiting state - fileName = workload.back(); + fileName = &workload.back()[0]; //deep copy: fileName is NOT empty (includes NULL-termination) workload.pop_back(); } - if (iconBuffer->requestFileIcon(Zstring(&fileName[0]))) //thread safety: Zstring okay, won't be reference-counted in requestIcon(), fileName is NOT empty + if (iconBuffer->requestFileIcon(fileName)) //thread safety: Zstring okay, won't be reference-counted in requestIcon() continue; //icon already in buffer: skip //despite what docu says about SHGetFileInfo() it can't handle all relative filenames, e.g. "\DirName" @@ -219,62 +258,41 @@ void WorkerThread::doWork() //load icon SHFILEINFO fileInfo; - fileInfo.hIcon = 0; //initialize hIcon + fileInfo.hIcon = 0; //initialize hIcon -> fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! + //bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080 - const Zstring extension = getFileExtension(&fileName[0]); //thread-safe: no sharing! + const Zstring extension = getFileExtension(fileName); //thread-safe: no sharing! if (isPriceyExtension(extension)) //"pricey" extensions are stored with fullnames and are read from disk, while cheap ones require just the extension { //NOTE: CoInitializeEx()/CoUninitialize() implicitly called by wxWidgets on program startup! - if (::SHGetFileInfo(&fileName[0], //FreeFileSync::removeLongPathPrefix(&fileName[0]), //::SHGetFileInfo() can't handle \\?\-prefix! - 0, - &fileInfo, - sizeof(fileInfo), - SHGFI_ICON | SHGFI_SMALLICON) && - fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! - { - //bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080 - - wxIcon newIcon; //attention: wxIcon uses reference counting! - newIcon.SetHICON(fileInfo.hIcon); - newIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE); - - iconBuffer->insertIntoBuffer(&fileName[0], newIcon); //thread safety: icon buffer is written by this thread and this call only, so - //newIcon can safely go out of scope without race-condition because of ref-counting + ::SHGetFileInfo(fileName.c_str(), //FreeFileSync::removeLongPathPrefix(fileName), //::SHGetFileInfo() can't handle \\?\-prefix! + 0, + &fileInfo, + sizeof(fileInfo), + SHGFI_ICON | SHGFI_SMALLICON); - //freeing of icon handle seems to happen somewhere beyond wxIcon destructor - //if (!DestroyIcon(fileInfo.hIcon)) - // throw RuntimeException(wxString(wxT("Error deallocating Icon handle!\n\n")) + FreeFileSync::getLastErrorFormatted()); - continue; - } + IconBuffer::IconHolder newIcon(fileInfo.hIcon); //pass icon ownership (may be 0) + iconBuffer->insertIntoBuffer(fileName, newIcon); } else //no read-access to disk! determine icon by extension { - if (::SHGetFileInfo((Zstring(DefaultStr("dummy.")) + extension).c_str(), //Windows Seven doesn't like this parameter to be without short name - FILE_ATTRIBUTE_NORMAL, - &fileInfo, - sizeof(fileInfo), - SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES) && - fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! - { - wxIcon newIcon; //attention: wxIcon uses reference counting! - newIcon.SetHICON(fileInfo.hIcon); - newIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE); + ::SHGetFileInfo((Zstring(DefaultStr("dummy.")) + extension).c_str(), //Windows Seven doesn't like this parameter to be without short name + FILE_ATTRIBUTE_NORMAL, + &fileInfo, + sizeof(fileInfo), + SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES); - iconBuffer->insertIntoBuffer(extension.c_str(), newIcon); //thread safety: icon buffer is written by this thread and this call only, so - continue; - } + IconBuffer::IconHolder newIcon(fileInfo.hIcon); //pass icon ownership (may be 0) + iconBuffer->insertIntoBuffer(extension, newIcon); } - - //if loading of icon fails for whatever reason, just save a dummy icon to avoid re-loading - iconBuffer->insertIntoBuffer(&fileName[0], wxNullIcon); } } -//--------------------------------------------------------------------------------------------------- -class IconDB : public std::map<Zstring, wxIcon> {}; // entryName/icon -class IconDbSequence : public std::queue<Zstring> {}; // entryName //--------------------------------------------------------------------------------------------------- +class IconBuffer::IconDB : public std::map<Zstring, IconBuffer::CountedIconPtr> {}; //entryName/icon -> ATTENTION: consider ref-counting for this shared data structure!!! +class IconBuffer::IconDbSequence : public std::queue<Zstring> {}; //entryName +//--------------------------------------------------------------------------------------------------- IconBuffer& IconBuffer::getInstance() @@ -294,6 +312,8 @@ IconBuffer::IconBuffer() : IconBuffer::~IconBuffer() { + //keep non-inline destructor for std::auto_ptr to work with forward declarations + worker->quitThread(); } @@ -311,7 +331,19 @@ bool IconBuffer::requestFileIcon(const Zstring& fileName, wxIcon* icon) if (i != buffer->end()) { if (icon != NULL) - *icon = i->second; + { + HICON clonedIcon = i->second->clone(); //thread safety: make deep copy! + if (clonedIcon != 0) + { + //create wxIcon from handle + wxIcon newIcon; //attention: wxIcon uses reference counting! + newIcon.SetHICON(clonedIcon); //transfer ownership!! + newIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE); + *icon = newIcon; + } + else + *icon = wxNullIcon; + } return true; } @@ -325,31 +357,28 @@ void IconBuffer::setWorkload(const std::vector<Zstring>& load) } -void IconBuffer::insertIntoBuffer(const DefaultChar* entryName, const wxIcon& icon) //called by worker thread +void IconBuffer::insertIntoBuffer(const DefaultChar* entryName, IconHolder& icon) //called by worker thread { - if (icon.IsOk()) //this check won't hurt - { - wxCriticalSectionLocker dummy(*lockIconDB); + wxCriticalSectionLocker dummy(*lockIconDB); - const Zstring fileNameZ = entryName; + //thread safety, ref-counting: (implicitly) make deep copy! + const Zstring fileNameZ = entryName; + const IconBuffer::CountedIconPtr newIcon(new IconBuffer::IconHolder); //exception safety! + newIcon->swap(icon); // - const std::pair<IconDB::iterator, bool> rc = buffer->insert(IconDB::value_type(fileNameZ, icon)); + const std::pair<IconDB::iterator, bool> rc = buffer->insert(IconDB::value_type(fileNameZ, newIcon)); //thread saftey: icon uses ref-counting! But is NOT shared with main thread! - if (rc.second) //if insertion took place - bufSequence->push(fileNameZ); + if (rc.second) //if insertion took place + bufSequence->push(fileNameZ); //note: sharing Zstring with IconDB!!! - assert(buffer->size() == bufSequence->size()); + assert(buffer->size() == bufSequence->size()); - //remove elements if buffer becomes too big: - if (buffer->size() > BUFFER_SIZE) //limit buffer size: critical because GDI resources are limited (e.g. 10000 on XP per process) - { - //remove oldest element - buffer->erase(bufSequence->front()); - bufSequence->pop(); - } + //remove elements if buffer becomes too big: + if (buffer->size() > BUFFER_SIZE) //limit buffer size: critical because GDI resources are limited (e.g. 10000 on XP per process) + { + //remove oldest element + buffer->erase(bufSequence->front()); + bufSequence->pop(); } } - - - diff --git a/library/iconBuffer.h b/library/iconBuffer.h index 703f7eb7..cb2d809f 100644 --- a/library/iconBuffer.h +++ b/library/iconBuffer.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef ICONBUFFER_H_INCLUDED #define ICONBUFFER_H_INCLUDED @@ -8,25 +14,21 @@ header should be used in the windows build only! #include <vector> #include "../shared/zstring.h" #include <memory> +#include <boost/shared_ptr.hpp> class wxCriticalSection; -class WorkerThread; -class IconDB; -class IconDbSequence; class wxIcon; namespace FreeFileSync { + class IconBuffer { - friend class ::WorkerThread; - public: - static IconBuffer& getInstance(); - static const wxIcon& getDirectoryIcon(); //one folder icon should be sufficient... + static IconBuffer& getInstance(); bool requestFileIcon(const Zstring& fileName, wxIcon* icon = NULL); //returns false if icon is not in buffer void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved; @@ -37,16 +39,24 @@ private: IconBuffer(); ~IconBuffer(); + class WorkerThread; + friend class WorkerThread; + + class IconDB; + class IconHolder; + class IconDbSequence; + typedef boost::shared_ptr<IconHolder> CountedIconPtr; + + //methods used by worker thread - void insertIntoBuffer(const DefaultChar* entryName, const wxIcon& icon); + void insertIntoBuffer(const DefaultChar* entryName, IconHolder& icon); //icon is invalidated by this call!! //---------------------- Shared Data ------------------------- std::auto_ptr<wxCriticalSection> lockIconDB; std::auto_ptr<IconDB> buffer; //use synchronisation when accessing this! + std::auto_ptr<IconDbSequence> bufSequence; //save sequence of buffer entry to delete oldest elements (implicitly shared by sharing Zstring with IconDB!!!) //------------------------------------------------------------ - std::auto_ptr<IconDbSequence> bufSequence; //save sequence of buffer entry to delte olderst elements - std::auto_ptr<WorkerThread> worker; }; } diff --git a/library/multithreading.cpp b/library/multithreading.cpp index aea4821b..252884a2 100644 --- a/library/multithreading.cpp +++ b/library/multithreading.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "multithreading.h" #include "statusHandler.h" #include <wx/utils.h> diff --git a/library/multithreading.h b/library/multithreading.h index 21c5bcf2..9017bf41 100644 --- a/library/multithreading.h +++ b/library/multithreading.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef MULTITHREADING_H_INCLUDED #define MULTITHREADING_H_INCLUDED diff --git a/library/pch.h b/library/pch.h index af086418..44a3b574 100644 --- a/library/pch.h +++ b/library/pch.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef FFS_PRECOMPILED_HEADER #define FFS_PRECOMPILED_HEADER @@ -86,6 +92,7 @@ do NOT use in release build! #include <wx/scrolwin.h> #include <wx/notebook.h> #include <wx/help.h> +#include <wx/event.h> //other #include "../shared/tinyxml/tinyxml.h" @@ -93,6 +100,9 @@ do NOT use in release build! //Boost #include <boost/shared_ptr.hpp> +//#include <boost/bind.hpp> <- conflict with #include <boost/lambda/bind.hpp> +#include <boost/scoped_array.hpp> +#include <boost/lambda/lambda.hpp> #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" diff --git a/library/processXml.cpp b/library/processXml.cpp index 4773fb72..69cf8baf 100644 --- a/library/processXml.cpp +++ b/library/processXml.cpp @@ -1,9 +1,14 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "processXml.h" #include "../shared/xmlBase.h" #include <wx/filefn.h> #include <wx/intl.h> #include "../shared/globalFunctions.h" -#include "../shared/fileHandling.h" #include "../shared/standardPaths.h" #include "../shared/stringConv.h" @@ -89,18 +94,18 @@ void xmlAccess::readBatchConfig(const wxString& filename, xmlAccess::XmlBatchCon void xmlAccess::readGlobalSettings(xmlAccess::XmlGlobalSettings& config) { //load XML - if (!wxFileExists(FreeFileSync::getGlobalConfigFile())) - throw XmlError(wxString(_("File does not exist:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile() + wxT("\"")); + if (!wxFileExists(getGlobalConfigFile())) + throw XmlError(wxString(_("File does not exist:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"")); TiXmlDocument doc; - if (!loadXmlDocument(FreeFileSync::getGlobalConfigFile(), XML_GLOBAL_SETTINGS, doc)) - throw XmlError(wxString(_("Error reading file:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile() + wxT("\"")); + if (!loadXmlDocument(getGlobalConfigFile(), XML_GLOBAL_SETTINGS, doc)) + throw XmlError(wxString(_("Error reading file:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"")); FfsXmlParser parser(doc.RootElement()); parser.readXmlGlobalSettings(config); //read GUI layout configuration if (parser.errorsOccured()) - throw XmlError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile() + wxT("\"\n\n") + + throw XmlError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"\n\n") + parser.getErrorMessageFormatted(), XmlError::WARNING); } @@ -138,8 +143,8 @@ void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& outputCfg) //populate and write XML tree if ( !writeXmlGlobalSettings(outputCfg, doc) || //add GUI layout configuration settings - !saveXmlDocument(FreeFileSync::getGlobalConfigFile(), doc)) //save XML - throw XmlError(wxString(_("Error writing file:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile() + wxT("\"")); + !saveXmlDocument(getGlobalConfigFile(), doc)) //save XML + throw XmlError(wxString(_("Error writing file:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"")); return; } @@ -416,9 +421,6 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //last update check readXmlElementLogging("LastCheckForUpdates", global, outputCfg.lastUpdateCheck); - //minimum size (in bytes) for files to be considered for rename-detection - readXmlElementLogging("DetectRenameThreshold", global, outputCfg.detectRenameThreshold); - const TiXmlElement* optionalDialogs = TiXmlHandleConst(root).FirstChild("Shared").FirstChild("ShowOptionalDialogs").ToElement(); @@ -450,12 +452,13 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg readXmlElementLogging("ManualDeletionOnBothSides", mainWindow, outputCfg.gui.deleteOnBothSides); readXmlElementLogging("ManualDeletionUseRecycler", mainWindow, outputCfg.gui.useRecyclerForManualDeletion); - readXmlElementLogging("ShowFileIconsLeft", mainWindow, outputCfg.gui.showFileIconsLeft); - readXmlElementLogging("ShowFileIconsRight", mainWindow, outputCfg.gui.showFileIconsRight); + + readXmlElementLogging("RespectCaseOnSearch", mainWindow, outputCfg.gui.textSearchRespectCase); //########################################################### //read column attributes readXmlAttributeLogging("AutoAdjust", TiXmlHandleConst(mainWindow).FirstChild("LeftColumns").ToElement(), outputCfg.gui.autoAdjustColumnsLeft); + readXmlAttributeLogging("ShowFileIcons", TiXmlHandleConst(mainWindow).FirstChild("LeftColumns").ToElement(), outputCfg.gui.showFileIconsLeft); const TiXmlElement* leftColumn = TiXmlHandleConst(mainWindow).FirstChild("LeftColumns").FirstChild("Column").ToElement(); unsigned int colPos = 0; @@ -472,6 +475,7 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg } readXmlAttributeLogging("AutoAdjust", TiXmlHandleConst(mainWindow).FirstChild("RightColumns").ToElement(), outputCfg.gui.autoAdjustColumnsRight); + readXmlAttributeLogging("ShowFileIcons", TiXmlHandleConst(mainWindow).FirstChild("RightColumns").ToElement(), outputCfg.gui.showFileIconsRight); const TiXmlElement* rightColumn = TiXmlHandleConst(mainWindow).FirstChild("RightColumns").FirstChild("Column").ToElement(); colPos = 0; @@ -817,9 +821,6 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD //last update check addXmlElement("LastCheckForUpdates", inputCfg.lastUpdateCheck, global); - //minimum size (in bytes) for files to be considered for rename-detection - addXmlElement("DetectRenameThreshold", inputCfg.detectRenameThreshold, global); - //optional dialogs TiXmlElement* optionalDialogs = new TiXmlElement("ShowOptionalDialogs"); @@ -866,14 +867,15 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD addXmlElement("ManualDeletionOnBothSides", inputCfg.gui.deleteOnBothSides, mainWindow); addXmlElement("ManualDeletionUseRecycler", inputCfg.gui.useRecyclerForManualDeletion, mainWindow); - addXmlElement("ShowFileIconsLeft", inputCfg.gui.showFileIconsLeft, mainWindow); - addXmlElement("ShowFileIconsRight", inputCfg.gui.showFileIconsRight, mainWindow); + + addXmlElement("RespectCaseOnSearch", inputCfg.gui.textSearchRespectCase, mainWindow); //write column attributes TiXmlElement* leftColumn = new TiXmlElement("LeftColumns"); mainWindow->LinkEndChild(leftColumn); addXmlAttribute("AutoAdjust", inputCfg.gui.autoAdjustColumnsLeft, leftColumn); + addXmlAttribute("ShowFileIcons", inputCfg.gui.showFileIconsLeft, leftColumn); ColumnAttributes columnAtrribLeftCopy = inputCfg.gui.columnAttribLeft; //can't change const vector sort(columnAtrribLeftCopy.begin(), columnAtrribLeftCopy.end(), xmlAccess::sortByPositionOnly); @@ -892,6 +894,7 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD mainWindow->LinkEndChild(rightColumn); addXmlAttribute("AutoAdjust", inputCfg.gui.autoAdjustColumnsRight, rightColumn); + addXmlAttribute("ShowFileIcons", inputCfg.gui.showFileIconsRight, rightColumn); ColumnAttributes columnAtrribRightCopy = inputCfg.gui.columnAttribRight; sort(columnAtrribRightCopy.begin(), columnAtrribRightCopy.end(), xmlAccess::sortByPositionOnly); @@ -956,12 +959,6 @@ int xmlAccess::retrieveSystemLanguage() } -bool xmlAccess::recycleBinAvailable() -{ - return FreeFileSync::recycleBinExists(); -} - - void xmlAccess::OptionalDialogs::resetDialogs() { warningDependentFolders = true; @@ -1007,3 +1004,9 @@ void xmlAccess::readGuiOrBatchConfig(const wxString& filename, XmlGuiConfig& con config = convertBatchToGui(batchCfg); } + + +wxString xmlAccess::getGlobalConfigFile() +{ + return FreeFileSync::getConfigDir() + wxT("GlobalSettings.xml"); +} diff --git a/library/processXml.h b/library/processXml.h index 9cb920d9..ad8465ff 100644 --- a/library/processXml.h +++ b/library/processXml.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef PROCESSXML_H_INCLUDED #define PROCESSXML_H_INCLUDED @@ -20,9 +26,10 @@ enum ColumnTypes REL_PATH, FILENAME, SIZE, - DATE + DATE, + EXTENSION }; -const unsigned int COLUMN_TYPE_COUNT = 6; +const unsigned int COLUMN_TYPE_COUNT = 7; struct ColumnAttrib { @@ -79,7 +86,6 @@ struct XmlBatchConfig }; int retrieveSystemLanguage(); -bool recycleBinAvailable(); struct OptionalDialogs @@ -101,6 +107,8 @@ struct OptionalDialogs }; +wxString getGlobalConfigFile(); + struct XmlGlobalSettings { //--------------------------------------------------------------------- @@ -109,14 +117,12 @@ struct XmlGlobalSettings programLanguage(retrieveSystemLanguage()), ignoreOneHourDiff(false), copyLockedFiles(true), - detectRenameThreshold(1024 *1024), lastUpdateCheck(0) {} int programLanguage; bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change bool copyLockedFiles; //VSS usage - unsigned int detectRenameThreshold; //minimum size (in bytes) for files to be considered for rename-detection long lastUpdateCheck; //time of last update check OptionalDialogs optDialogs; @@ -125,10 +131,10 @@ struct XmlGlobalSettings struct _Gui { _Gui() : - widthNotMaximized(wxDefaultCoord), + widthNotMaximized( wxDefaultCoord), heightNotMaximized(wxDefaultCoord), - posXNotMaximized(wxDefaultCoord), - posYNotMaximized(wxDefaultCoord), + posXNotMaximized( wxDefaultCoord), + posYNotMaximized( wxDefaultCoord), isMaximized(false), autoAdjustColumnsLeft(false), autoAdjustColumnsRight(false), @@ -137,15 +143,24 @@ struct XmlGlobalSettings folderHistRightMax(12), selectedTabBottomLeft(0), deleteOnBothSides(false), - useRecyclerForManualDeletion(recycleBinAvailable()), //enable if OS supports it; else user will have to activate first and then get an error message + useRecyclerForManualDeletion(true), //enable if OS supports it; else user will have to activate first and then get an error message +#ifdef FFS_WIN + textSearchRespectCase(false), +#elif defined FFS_LINUX + textSearchRespectCase(true), +#endif showFileIconsLeft(true), showFileIconsRight(true) { + //default external apps will be translated "on the fly"!!! #ifdef FFS_WIN - externelApplications.push_back(std::make_pair(_("Open with Explorer"), wxT("explorer /select, \"%name\""))); - externelApplications.push_back(std::make_pair(_("Open directly"), wxT("cmd /c start \"\" \"%name\""))); + externelApplications.push_back(std::make_pair(wxT("Open with Explorer"), //mark for extraction: _("Open with Explorer") + wxT("explorer /select, \"%name\""))); + externelApplications.push_back(std::make_pair(wxT("Open directly"), //mark for extraction: _("Open directly") + wxT("cmd /c start \"\" \"%name\""))); #elif defined FFS_LINUX - externelApplications.push_back(std::make_pair(_("Open with Konqueror"), wxT("konqueror \"%dir\""))); + externelApplications.push_back(std::make_pair(wxT("Open with Konqueror"), //mark for extraction: _("Open with Konqueror") + wxT("konqueror \"%dir\""))); #endif } @@ -176,6 +191,7 @@ struct XmlGlobalSettings bool deleteOnBothSides; bool useRecyclerForManualDeletion; + bool textSearchRespectCase; bool showFileIconsLeft; bool showFileIconsRight; } gui; diff --git a/library/resources.cpp b/library/resources.cpp index 3b44a361..ae39d9e7 100644 --- a/library/resources.cpp +++ b/library/resources.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "resources.h" #include <wx/wfstream.h> #include <wx/zipstrm.h> @@ -61,7 +67,7 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation* animation) void GlobalResources::load() const { - wxFFileInputStream input(FreeFileSync::getInstallationDir() + wxT("Resources.dat")); + wxFFileInputStream input(FreeFileSync::getResourceDir() + wxT("Resources.dat")); if (input.IsOk()) //if not... we don't want to react too harsh here { //activate support for .png files diff --git a/library/resources.h b/library/resources.h index c6424dbb..d2e7ce49 100644 --- a/library/resources.h +++ b/library/resources.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef RESOURCES_H_INCLUDED #define RESOURCES_H_INCLUDED diff --git a/library/statistics.cpp b/library/statistics.cpp index f4319686..ac968d1f 100644 --- a/library/statistics.cpp +++ b/library/statistics.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "statistics.h" #include <wx/ffile.h> @@ -16,6 +22,8 @@ RetrieveStatistics::RetrieveStatistics() : RetrieveStatistics::~RetrieveStatistics() { + //keep non-inline destructor for std::auto_ptr to work with forward declaration + //write statistics to a file wxFFile outputFile(wxT("statistics.dat"), wxT("w")); diff --git a/library/statistics.h b/library/statistics.h index a8aa140f..f7bec519 100644 --- a/library/statistics.h +++ b/library/statistics.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef STATISTICS_H_INCLUDED #define STATISTICS_H_INCLUDED diff --git a/library/statusHandler.cpp b/library/statusHandler.cpp index 78dba057..7ac46134 100644 --- a/library/statusHandler.cpp +++ b/library/statusHandler.cpp @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #include "statusHandler.h" #include <wx/app.h> #include <wx/timer.h> diff --git a/library/statusHandler.h b/library/statusHandler.h index cefb129b..a1226c54 100644 --- a/library/statusHandler.h +++ b/library/statusHandler.h @@ -1,3 +1,9 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// #ifndef STATUSHANDLER_H_INCLUDED #define STATUSHANDLER_H_INCLUDED |