summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 16:58:10 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 16:58:10 +0200
commitfefe20351d0720683990b666584b6879c90bd37d (patch)
tree8ab90520ae2123ac84293b0f9cec006317e5fc01 /library
parent1.18 (diff)
downloadFreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.gz
FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.bz2
FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.zip
1.19
Diffstat (limited to 'library')
-rw-r--r--library/CustomGrid.cpp564
-rw-r--r--library/CustomGrid.h113
-rw-r--r--library/customButton.cpp3
-rw-r--r--library/fileHandling.cpp46
-rw-r--r--library/filter.cpp131
-rw-r--r--library/filter.h22
-rw-r--r--library/localization.cpp11
-rw-r--r--library/processXml.cpp92
-rw-r--r--library/processXml.h31
-rw-r--r--library/resources.cpp52
-rw-r--r--library/resources.h51
-rw-r--r--library/statusHandler.cpp3
-rw-r--r--library/statusHandler.h4
-rw-r--r--library/zstring.cpp7
-rw-r--r--library/zstring.h1
15 files changed, 830 insertions, 301 deletions
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp
index faa75b2d..048bc5e0 100644
--- a/library/CustomGrid.cpp
+++ b/library/CustomGrid.cpp
@@ -41,11 +41,14 @@ class CustomGridTable : public wxGridTableBase
public:
CustomGridTable(int initialRows = 0, int initialCols = 0) : //note: initialRows/initialCols MUST match with GetNumberRows()/GetNumberCols() at initialization!!!
wxGridTableBase(),
- COLOR_BLUE( 80, 110, 255),
- COLOR_GREY( 212, 208, 200),
- COLOR_LIGHT_RED( 235, 57, 61),
- COLOR_LIGHT_BLUE( 63, 206, 233),
- COLOR_LIGHT_GREEN(54, 218, 2),
+ COLOR_BLUE( 80, 110, 255),
+ COLOR_GREY( 212, 208, 200),
+ COLOR_CMP_RED( 249, 163, 165),
+ COLOR_CMP_BLUE( 144, 232, 246),
+ COLOR_CMP_GREEN( 147, 253, 159),
+ COLOR_SYNC_BLUE( 201, 203, 247),
+ COLOR_SYNC_GREEN(197, 248, 190),
+ COLOR_YELLOW( 247, 252, 62),
gridDataView(NULL),
lastNrRows(initialRows),
lastNrCols(initialCols) {}
@@ -54,7 +57,7 @@ public:
virtual ~CustomGridTable() {}
- void setGridDataTable(GridView* gridDataView)
+ void setGridDataTable(const GridView* gridDataView)
{
this->gridDataView = gridDataView;
}
@@ -185,17 +188,20 @@ public:
protected:
const wxColour COLOR_BLUE;
const wxColour COLOR_GREY;
- const wxColour COLOR_LIGHT_RED;
- const wxColour COLOR_LIGHT_BLUE;
- const wxColour COLOR_LIGHT_GREEN;
+ const wxColour COLOR_CMP_RED;
+ const wxColour COLOR_CMP_BLUE;
+ const wxColour COLOR_CMP_GREEN;
+ const wxColour COLOR_SYNC_BLUE;
+ const wxColour COLOR_SYNC_GREEN;
+ const wxColour COLOR_YELLOW;
const GridView* gridDataView; //(very fast) access to underlying grid data :)
private:
virtual const wxColour& getRowColor(int row) = 0; //rows that are filtered out are shown in different color
- int lastNrRows;
- int lastNrCols;
+ int lastNrRows;
+ int lastNrCols;
};
@@ -246,8 +252,8 @@ public:
{
switch (getTypeAtPos(col))
{
- case xmlAccess::FULL_NAME:
- return gridLine->fileDescrLeft.fullName.c_str();
+ case xmlAccess::FULL_PATH:
+ return wxString(gridLine->fileDescrLeft.fullName.c_str());
case xmlAccess::FILENAME:
return wxEmptyString;
case xmlAccess::REL_PATH:
@@ -264,8 +270,8 @@ public:
{
switch (getTypeAtPos(col))
{
- case xmlAccess::FULL_NAME:
- return gridLine->fileDescrLeft.fullName.c_str();
+ case xmlAccess::FULL_PATH:
+ return wxString(gridLine->fileDescrLeft.fullName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
case xmlAccess::FILENAME: //filename
return wxString(gridLine->fileDescrLeft.relativeName.c_str()).AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
case xmlAccess::REL_PATH: //relative path
@@ -275,7 +281,7 @@ public:
case xmlAccess::SIZE: //file size
return globalFunctions::includeNumberSeparator(gridLine->fileDescrLeft.fileSize.ToString());
case xmlAccess::DATE: //date
- return FreeFileSync::utcTimeToLocalString(gridLine->fileDescrLeft.lastWriteTimeRaw);
+ return FreeFileSync::utcTimeToLocalString(gridLine->fileDescrLeft.lastWriteTimeRaw, gridLine->fileDescrLeft.fullName);
}
}
}
@@ -315,8 +321,8 @@ public:
{
switch (getTypeAtPos(col))
{
- case xmlAccess::FULL_NAME:
- return gridLine->fileDescrRight.fullName.c_str();
+ case xmlAccess::FULL_PATH:
+ return wxString(gridLine->fileDescrRight.fullName.c_str());
case xmlAccess::FILENAME: //filename
return wxEmptyString;
case xmlAccess::REL_PATH: //relative path
@@ -333,8 +339,8 @@ public:
{
switch (getTypeAtPos(col))
{
- case xmlAccess::FULL_NAME:
- return gridLine->fileDescrRight.fullName.c_str();
+ case xmlAccess::FULL_PATH:
+ return wxString(gridLine->fileDescrRight.fullName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
case xmlAccess::FILENAME: //filename
return wxString(gridLine->fileDescrRight.relativeName.c_str()).AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
case xmlAccess::REL_PATH: //relative path
@@ -344,7 +350,7 @@ public:
case xmlAccess::SIZE: //file size
return globalFunctions::includeNumberSeparator(gridLine->fileDescrRight.fileSize.ToString());
case xmlAccess::DATE: //date
- return FreeFileSync::utcTimeToLocalString(gridLine->fileDescrRight.lastWriteTimeRaw);
+ return FreeFileSync::utcTimeToLocalString(gridLine->fileDescrRight.lastWriteTimeRaw, gridLine->fileDescrRight.fullName);
}
}
}
@@ -376,7 +382,9 @@ class CustomGridTableMiddle : public CustomGridTable
{
public:
//middle grid is created (first wxWidgets internal call to GetNumberCols()) with one column
- CustomGridTableMiddle() : CustomGridTable(0, GetNumberCols()) {} //attention: static binding to virtual GetNumberCols() in a Constructor!
+ CustomGridTableMiddle() :
+ CustomGridTable(0, GetNumberCols()), //attention: static binding to virtual GetNumberCols() in a Constructor!
+ syncPreviewActive(false) {}
virtual int GetNumberCols()
{
@@ -388,35 +396,21 @@ public:
return wxEmptyString;
}
-
virtual wxString GetValue(int row, int col)
{
- const FileCompareLine* gridLine = getRawData(row);
- if (gridLine)
- {
- switch (gridLine->cmpResult)
- {
- case FILE_LEFT_SIDE_ONLY:
- return wxT("<|");
- case FILE_RIGHT_SIDE_ONLY:
- return wxT("|>");
- case FILE_RIGHT_NEWER:
- return wxT(">>");
- case FILE_LEFT_NEWER:
- return wxT("<<");
- case FILE_DIFFERENT:
- return wxT("!=");
- case FILE_EQUAL:
- return wxT("==");
- default:
- assert (false);
- return wxEmptyString;
- }
- }
- //if data is not found:
return wxEmptyString;
}
+ void enableSyncPreview(bool value)
+ {
+ syncPreviewActive = value;
+ }
+
+ bool syncPreviewIsActive() const
+ {
+ return syncPreviewActive;
+ }
+
private:
virtual const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
{
@@ -426,23 +420,46 @@ private:
//mark filtered rows
if (!gridLine->selectedForSynchronization)
return COLOR_BLUE;
- else
+
+ if (syncPreviewActive) //synchronization preview
+ {
+ switch (gridLine->direction)
+ {
+ case SYNC_DIR_LEFT:
+ return COLOR_SYNC_BLUE;
+ case SYNC_DIR_RIGHT:
+ return COLOR_SYNC_GREEN;
+ case SYNC_DIR_NONE:
+ return *wxWHITE;
+ case SYNC_UNRESOLVED_CONFLICT:
+ return COLOR_YELLOW;
+ }
+ }
+ else //comparison results view
+ {
switch (gridLine->cmpResult)
{
case FILE_LEFT_SIDE_ONLY:
case FILE_RIGHT_SIDE_ONLY:
- return COLOR_LIGHT_GREEN;
+ return COLOR_CMP_GREEN;
case FILE_LEFT_NEWER:
case FILE_RIGHT_NEWER:
- return COLOR_LIGHT_BLUE;
+ return COLOR_CMP_BLUE;
case FILE_DIFFERENT:
- return COLOR_LIGHT_RED;
- default:
+ return COLOR_CMP_RED;
+ case FILE_EQUAL:
return *wxWHITE;
+ case FILE_CONFLICT:
+ return COLOR_YELLOW;
}
+ }
}
+
+ //fallback
return *wxWHITE;
}
+
+ bool syncPreviewActive; //determines wheter grid shall show compare result or sync preview
};
//########################################################################################################
@@ -748,6 +765,59 @@ void CustomGrid::DrawColLabel(wxDC& dc, int col)
dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
}
+
+std::set<int> CustomGrid::getAllSelectedRows() const
+{
+ std::set<int> output;
+
+ const wxArrayInt selectedRows = this->GetSelectedRows();
+ if (!selectedRows.IsEmpty())
+ {
+ for (unsigned int i = 0; i < selectedRows.GetCount(); ++i)
+ output.insert(selectedRows[i]);
+ }
+
+ if (!this->GetSelectedCols().IsEmpty()) //if a column is selected this is means all rows are marked for deletion
+ {
+ for (int k = 0; k < const_cast<CustomGrid*>(this)->GetNumberRows(); ++k) //messy wxGrid implementation...
+ output.insert(k);
+ }
+
+ const wxGridCellCoordsArray singlySelected = this->GetSelectedCells();
+ if (!singlySelected.IsEmpty())
+ {
+ for (unsigned int k = 0; k < singlySelected.GetCount(); ++k)
+ output.insert(singlySelected[k].GetRow());
+ }
+
+ const wxGridCellCoordsArray tmpArrayTop = this->GetSelectionBlockTopLeft();
+ if (!tmpArrayTop.IsEmpty())
+ {
+ wxGridCellCoordsArray tmpArrayBottom = this->GetSelectionBlockBottomRight();
+
+ unsigned int arrayCount = tmpArrayTop.GetCount();
+
+ if (arrayCount == tmpArrayBottom.GetCount())
+ {
+ for (unsigned int i = 0; i < arrayCount; ++i)
+ {
+ const int rowTop = tmpArrayTop[i].GetRow();
+ const int rowBottom = tmpArrayBottom[i].GetRow();
+
+ for (int k = rowTop; k <= rowBottom; ++k)
+ output.insert(k);
+ }
+ }
+ }
+
+ //some exception: also add current cursor row to selection if there are no others... hopefully improving usability
+ if (output.empty() && this->isLeadGrid())
+ output.insert(const_cast<CustomGrid*>(this)->GetCursorRow()); //messy wxGrid implementation...
+
+ return output;
+}
+
+
//############################################################################################
//CustomGrid specializations
@@ -837,6 +907,26 @@ private:
const CustomGridTableRim* const m_gridDataTable;
};
+//----------------------------------------------------------------------------------------
+
+
+void CustomGridRim::initSettings(const bool showFileIcons,
+ CustomGrid* gridLeft,
+ CustomGrid* gridRight,
+ CustomGrid* gridMiddle,
+ const GridView* gridDataView)
+{
+ //these grids will scroll together
+ m_gridLeft = gridLeft;
+ m_gridRight = gridRight;
+ m_gridMiddle = gridMiddle;
+
+ //set underlying grid data
+ assert(gridDataTable);
+ gridDataTable->setGridDataTable(gridDataView);
+
+ enableFileIcons(showFileIcons);
+}
void CustomGridRim::updateGridSizes()
@@ -851,7 +941,7 @@ xmlAccess::ColumnAttributes CustomGridRim::getDefaultColumnAttributes()
xmlAccess::ColumnAttributes defaultColumnSettings;
xmlAccess::ColumnAttrib newEntry;
- newEntry.type = xmlAccess::FULL_NAME;
+ newEntry.type = xmlAccess::FULL_PATH;
newEntry.visible = false;
newEntry.position = 0;
newEntry.width = 150;
@@ -990,8 +1080,8 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType)
{
switch (colType)
{
- case xmlAccess::FULL_NAME:
- return _("Full name");
+ case xmlAccess::FULL_PATH:
+ return _("Full path");
case xmlAccess::FILENAME:
return _("Filename");
case xmlAccess::REL_PATH:
@@ -1002,13 +1092,14 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType)
return _("Size");
case xmlAccess::DATE:
return _("Date");
- default:
- return wxEmptyString;
}
-}
+ return wxEmptyString; //dummy
+}
//----------------------------------------------------------------------------------------
+
+
CustomGridLeft::CustomGridLeft(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
@@ -1029,25 +1120,14 @@ bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectio
}
-void CustomGridLeft::initSettings(const bool showFileIcons,
- CustomGrid* gridLeft,
- CustomGrid* gridRight,
- CustomGrid* gridMiddle,
- GridView* gridDataView)
+void CustomGridLeft::enableFileIcons(const bool value)
{
- //these grids will scroll together
- m_gridLeft = gridLeft;
- m_gridRight = gridRight;
- m_gridMiddle = gridMiddle;
-
- //set underlying grid data
- assert(gridDataTable);
- gridDataTable->setGridDataTable(gridDataView);
-
- if (showFileIcons)
+ if (value)
SetDefaultRenderer(new GridCellRenderer<true, true>(gridDataTable)); //SetDefaultRenderer takes ownership!
else
SetDefaultRenderer(new GridCellRenderer<true, false>(gridDataTable));
+
+ Refresh();
}
@@ -1085,25 +1165,14 @@ bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelecti
}
-void CustomGridRight::initSettings(const bool showFileIcons,
- CustomGrid* gridLeft,
- CustomGrid* gridRight,
- CustomGrid* gridMiddle,
- GridView* gridDataView)
+void CustomGridRight::enableFileIcons(const bool value)
{
- //these grids will scroll together
- m_gridLeft = gridLeft;
- m_gridRight = gridRight;
- m_gridMiddle = gridMiddle;
-
- //set underlying grid data
- assert(gridDataTable);
- gridDataTable->setGridDataTable(gridDataView);
-
- if (showFileIcons)
+ if (value)
SetDefaultRenderer(new GridCellRenderer<false, true>(gridDataTable)); //SetDefaultRenderer takes ownership!
else
SetDefaultRenderer(new GridCellRenderer<false, false>(gridDataTable));
+
+ Refresh();
}
@@ -1123,6 +1192,19 @@ void CustomGridRight::DoPrepareDC(wxDC& dc)
//----------------------------------------------------------------------------------------
+//define new event types
+const wxEventType FFS_CHECK_ROWS_EVENT = wxNewEventType(); //attention! do NOT place in header to keep (generated) id unique!
+const wxEventType FFS_SYNC_DIRECTION_EVENT = wxNewEventType();
+
+const int CHECK_BOX_IMAGE = 11; //width of checkbox image
+const int CHECK_BOX_WIDTH = CHECK_BOX_IMAGE + 3; //width of first block
+
+// cell:
+// ----------------------------------
+// | checkbox | left | middle | right|
+// ----------------------------------
+
+
CustomGridMiddle::CustomGridMiddle(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
@@ -1130,25 +1212,155 @@ CustomGridMiddle::CustomGridMiddle(wxWindow *parent,
long style,
const wxString& name) :
CustomGrid(parent, id, pos, size, style, name),
+ selectionRowBegin(-1),
+ selectionPos(BLOCKPOS_CHECK_BOX),
+ highlightedRow(-1),
+ highlightedPos(BLOCKPOS_CHECK_BOX),
gridDataTable(NULL)
{
- const wxString header = _("Legend");
- wxString toolTip = header + wxT("\n") +
- wxString().Pad(header.Len(), wxChar('-')) + wxT("\n") +
- _("<| file on left side only\n") +
- _("|> file on right side only\n") +
- _("<< left file is newer\n") +
- _(">> right file is newer\n") +
- _("!= files are different\n") +
- _("== files are equal\n\n");
- GetGridWindow()->SetToolTip(toolTip);
+ //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);
+}
+
+
+void CustomGridMiddle::OnMouseMovement(wxMouseEvent& event)
+{
+ const int highlightedRowOld = highlightedRow;
+
+ if (selectionRowBegin == -1) //change highlightning only if currently not dragging mouse
+ {
+ highlightedRow = mousePosToRow(event.GetPosition(), &highlightedPos);
+ if (highlightedRow >= 0) RefreshRow(highlightedRow);
+ if ( highlightedRowOld >= 0 &&
+ highlightedRow != highlightedRowOld)
+ RefreshRow(highlightedRowOld);
+ }
+
+ event.Skip();
+}
+
+
+void CustomGridMiddle::RefreshRow(int row)
+{
+ wxRect rectScrolled(CellToRect(row, 0));
+ CalcScrolledPosition(rectScrolled.x, rectScrolled.y, &rectScrolled.x, &rectScrolled.y);
+
+ GetGridWindow()->Refresh(false, &rectScrolled); //note: CellToRect() and YToRow work on m_gridWindow NOT on the whole grid!
+}
+
+
+void CustomGridMiddle::OnLeaveWindow(wxMouseEvent& event)
+{
+ highlightedRow = -1;
+ highlightedPos = BLOCKPOS_CHECK_BOX;
+ Refresh();
+}
+
+
+void CustomGridMiddle::OnLeftMouseDown(wxMouseEvent& event)
+{
+ selectionRowBegin = mousePosToRow(event.GetPosition(), &selectionPos);
+ event.Skip();
+}
+
+
+void CustomGridMiddle::OnLeftMouseUp(wxMouseEvent& event)
+{
+ const int rowEndFiltering = mousePosToRow(event.GetPosition());
+
+ if (0 <= selectionRowBegin && 0 <= rowEndFiltering)
+ {
+ switch (selectionPos)
+ {
+ case BLOCKPOS_CHECK_BOX:
+ {
+ //create a custom event
+ FFSCheckRowsEvent evt(selectionRowBegin, rowEndFiltering);
+ AddPendingEvent(evt);
+ }
+ break;
+ case BLOCKPOS_LEFT:
+ {
+ //create a custom event
+ FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_LEFT);
+ AddPendingEvent(evt);
+ }
+ break;
+ case BLOCKPOS_MIDDLE:
+ {
+ //create a custom event
+ FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_NONE);
+ AddPendingEvent(evt);
+ }
+ break;
+ case BLOCKPOS_RIGHT:
+ {
+ //create a custom event
+ FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_RIGHT);
+ AddPendingEvent(evt);
+ }
+ break;
+ }
+ }
+ selectionRowBegin = -1;
+ selectionPos = BLOCKPOS_CHECK_BOX;
+
+ ClearSelection();
+ event.Skip();
+}
+
+
+int CustomGridMiddle::mousePosToRow(const wxPoint pos, BlockPosition* block)
+{
+ int row = -1;
+ int x = -1;
+ int y = -1;
+ CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
+ if (x >= 0 && y >= 0)
+ {
+ row = YToRow(y);
+
+ //determine blockposition within cell (optional)
+ if (block)
+ {
+ *block = BLOCKPOS_CHECK_BOX; //default
+ if (gridDataTable->syncPreviewIsActive() &&
+ row >= 0)
+ {
+ // cell:
+ // ----------------------------------
+ // | checkbox | left | middle | right|
+ // ----------------------------------
+
+ const wxRect rect = CellToRect(row, 0);
+ if (rect.GetWidth() > CHECK_BOX_WIDTH)
+ {
+ const double blockWidth = (rect.GetWidth() - CHECK_BOX_WIDTH) / 3.0;
+ if (rect.GetX() + CHECK_BOX_WIDTH <= x && x < rect.GetX() + rect.GetWidth())
+ {
+ if (x - (rect.GetX() + CHECK_BOX_WIDTH) < blockWidth)
+ *block = BLOCKPOS_LEFT;
+ else if (x - (rect.GetX() + CHECK_BOX_WIDTH) < 2 * blockWidth)
+ *block = BLOCKPOS_MIDDLE;
+ else
+ *block = BLOCKPOS_RIGHT;
+ }
+ }
+ }
+ }
+ }
+ return row;
}
void CustomGridMiddle::initSettings(CustomGrid* gridLeft,
CustomGrid* gridRight,
CustomGrid* gridMiddle,
- FreeFileSync::GridView* gridDataView)
+ const FreeFileSync::GridView* gridDataView)
{
//these grids will scroll together
m_gridLeft = gridLeft;
@@ -1174,6 +1386,40 @@ void CustomGridMiddle::SetScrollbar(int orientation, int position, int thumbSize
}
#endif
+
+void CustomGridMiddle::enableSyncPreview(bool value)
+{
+ assert(gridDataTable);
+ gridDataTable->enableSyncPreview(value);
+
+ //update legend
+ wxString toolTip;
+
+ if (gridDataTable->syncPreviewIsActive()) //synchronization preview
+ {
+ const wxString header = _("Synchronization Preview");
+ toolTip = header + wxT("\n") + wxString().Pad(header.Len(), wxChar('-')) + wxT("\n");
+ toolTip += wxString(_("<- copy to left side\n")) +
+ _("-> copy to right side\n") +
+ wxT(" ")+ _("- do not copy\n") +
+ _("flash conflict\n");
+ }
+ else //compare results view
+ {
+ const wxString header = _("Comparison Result");
+ toolTip = header + wxT("\n") + wxString().Pad(header.Len(), wxChar('-')) + wxT("\n");
+ toolTip += wxString(_("<| file on left side only\n")) +
+ _("|> file on right side only\n") +
+ _("<< left file is newer\n") +
+ _(">> right file is newer\n") +
+ _("!= files are different\n") +
+ _("== files are equal\n") +
+ _("flash conflict\n");
+ }
+ GetGridColLabelWindow()->SetToolTip(toolTip);
+}
+
+
void CustomGridMiddle::updateGridSizes()
{
assert(gridDataTable);
@@ -1184,7 +1430,7 @@ void CustomGridMiddle::updateGridSizes()
class GridCellRendererMiddle : public wxGridCellStringRenderer
{
public:
- GridCellRendererMiddle(CustomGridTable* gridDataTable) : m_gridDataTable(gridDataTable) {};
+ GridCellRendererMiddle(const CustomGridMiddle* middleGrid) : m_gridMiddle(middleGrid) {};
virtual void Draw(wxGrid& grid,
@@ -1195,36 +1441,112 @@ public:
bool isSelected)
{
//retrieve grid data
- const FileCompareLine* rowData = m_gridDataTable->getRawData(row);
- if (!rowData) //no valid row
+ const FileCompareLine* const rowData = m_gridMiddle->gridDataTable->getRawData(row);
+ if (rowData) //no valid row
{
- wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
- return;
- }
+ if (rect.GetWidth() > CHECK_BOX_WIDTH)
+ {
+ wxRect rectShrinked(rect);
- const int shift = std::min(11 + 3, rect.GetWidth()); //11 is width of checkbox image
+ //clean first block of rect that will receive image of checkbox
+ rectShrinked.SetWidth(CHECK_BOX_WIDTH);
+ wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
- wxRect rectShrinked(rect);
+ //print image into first block
+ rectShrinked.SetX(rect.GetX() + 1);
+ bool selected = rowData->selectedForSynchronization;
- //clean first block of rect that will receive image of checkbox
- rectShrinked.SetWidth(shift);
- wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+ //HIGHLIGHTNING:
+ if ( row == m_gridMiddle->highlightedRow &&
+ m_gridMiddle->highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX)
+ selected = !selected;
- //print image into first block
- rectShrinked.SetX(rect.GetX() + 1);
- if (rowData->selectedForSynchronization)
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
- else
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxFalse, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+ if (selected)
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+ else
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxFalse, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
- //print second block (default): display compare result
- rectShrinked.SetWidth(rect.GetWidth() - shift);
- rectShrinked.SetX(rect.GetX() + shift);
- wxGridCellStringRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+ //clean remaining block of rect that will receive image of checkbox/directions
+ rectShrinked.SetWidth(rect.GetWidth() - CHECK_BOX_WIDTH);
+ rectShrinked.SetX(rect.GetX() + CHECK_BOX_WIDTH);
+ wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+
+ //print remaining block
+ if (m_gridMiddle->gridDataTable->syncPreviewIsActive()) //synchronization preview
+ {
+ //print sync direction into second block
+
+ //HIGHLIGHTNING:
+ if (row == m_gridMiddle->highlightedRow && m_gridMiddle->highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX)
+ switch (m_gridMiddle->highlightedPos)
+ {
+ case CustomGridMiddle::BLOCKPOS_CHECK_BOX:
+ break;
+ case CustomGridMiddle::BLOCKPOS_LEFT:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirLeftSmall, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+ break;
+ case CustomGridMiddle::BLOCKPOS_MIDDLE:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirNoneSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case CustomGridMiddle::BLOCKPOS_RIGHT:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirRightSmall, rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
+ break;
+ }
+ else //default
+ switch (rowData->direction)
+ {
+ case SYNC_DIR_LEFT:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirLeftSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case SYNC_DIR_RIGHT:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirRightSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case SYNC_DIR_NONE:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirNoneSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case SYNC_UNRESOLVED_CONFLICT:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapConflictSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ }
+ }
+ else //comparison results view
+ {
+ switch (rowData->cmpResult)
+ {
+ case FILE_LEFT_SIDE_ONLY:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapLeftOnlySmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_RIGHT_SIDE_ONLY:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapRightOnlySmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_LEFT_NEWER:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapLeftNewerSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_RIGHT_NEWER:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapRightNewerSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_DIFFERENT:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapDifferentSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_EQUAL:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapEqualSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_CONFLICT:
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapConflictSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ }
+ }
+
+ return;
+ }
+ }
+
+ //fallback
+ wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
}
private:
- const CustomGridTable* const m_gridDataTable;
+ const CustomGridMiddle* const m_gridMiddle;
};
@@ -1234,7 +1556,7 @@ bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelect
SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
//display checkboxes (representing bool values) if row is enabled for synchronization
- SetDefaultRenderer(new GridCellRendererMiddle(gridDataTable)); //SetDefaultRenderer takes ownership!
+ SetDefaultRenderer(new GridCellRendererMiddle(this)); //SetDefaultRenderer takes ownership!
return true;
}
diff --git a/library/CustomGrid.h b/library/CustomGrid.h
index 802db231..89ec39d0 100644
--- a/library/CustomGrid.h
+++ b/library/CustomGrid.h
@@ -10,6 +10,7 @@
class CustomGridTable;
class CustomGridTableRim;
class CustomGridTableMiddle;
+class GridCellRendererMiddle;
namespace FreeFileSync
{
@@ -44,6 +45,8 @@ public:
virtual void DrawColLabel(wxDC& dc, int col);
+ std::set<int> getAllSelectedRows() const;
+
//set sort direction indicator on UI
void setSortMarker(const int sortColumn, const wxBitmap* bitmap = &wxNullBitmap);
@@ -79,6 +82,12 @@ public:
~CustomGridRim() {}
+ void initSettings(const bool showFileIcons, //workaround: though this coding better belongs into a constructor
+ CustomGrid* gridLeft, //this is not possible due to source code generation (information not available at time of construction)
+ CustomGrid* gridRight,
+ CustomGrid* gridMiddle,
+ const FreeFileSync::GridView* gridDataView);
+
//notify wxGrid that underlying table size has changed
void updateGridSizes();
@@ -88,9 +97,10 @@ public:
void setColumnAttributes(const xmlAccess::ColumnAttributes& attr);
xmlAccess::ColumnTypes getTypeAtPos(unsigned pos) const;
-
static wxString getTypeName(xmlAccess::ColumnTypes colType);
+ virtual void enableFileIcons(const bool value) = 0;
+
protected:
CustomGridTableRim* gridDataTable;
@@ -113,11 +123,7 @@ public:
virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
- void initSettings(const bool showFileIcons, //workaround: though this coding better belongs into a constructor
- CustomGrid* gridLeft, //this is not possible due to source code generation (information not available at time of construction)
- CustomGrid* gridRight,
- CustomGrid* gridMiddle,
- FreeFileSync::GridView* gridDataView);
+ virtual void enableFileIcons(const bool value);
//this method is called when grid view changes: useful for parallel updating of multiple grids
virtual void DoPrepareDC(wxDC& dc);
@@ -138,11 +144,7 @@ public:
virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
- void initSettings(const bool showFileIcons, //workaround: though this coding better belongs into a constructor
- CustomGrid* gridLeft, //this is not possible due to source code generation (information not available at time of construction)
- CustomGrid* gridRight,
- CustomGrid* gridMiddle,
- FreeFileSync::GridView* gridDataView);
+ virtual void enableFileIcons(const bool value);
//this method is called when grid view changes: useful for parallel updating of multiple grids
virtual void DoPrepareDC(wxDC& dc);
@@ -151,6 +153,8 @@ public:
class CustomGridMiddle : public CustomGrid
{
+ friend class GridCellRendererMiddle;
+
public:
CustomGridMiddle(wxWindow *parent,
wxWindowID id,
@@ -166,7 +170,9 @@ public:
void initSettings(CustomGrid* gridLeft, //workaround: though this coding better belongs into a constructor
CustomGrid* gridRight, //this is not possible due to source code generation (information not available at time of construction)
CustomGrid* gridMiddle,
- FreeFileSync::GridView* gridDataView);
+ const FreeFileSync::GridView* gridDataView);
+
+ void enableSyncPreview(bool value);
//notify wxGrid that underlying table size has changed
void updateGridSizes();
@@ -179,7 +185,90 @@ public:
virtual void DoPrepareDC(wxDC& dc);
private:
+ void OnMouseMovement(wxMouseEvent& event);
+ void OnLeaveWindow(wxMouseEvent& event);
+ void OnLeftMouseDown(wxMouseEvent& event);
+ void OnLeftMouseUp(wxMouseEvent& event);
+
+ //small helper methods
+ void RefreshRow(int row);
+ enum BlockPosition //each cell can be divided into four blocks concerning mouse selections
+ {
+ BLOCKPOS_CHECK_BOX,
+ BLOCKPOS_LEFT,
+ BLOCKPOS_MIDDLE,
+ BLOCKPOS_RIGHT
+ };
+ int mousePosToRow(const wxPoint pos, BlockPosition* block = NULL);
+
+ //variables for selecting sync direction
+ int selectionRowBegin;
+ BlockPosition selectionPos;
+
+ //variables for highlightning on mouse-over
+ int highlightedRow;
+ BlockPosition highlightedPos;
+
CustomGridTableMiddle* gridDataTable;
};
+//custom events for middle grid:
+
+//--------------------------------------------------------------------------------------------
+//(UN-)CHECKING ROWS FROM SYNCHRONIZATION
+
+extern const wxEventType FFS_CHECK_ROWS_EVENT; //define new event type
+
+class FFSCheckRowsEvent : public wxCommandEvent
+{
+public:
+ FFSCheckRowsEvent(const int from, const int to) :
+ wxCommandEvent(FFS_CHECK_ROWS_EVENT),
+ rowFrom(from),
+ rowTo(to) {}
+
+ virtual wxEvent* Clone() const
+ {
+ return new FFSCheckRowsEvent(rowFrom, rowTo);
+ }
+
+ const int rowFrom;
+ const int rowTo;
+};
+
+typedef void (wxEvtHandler::*FFSCheckRowsEventFunction)(FFSCheckRowsEvent&);
+
+#define FFSCheckRowsEventHandler(func) \
+ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(FFSCheckRowsEventFunction, &func)
+
+//--------------------------------------------------------------------------------------------
+//SELECTING SYNC DIRECTION
+
+extern const wxEventType FFS_SYNC_DIRECTION_EVENT; //define new event type
+
+class FFSSyncDirectionEvent : public wxCommandEvent
+{
+public:
+ FFSSyncDirectionEvent(const int from, const int to, const FreeFileSync::SyncDirection dir) :
+ wxCommandEvent(FFS_SYNC_DIRECTION_EVENT),
+ rowFrom(from),
+ rowTo(to),
+ direction(dir) {}
+
+ virtual wxEvent* Clone() const
+ {
+ return new FFSSyncDirectionEvent(rowFrom, rowTo, direction);
+ }
+
+ const int rowFrom;
+ const int rowTo;
+ const FreeFileSync::SyncDirection direction;
+};
+
+typedef void (wxEvtHandler::*FFSSyncDirectionEventFunction)(FFSSyncDirectionEvent&);
+
+#define FFSSyncDirectionEventHandler(func) \
+ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(FFSSyncDirectionEventFunction, &func)
+
+
#endif // CUSTOMGRID_H_INCLUDED
diff --git a/library/customButton.cpp b/library/customButton.cpp
index 02cfdad0..fc686d3f 100644
--- a/library/customButton.cpp
+++ b/library/customButton.cpp
@@ -126,6 +126,9 @@ void linearInterpolation(wxImage& img)
wxBitmap wxButtonWithImage::createBitmapFromText(const wxString& text)
{
+ if (text.empty())
+ return wxBitmap();
+
wxFont currentFont = wxBitmapButton::GetFont();
wxColor textColor = wxBitmapButton::GetForegroundColour();
diff --git a/library/fileHandling.cpp b/library/fileHandling.cpp
index 4f8caec6..b6d3d9d7 100644
--- a/library/fileHandling.cpp
+++ b/library/fileHandling.cpp
@@ -284,18 +284,25 @@ private:
};
+class KernelDllHandler //dynamically load windows API functions
+{
+ typedef DWORD WINAPI (*GetFinalPath)(
+ HANDLE hFile,
+ LPTSTR lpszFilePath,
+ DWORD cchFilePath,
+ DWORD dwFlags);
-typedef DWORD WINAPI (*GetFinalPath)(
- HANDLE hFile,
- LPTSTR lpszFilePath,
- DWORD cchFilePath,
- DWORD dwFlags);
+public:
+ static const KernelDllHandler& getInstance() //lazy creation of KernelDllHandler
+ {
+ static KernelDllHandler instance;
+ return instance;
+ }
+ GetFinalPath getFinalPathNameByHandle;
-class DllHandler //dynamically load windows API functions
-{
-public:
- DllHandler() :
+private:
+ KernelDllHandler() :
getFinalPathNameByHandle(NULL),
hKernel(NULL)
{
@@ -305,26 +312,15 @@ public:
getFinalPathNameByHandle = reinterpret_cast<GetFinalPath>(::GetProcAddress(hKernel, "GetFinalPathNameByHandleW")); //load unicode version!
}
- ~DllHandler()
+ ~KernelDllHandler()
{
if (hKernel) ::FreeLibrary(hKernel);
}
- GetFinalPath getFinalPathNameByHandle;
-
-private:
HINSTANCE hKernel;
};
-inline
-DllHandler& getDllHandler() //lazy creation of DllHandler
-{
- static DllHandler instance;
- return instance;
-}
-
-
Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target path of symbolic link to a directory
{
//open handle to target of symbolic link
@@ -340,13 +336,13 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa
CloseHandleOnExit dummy(hDir);
- if (getDllHandler().getFinalPathNameByHandle == NULL )
+ if (KernelDllHandler::getInstance().getFinalPathNameByHandle == NULL )
throw FileError(Zstring(_("Error loading library function:")) + wxT("\n\"") + wxT("GetFinalPathNameByHandleW") + wxT("\""));
const unsigned BUFFER_SIZE = 10000;
TCHAR targetPath[BUFFER_SIZE];
- const DWORD rv = getDllHandler().getFinalPathNameByHandle(
+ const DWORD rv = KernelDllHandler::getInstance().getFinalPathNameByHandle(
hDir,
targetPath,
BUFFER_SIZE,
@@ -669,8 +665,8 @@ inline
void setWin32FileInformation(const FILETIME& lastWriteTime, const DWORD fileSizeHigh, const DWORD fileSizeLow, FreeFileSync::FileInfo& output)
{
//convert UTC FILETIME to ANSI C format (number of seconds since Jan. 1st 1970 UTC)
- wxLongLong writeTimeLong(lastWriteTime.dwHighDateTime, lastWriteTime.dwLowDateTime);
- writeTimeLong /= 10000000; //reduce precision to 1 second (FILETIME has unit 10^-7 s)
+ wxLongLong writeTimeLong(wxInt32(lastWriteTime.dwHighDateTime), lastWriteTime.dwLowDateTime);
+ writeTimeLong /= 10000000; //reduce precision to 1 second (FILETIME has unit 10^-7 s)
writeTimeLong -= wxLongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s
output.lastWriteTimeRaw = writeTimeLong;
diff --git a/library/filter.cpp b/library/filter.cpp
index d5255367..d9ba8c5f 100644
--- a/library/filter.cpp
+++ b/library/filter.cpp
@@ -5,6 +5,8 @@
#include <vector>
#include "resources.h"
+using FreeFileSync::FilterProcess;
+
void compoundStringToTable(const Zstring& compoundInput, const DefaultChar* delimiter, std::vector<Zstring>& output)
{
@@ -42,21 +44,6 @@ void mergeVectors(std::vector<Zstring>& changing, const std::vector<Zstring>& in
}
-inline
-void formatFilterString(Zstring& filter)
-{
-#ifdef FFS_WIN
- //Windows does NOT distinguish between upper/lower-case
- filter.MakeLower();
-#elif defined FFS_LINUX
- //Linux DOES distinguish between upper/lower-case
-//nothing to do here
-#else
- adapt;
-#endif
-}
-
-
std::vector<Zstring> compoundStringToFilter(const Zstring& filterString)
{
//delimiters may be ';' or '\n'
@@ -78,12 +65,26 @@ std::vector<Zstring> compoundStringToFilter(const Zstring& filterString)
inline
void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, std::set<Zstring>& directoryFilter)
{
- //Test if filtername ends with GlobalResources::FILE_NAME_SEPARATOR, ignoring '*' and '?'.
- //If so, treat as filter for directory and add to directoryFilter.
- if (!filtername.empty())
+ Zstring filterFormatted = filtername;
+
+#ifdef FFS_WIN
+ //Windows does NOT distinguish between upper/lower-case
+ filterFormatted.MakeLower();
+#elif defined FFS_LINUX
+ //Linux DOES distinguish between upper/lower-case
+//nothing to do here
+#endif
+
+ //remove leading separators (keep BEFORE test for Zstring::empty()!)
+ if (filterFormatted.length() > 0 && *filterFormatted.c_str() == GlobalResources::FILE_NAME_SEPARATOR)
+ filterFormatted = Zstring(filterFormatted.c_str() + 1);
+
+ if (!filterFormatted.empty())
{
- const DefaultChar* filter = filtername.c_str();
- int i = filtername.length() - 1;
+ //Test if filterFormatted ends with GlobalResources::FILE_NAME_SEPARATOR, ignoring '*' and '?'.
+ //If so, treat as filter for directory and add to directoryFilter.
+ const DefaultChar* filter = filterFormatted.c_str();
+ int i = filterFormatted.length() - 1;
while (filter[i] == DefaultChar('*') || filter[i] == DefaultChar('?'))
{
--i;
@@ -94,37 +95,46 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st
if (i >= 0 && filter[i] == GlobalResources::FILE_NAME_SEPARATOR) //last FILE_NAME_SEPARATOR found
{
- if (i != int(filtername.length()) - 1) // "name\*"
+ if (i != int(filterFormatted.length()) - 1) // "name\*"
{
- fileFilter.insert(filtername);
- directoryFilter.insert(filtername);
+ fileFilter.insert(filterFormatted);
+ directoryFilter.insert(filterFormatted);
}
- //else: "name\" -> not inserted directly
+ //else // "name\"
if (i > 0) // "name\*" or "name\": add "name" to directory filter
- directoryFilter.insert(Zstring(filtername.c_str(), i));
+ directoryFilter.insert(Zstring(filterFormatted.c_str(), i));
}
else
{
- fileFilter.insert(filtername);
- directoryFilter.insert(filtername);
+ fileFilter.insert(filterFormatted);
+ directoryFilter.insert(filterFormatted);
}
}
}
inline
-bool matchesFilter(const Zstring& name, const std::set<Zstring>& filter)
+bool matchesFilter(const DefaultChar* name, const std::set<Zstring>& filter)
{
+#ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case
+ Zstring nameFormatted = name;
+ nameFormatted.MakeLower();
+#elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case
+ const DefaultChar* const nameFormatted = name; //nothing to do here
+#endif
+
for (std::set<Zstring>::iterator j = filter.begin(); j != filter.end(); ++j)
- if (name.Matches(*j))
+ if (Zstring::Matches(nameFormatted, *j))
return true;
return false;
}
+//##############################################################
+
-void FreeFileSync::filterGridData(FolderComparison& folderCmp, const wxString& includeFilter, const wxString& excludeFilter)
+FilterProcess::FilterProcess(const wxString& includeFilter, const wxString& excludeFilter)
{
//no need for regular expressions! In tests wxRegex was by factor of 10 slower than wxString::Matches()!!
@@ -133,26 +143,37 @@ void FreeFileSync::filterGridData(FolderComparison& folderCmp, const wxString& i
std::vector<Zstring> includeList = compoundStringToFilter(includeFilter.c_str());
std::vector<Zstring> excludeList = compoundStringToFilter(excludeFilter.c_str());
-//##############################################################
//setup include/exclude filters for files and directories
- std::set<Zstring> filterFileIn;
- std::set<Zstring> filterFolderIn;
for (std::vector<Zstring>::iterator i = includeList.begin(); i != includeList.end(); ++i)
- {
- formatFilterString(*i); //format entry
addFilterEntry(*i, filterFileIn, filterFolderIn);
- }
- std::set<Zstring> filterFileEx;
- std::set<Zstring> filterFolderEx;
for (std::vector<Zstring>::iterator i = excludeList.begin(); i != excludeList.end(); ++i)
- {
- formatFilterString(*i); //format entry
addFilterEntry(*i, filterFileEx, filterFolderEx);
- }
+}
+
+
+bool FilterProcess::matchesFileFilter(const DefaultChar* relFilename) const
+{
+ if ( matchesFilter(relFilename, filterFileIn) && //process include filters
+ !matchesFilter(relFilename, filterFileEx)) //process exclude filters
+ return true;
+ else
+ return false;
+}
+
+
+bool FilterProcess::matchesDirFilter(const DefaultChar* relDirname) const
+{
+ if ( matchesFilter(relDirname, filterFolderIn) && //process include filters
+ !matchesFilter(relDirname, filterFolderEx)) //process exclude filters
+ return true;
+ else
+ return false;
+}
-//##############################################################
+void FilterProcess::filterGridData(FolderComparison& folderCmp) const
+{
//execute filtering...
for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j)
{
@@ -160,18 +181,10 @@ void FreeFileSync::filterGridData(FolderComparison& folderCmp, const wxString& i
for (FileComparison::iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
{
- Zstring filenameLeft = i->fileDescrLeft.fullName;
- Zstring filenameRight = i->fileDescrRight.fullName;
-
- formatFilterString(filenameLeft);
- formatFilterString(filenameRight);
-
-
//left hand side
if (i->fileDescrLeft.objType == FileDescrLine::TYPE_FILE)
{
- if ( !matchesFilter(filenameLeft, filterFileIn) || //process include filters
- matchesFilter(filenameLeft, filterFileEx)) //process exclude filters
+ if (!matchesFileFilter(i->fileDescrLeft.relativeName.c_str()))
{
i->selectedForSynchronization = false;
continue;
@@ -179,19 +192,16 @@ void FreeFileSync::filterGridData(FolderComparison& folderCmp, const wxString& i
}
else if (i->fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
{
- if ( !matchesFilter(filenameLeft, filterFolderIn) || //process include filters
- matchesFilter(filenameLeft, filterFolderEx)) //process exclude filters
+ if (!matchesDirFilter(i->fileDescrLeft.relativeName.c_str()))
{
i->selectedForSynchronization = false;
continue;
}
}
-
//right hand side
- if (i->fileDescrRight.objType == FileDescrLine::TYPE_FILE)
+ else if (i->fileDescrRight.objType == FileDescrLine::TYPE_FILE)
{
- if ( !matchesFilter(filenameRight, filterFileIn) || //process include filters
- matchesFilter(filenameRight, filterFileEx)) //process exclude filters
+ if (!matchesFileFilter(i->fileDescrRight.relativeName.c_str()))
{
i->selectedForSynchronization = false;
continue;
@@ -199,8 +209,7 @@ void FreeFileSync::filterGridData(FolderComparison& folderCmp, const wxString& i
}
else if (i->fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
{
- if ( !matchesFilter(filenameRight, filterFolderIn) || //process include filters
- matchesFilter(filenameRight, filterFolderEx)) //process exclude filters
+ if (!matchesDirFilter(i->fileDescrRight.relativeName.c_str()))
{
i->selectedForSynchronization = false;
continue;
@@ -227,14 +236,14 @@ void inOrExcludeAllRows(FreeFileSync::FolderComparison& folderCmp)
}
-void FreeFileSync::includeAllRowsOnGrid(FolderComparison& folderCmp)
+void FilterProcess::includeAllRowsOnGrid(FolderComparison& folderCmp)
{
//remove all filters on currentGridData
inOrExcludeAllRows<true>(folderCmp);
}
-void FreeFileSync::excludeAllRowsOnGrid(FolderComparison& folderCmp)
+void FilterProcess::excludeAllRowsOnGrid(FolderComparison& folderCmp)
{
//exclude all rows on currentGridData
inOrExcludeAllRows<false>(folderCmp);
diff --git a/library/filter.h b/library/filter.h
index 3d0598e1..dd716680 100644
--- a/library/filter.h
+++ b/library/filter.h
@@ -6,9 +6,25 @@
namespace FreeFileSync
{
- void filterGridData(FolderComparison& folderCmp, const wxString& includeFilter, const wxString& excludeFilter);
- void includeAllRowsOnGrid(FolderComparison& folderCmp);
- void excludeAllRowsOnGrid(FolderComparison& folderCmp);
+ class FilterProcess //relative filtering
+ {
+ public:
+ FilterProcess(const wxString& includeFilter, const wxString& excludeFilter);
+
+ bool matchesFileFilter(const DefaultChar* relFilename) const;
+ bool matchesDirFilter(const DefaultChar* relDirname) const;
+
+ void filterGridData(FolderComparison& folderCmp) const;
+
+ static void includeAllRowsOnGrid(FolderComparison& folderCmp);
+ static void excludeAllRowsOnGrid(FolderComparison& folderCmp);
+
+ private:
+ std::set<Zstring> filterFileIn;
+ std::set<Zstring> filterFolderIn;
+ std::set<Zstring> filterFileEx;
+ std::set<Zstring> filterFolderEx;
+ };
}
diff --git a/library/localization.cpp b/library/localization.cpp
index 328f37be..ef433012 100644
--- a/library/localization.cpp
+++ b/library/localization.cpp
@@ -129,7 +129,7 @@ void CustomLocale::setLanguage(const int language)
currentLanguage = wxLANGUAGE_ENGLISH;
}
- static bool initialized = false; //wxLocale is a global too!
+ static bool initialized = false; //wxLocale is a static global too!
if (!initialized)
{
initialized = true;
@@ -152,7 +152,7 @@ void CustomLocale::setLanguage(const int language)
//Linux: 0xa \n
//Mac: 0xd \r
//Win: 0xd 0xa \r\n <- language files are in Windows format
- for (int rowNumber = 0; langFile.getline(temp, bufferSize, 0xd); ++rowNumber) //specify delimiter explicitly
+ for (int rowNumber = 0; langFile.getline(temp, bufferSize, 0xD); ++rowNumber) //specify delimiter explicitly
{
langFile.get(); //discard the 0xa character
@@ -165,8 +165,11 @@ void CustomLocale::setLanguage(const int language)
currentLine.original = formattedString;
else
{
- currentLine.translation = formattedString;
- translationDB->insert(currentLine);
+ if (!formattedString.empty())
+ {
+ currentLine.translation = formattedString;
+ translationDB->insert(currentLine);
+ }
}
}
langFile.close();
diff --git a/library/processXml.cpp b/library/processXml.cpp
index c16b9d76..750bd879 100644
--- a/library/processXml.cpp
+++ b/library/processXml.cpp
@@ -19,12 +19,12 @@ const wxString xmlAccess::GLOBAL_CONFIG_FILE = wxT("GlobalSettings.xml");
bool readXmlElementValue(std::string& output, const TiXmlElement* parent, const std::string& name);
bool readXmlElementValue(int& output, const TiXmlElement* parent, const std::string& name);
bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const std::string& name);
-bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const std::string& name);
+bool readXmlElementValue(SyncDirection& output, const TiXmlElement* parent, const std::string& name);
bool readXmlElementValue(bool& output, const TiXmlElement* parent, const std::string& name);
void addXmlElement(TiXmlElement* parent, const std::string& name, const std::string& value);
void addXmlElement(TiXmlElement* parent, const std::string& name, const int value);
-void addXmlElement(TiXmlElement* parent, const std::string& name, const SyncConfiguration::Direction value);
+void addXmlElement(TiXmlElement* parent, const std::string& name, const SyncDirection value);
void addXmlElement(TiXmlElement* parent, const std::string& name, const bool value);
@@ -306,17 +306,17 @@ bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, con
}
-bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const std::string& name)
+bool readXmlElementValue(SyncDirection& output, const TiXmlElement* parent, const std::string& name)
{
std::string dummy;
if (readXmlElementValue(dummy, parent, name))
{
if (dummy == "left")
- output = SyncConfiguration::SYNC_DIR_LEFT;
+ output = SYNC_DIR_LEFT;
else if (dummy == "right")
- output = SyncConfiguration::SYNC_DIR_RIGHT;
+ output = SYNC_DIR_RIGHT;
else //treat all other input as "none"
- output = SyncConfiguration::SYNC_DIR_NONE;
+ output = SYNC_DIR_NONE;
return true;
}
@@ -460,8 +460,8 @@ bool XmlConfigInput::readXmlGuiConfig(xmlAccess::XmlGuiConfig& outputCfg)
if (guiConfig)
{
readXmlElementValue(outputCfg.hideFilteredElements, guiConfig, "HideFiltered");
-
readXmlElementValue(outputCfg.ignoreErrors, guiConfig, "IgnoreErrors");
+ readXmlElementValue(outputCfg.syncPreviewEnabled, guiConfig, "SyncPreviewActive");
}
return true;
@@ -508,7 +508,7 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
TiXmlElement* global = hRoot.FirstChild("Shared").ToElement();
if (global)
{
- //program language
+ //try to read program language setting
readXmlElementValue(outputCfg.shared.programLanguage, global, "Language");
//max. allowed file time deviation
@@ -516,6 +516,9 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
if (readXmlElementValue(dummy, global, "FileTimeTolerance"))
outputCfg.shared.fileTimeTolerance = dummy;
+ //ignore +/- 1 hour due to DST change
+ readXmlElementValue(outputCfg.shared.ignoreOneHourDiff, global, "IgnoreOneHourDifference");
+
//traverse into symbolic links (to folders)
readXmlElementValue(outputCfg.shared.traverseDirectorySymlinks, global, "TraverseDirectorySymlinks");
@@ -537,6 +540,12 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
//check free disk space
readXmlElementValue(outputCfg.shared.warningNotEnoughDiskSpace, warnings, "CheckForFreeDiskSpace");
+
+ //check for unresolved conflicts
+ readXmlElementValue(outputCfg.shared.warningUnresolvedConflicts, warnings, "CheckForUnresolvedConflicts");
+
+ //small reminder that synchronization will be starting immediately
+ readXmlElementValue(outputCfg.shared.warningSynchronizationStarting, warnings, "SynchronizationStarting");
}
//gui specific global settings (optional)
@@ -558,19 +567,19 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
//###########################################################
//read column attributes
TiXmlElement* leftColumn = TiXmlHandle(mainWindow).FirstChild("LeftColumns").FirstChild("Column").ToElement();
- unsigned int colType = 0;
+ unsigned int colPos = 0;
while (leftColumn)
{
- const char* visible = leftColumn->Attribute("Visible");
- const char* position = leftColumn->Attribute("Position");
- const char* width = leftColumn->Attribute("Width");
+ const char* type = leftColumn->Attribute("Type");
+ const char* visible = leftColumn->Attribute("Visible");
+ const char* width = leftColumn->Attribute("Width");
- if (visible && position && width) //may be NULL!!
+ if (type && visible && width) //may be NULL!!
{
xmlAccess::ColumnAttrib newAttrib;
- newAttrib.type = xmlAccess::ColumnTypes(colType);
+ newAttrib.type = xmlAccess::ColumnTypes(globalFunctions::stringToInt(type));
newAttrib.visible = std::string(visible) != std::string("false");
- newAttrib.position = globalFunctions::stringToInt(position);
+ newAttrib.position = colPos;
newAttrib.width = globalFunctions::stringToInt(width);
outputCfg.gui.columnAttribLeft.push_back(newAttrib);
}
@@ -578,23 +587,23 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
break;
leftColumn = leftColumn->NextSiblingElement();
- ++colType;
+ ++colPos;
}
TiXmlElement* rightColumn = TiXmlHandle(mainWindow).FirstChild("RightColumns").FirstChild("Column").ToElement();
- colType = 0;
+ colPos = 0;
while (rightColumn)
{
- const char* visible = rightColumn->Attribute("Visible");
- const char* position = rightColumn->Attribute("Position");
- const char* width = rightColumn->Attribute("Width");
+ const char* type = rightColumn->Attribute("Type");
+ const char* visible = rightColumn->Attribute("Visible");
+ const char* width = rightColumn->Attribute("Width");
- if (visible && position && width) //may be NULL!!
+ if (type && visible && width) //may be NULL!!
{
xmlAccess::ColumnAttrib newAttrib;
- newAttrib.type = xmlAccess::ColumnTypes(colType);
+ newAttrib.type = xmlAccess::ColumnTypes(globalFunctions::stringToInt(type));
newAttrib.visible = std::string(visible) != std::string("false");
- newAttrib.position = globalFunctions::stringToInt(position);
+ newAttrib.position = colPos;
newAttrib.width = globalFunctions::stringToInt(width);
outputCfg.gui.columnAttribRight.push_back(newAttrib);
}
@@ -602,7 +611,7 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
break;
rightColumn = rightColumn->NextSiblingElement();
- ++colType;
+ ++colPos;
}
//load folder history elements
@@ -722,13 +731,13 @@ void addXmlElement(TiXmlElement* parent, const std::string& name, const long val
}
-void addXmlElement(TiXmlElement* parent, const std::string& name, const SyncConfiguration::Direction value)
+void addXmlElement(TiXmlElement* parent, const std::string& name, const SyncDirection value)
{
- if (value == SyncConfiguration::SYNC_DIR_LEFT)
+ if (value == SYNC_DIR_LEFT)
addXmlElement(parent, name, std::string("left"));
- else if (value == SyncConfiguration::SYNC_DIR_RIGHT)
+ else if (value == SYNC_DIR_RIGHT)
addXmlElement(parent, name, std::string("right"));
- else if (value == SyncConfiguration::SYNC_DIR_NONE)
+ else if (value == SYNC_DIR_NONE)
addXmlElement(parent, name, std::string("none"));
else
assert(false);
@@ -841,8 +850,8 @@ bool XmlConfigOutput::writeXmlGuiConfig(const xmlAccess::XmlGuiConfig& inputCfg)
root->LinkEndChild(guiConfig);
addXmlElement(guiConfig, "HideFiltered", inputCfg.hideFilteredElements);
-
addXmlElement(guiConfig, "IgnoreErrors", inputCfg.ignoreErrors);
+ addXmlElement(guiConfig, "SyncPreviewActive", inputCfg.syncPreviewEnabled);
return true;
}
@@ -885,6 +894,9 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings&
//max. allowed file time deviation
addXmlElement(global, "FileTimeTolerance", int(inputCfg.shared.fileTimeTolerance));
+ //ignore +/- 1 hour due to DST change
+ addXmlElement(global, "IgnoreOneHourDifference", inputCfg.shared.ignoreOneHourDiff);
+
//traverse into symbolic links (to folders)
addXmlElement(global, "TraverseDirectorySymlinks", inputCfg.shared.traverseDirectorySymlinks);
@@ -907,6 +919,12 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings&
//check free disk space
addXmlElement(warnings, "CheckForFreeDiskSpace", inputCfg.shared.warningNotEnoughDiskSpace);
+ //check for unresolved conflicts
+ addXmlElement(warnings, "CheckForUnresolvedConflicts", inputCfg.shared.warningUnresolvedConflicts);
+
+ //small reminder that synchronization will be starting immediately
+ addXmlElement(warnings, "SynchronizationStarting", inputCfg.shared.warningSynchronizationStarting);
+
//###################################################################
//write global gui settings
@@ -937,32 +955,32 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings&
TiXmlElement* leftColumn = new TiXmlElement("LeftColumns");
mainWindow->LinkEndChild(leftColumn);
xmlAccess::ColumnAttributes columnAtrribLeftCopy = inputCfg.gui.columnAttribLeft; //can't change const vector
- sort(columnAtrribLeftCopy.begin(), columnAtrribLeftCopy.end(), xmlAccess::sortByType);
+ sort(columnAtrribLeftCopy.begin(), columnAtrribLeftCopy.end(), xmlAccess::sortByPositionOnly);
for (unsigned int i = 0; i < columnAtrribLeftCopy.size(); ++i)
{
TiXmlElement* subElement = new TiXmlElement("Column");
leftColumn->LinkEndChild(subElement);
const xmlAccess::ColumnAttrib& colAttrib = columnAtrribLeftCopy[i];
+ subElement->SetAttribute("Type", colAttrib.type);
if (colAttrib.visible) subElement->SetAttribute("Visible", "true");
else subElement->SetAttribute("Visible", "false");
- subElement->SetAttribute("Position", colAttrib.position);
subElement->SetAttribute("Width", colAttrib.width);
}
TiXmlElement* rightColumn = new TiXmlElement("RightColumns");
mainWindow->LinkEndChild(rightColumn);
xmlAccess::ColumnAttributes columnAtrribRightCopy = inputCfg.gui.columnAttribRight;
- sort(columnAtrribRightCopy.begin(), columnAtrribRightCopy.end(), xmlAccess::sortByType);
+ sort(columnAtrribRightCopy.begin(), columnAtrribRightCopy.end(), xmlAccess::sortByPositionOnly);
for (unsigned int i = 0; i < columnAtrribRightCopy.size(); ++i)
{
TiXmlElement* subElement = new TiXmlElement("Column");
rightColumn->LinkEndChild(subElement);
const xmlAccess::ColumnAttrib& colAttrib = columnAtrribRightCopy[i];
+ subElement->SetAttribute("Type", colAttrib.type);
if (colAttrib.visible) subElement->SetAttribute("Visible", "true");
else subElement->SetAttribute("Visible", "false");
- subElement->SetAttribute("Position", colAttrib.position);
subElement->SetAttribute("Width", colAttrib.width);
}
@@ -1094,7 +1112,9 @@ bool xmlAccess::supportForSymbolicLinks()
void xmlAccess::XmlGlobalSettings::_Shared::resetWarnings()
{
- warningDependentFolders = true;
- warningSignificantDifference = true;
- warningNotEnoughDiskSpace = true;
+ warningDependentFolders = true;
+ warningSignificantDifference = true;
+ warningNotEnoughDiskSpace = true;
+ warningUnresolvedConflicts = true;
+ warningSynchronizationStarting = true;
}
diff --git a/library/processXml.h b/library/processXml.h
index 763edbca..313fbfae 100644
--- a/library/processXml.h
+++ b/library/processXml.h
@@ -26,21 +26,21 @@ namespace xmlAccess
enum ColumnTypes
{
- FILENAME = 0,
+ DIRECTORY,
+ FULL_PATH,
REL_PATH,
+ FILENAME,
SIZE,
- DATE,
- FULL_NAME,
- DIRECTORY
+ DATE
};
const unsigned COLUMN_TYPE_COUNT = 6;
struct ColumnAttrib
{
ColumnTypes type;
- bool visible;
- unsigned position;
- int width;
+ bool visible;
+ unsigned int position;
+ int width;
};
typedef std::vector<ColumnAttrib> ColumnAttributes;
@@ -51,20 +51,23 @@ namespace xmlAccess
{
XmlGuiConfig() :
hideFilteredElements(false),
- ignoreErrors(false) {} //initialize values
+ ignoreErrors(false),
+ syncPreviewEnabled(true) {} //initialize values
FreeFileSync::MainConfiguration mainCfg;
std::vector<FreeFileSync::FolderPair> directoryPairs;
bool hideFilteredElements;
bool ignoreErrors; //reaction on error situation during synchronization
+ bool syncPreviewEnabled;
bool operator==(const XmlGuiConfig& other) const
{
- return mainCfg == other.mainCfg &&
- directoryPairs == other.directoryPairs &&
+ return mainCfg == other.mainCfg &&
+ directoryPairs == other.directoryPairs &&
hideFilteredElements == other.hideFilteredElements &&
- ignoreErrors == other.ignoreErrors;
+ ignoreErrors == other.ignoreErrors &&
+ syncPreviewEnabled == other.syncPreviewEnabled;
}
bool operator!=(const XmlGuiConfig& other) const
@@ -98,6 +101,7 @@ namespace xmlAccess
_Shared() :
programLanguage(retrieveSystemLanguage()),
fileTimeTolerance(2), //default 2s: FAT vs NTFS
+ ignoreOneHourDiff(true),
traverseDirectorySymlinks(false),
copyFileSymlinks(supportForSymbolicLinks()),
lastUpdateCheck(0)
@@ -106,7 +110,8 @@ namespace xmlAccess
}
int programLanguage;
- unsigned fileTimeTolerance; //max. allowed file time deviation
+ unsigned int fileTimeTolerance; //max. allowed file time deviation
+ bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change
bool traverseDirectorySymlinks;
bool copyFileSymlinks; //copy symbolic link instead of target file
long lastUpdateCheck; //time of last update check
@@ -117,6 +122,8 @@ namespace xmlAccess
bool warningDependentFolders;
bool warningSignificantDifference;
bool warningNotEnoughDiskSpace;
+ bool warningUnresolvedConflicts;
+ bool warningSynchronizationStarting;
} shared;
//---------------------------------------------------------------------
diff --git a/library/resources.cpp b/library/resources.cpp
index 23d1ac37..9e43a78a 100644
--- a/library/resources.cpp
+++ b/library/resources.cpp
@@ -37,29 +37,32 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("about_small.png")] = (bitmapAboutSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("website.png")] = (bitmapWebsite = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("exit.png")] = (bitmapExit = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("sync.png")] = (bitmapSync = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("compare.png")] = (bitmapCompare = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("compare disabled.png")] = (bitmapCompareDisabled = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("sync.png")] = (bitmapSync = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("sync disabled.png")] = (bitmapSyncDisabled = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("swap.png")] = (bitmapSwap = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("help.png")] = (bitmapHelp = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("equal.png")] = (bitmapEqual = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("equalAct.png")] = (bitmapEqualAct = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("equalDeact.png")] = (bitmapEqualDeact = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftOnly.png")] = (bitmapLeftOnly = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftOnlyAct.png")] = (bitmapLeftOnlyAct = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftOnlyDeact.png")] = (bitmapLeftOnlyDeact = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("rightOnly.png")] = (bitmapRightOnly = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("rightOnlyAct.png")] = (bitmapRightOnlyAct = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("rightOnlyDeact.png")] = (bitmapRightOnlyDeact = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftNewer.png")] = (bitmapLeftNewer = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftNewerAct.png")] = (bitmapLeftNewerAct = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftNewerDeact.png")] = (bitmapLeftNewerDeact = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("different.png")] = (bitmapDifferent = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("differentAct.png")] = (bitmapDifferentAct = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("differentDeact.png")] = (bitmapDifferentDeact = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("rightNewer.png")] = (bitmapRightNewer = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("rightNewerAct.png")] = (bitmapRightNewerAct = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("rightNewerDeact.png")] = (bitmapRightNewerDeact = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("rightOnly.png")] = (bitmapRightOnly = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("rightOnlyAct.png")] = (bitmapRightOnlyAct = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("rightOnlyDeact.png")] = (bitmapRightOnlyDeact = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("different.png")] = (bitmapDifferent = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("differentAct.png")] = (bitmapDifferentAct = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("differentDeact.png")] = (bitmapDifferentDeact = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("equal.png")] = (bitmapEqual = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("equalAct.png")] = (bitmapEqualAct = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("equalDeact.png")] = (bitmapEqualDeact = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("conflictAct.png")] = (bitmapConflictAct = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("conflictDeact.png")] = (bitmapConflictDeact = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("include.png")] = (bitmapInclude = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("exclude.png")] = (bitmapExclude = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("filter active.png")] = (bitmapFilterOn = new wxBitmap(wxNullBitmap));
@@ -80,7 +83,7 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("statusSuccess.png")] = (bitmapStatusSuccess = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("statusWarning.png")] = (bitmapStatusWarning = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("statusScanning.png")] = (bitmapStatusScanning = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("statusComparing.png")] = (bitmapStatusComparing = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("statusBinaryCompare.png")]= (bitmapStatusBinCompare = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("statusSyncing.png")] = (bitmapStatusSyncing = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("logo.png")] = (bitmapLogo = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("statusEdge.png")] = (bitmapStatusEdge = new wxBitmap(wxNullBitmap));
@@ -104,6 +107,9 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("settings_small.png")] = (bitmapSettingsSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("recycler.png")] = (bitmapRecycler = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("shift.png")] = (bitmapShift = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncConfig.png")] = (bitmapSyncCfg = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncPreview.png")] = (bitmapPreview = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncPreviewDisabl.png")] = (bitmapPreviewDisabled = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("question.png")] = (bitmapQuestion = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("china.png")] = (bitmapChina = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("holland.png")] = (bitmapHolland = new wxBitmap(wxNullBitmap));
@@ -118,6 +124,30 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("brazil.png")] = (bitmapBrazil = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("slovakia.png")] = (bitmapSlovakia = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("spain.png")] = (bitmapSpain = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirLeftAct.png")] = (bitmapSyncDirLeftAct = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirLeftDeact.png")] = (bitmapSyncDirLeftDeact = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirRightAct.png")] = (bitmapSyncDirRightAct = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirRightDeact.png")] = (bitmapSyncDirRightDeact = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirNoneAct.png")] = (bitmapSyncDirNoneAct = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirNoneDeact.png")] = (bitmapSyncDirNoneDeact = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirLeftSmall.png")] = (bitmapSyncDirLeftSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirRightSmall.png")] = (bitmapSyncDirRightSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncDirNoneSmall.png")] = (bitmapSyncDirNoneSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("leftOnlySmall.png")] = (bitmapLeftOnlySmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("rightOnlySmall.png")] = (bitmapRightOnlySmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("leftNewerSmall.png")] = (bitmapLeftNewerSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("rightNewerSmall.png")] = (bitmapRightNewerSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("equalSmall.png")] = (bitmapEqualSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("differentSmall.png")] = (bitmapDifferentSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("conflictSmall.png")] = (bitmapConflictSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("create.png")] = (bitmapCreate = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("update.png")] = (bitmapUpdate = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("delete.png")] = (bitmapDelete = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("data.png")] = (bitmapData = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("cmpView.png")] = (bitmapCmpView = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncView.png")] = (bitmapSyncView = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("toggleViewSmall.png")] = (bitmapSwitchViewSmall = new wxBitmap(wxNullBitmap));
+
//init all the other resource files
animationMoney = new wxAnimation(wxNullAnimation);
diff --git a/library/resources.h b/library/resources.h
index 5de79ec2..60b4ab48 100644
--- a/library/resources.h
+++ b/library/resources.h
@@ -36,29 +36,32 @@ public:
wxBitmap* bitmapAboutSmall;
wxBitmap* bitmapWebsite;
wxBitmap* bitmapExit;
- wxBitmap* bitmapSync;
wxBitmap* bitmapCompare;
+ wxBitmap* bitmapCompareDisabled;
+ wxBitmap* bitmapSync;
wxBitmap* bitmapSyncDisabled;
wxBitmap* bitmapSwap;
wxBitmap* bitmapHelp;
- wxBitmap* bitmapEqual;
- wxBitmap* bitmapEqualAct;
- wxBitmap* bitmapEqualDeact;
wxBitmap* bitmapLeftOnly;
wxBitmap* bitmapLeftOnlyAct;
wxBitmap* bitmapLeftOnlyDeact;
+ wxBitmap* bitmapRightOnly;
+ wxBitmap* bitmapRightOnlyAct;
+ wxBitmap* bitmapRightOnlyDeact;
wxBitmap* bitmapLeftNewer;
wxBitmap* bitmapLeftNewerAct;
wxBitmap* bitmapLeftNewerDeact;
- wxBitmap* bitmapDifferent;
- wxBitmap* bitmapDifferentAct;
- wxBitmap* bitmapDifferentDeact;
wxBitmap* bitmapRightNewer;
wxBitmap* bitmapRightNewerAct;
wxBitmap* bitmapRightNewerDeact;
- wxBitmap* bitmapRightOnly;
- wxBitmap* bitmapRightOnlyAct;
- wxBitmap* bitmapRightOnlyDeact;
+ wxBitmap* bitmapEqual;
+ wxBitmap* bitmapEqualAct;
+ wxBitmap* bitmapEqualDeact;
+ wxBitmap* bitmapDifferent;
+ wxBitmap* bitmapDifferentAct;
+ wxBitmap* bitmapDifferentDeact;
+ wxBitmap* bitmapConflictAct;
+ wxBitmap* bitmapConflictDeact;
wxBitmap* bitmapInclude;
wxBitmap* bitmapExclude;
wxBitmap* bitmapFilterOn;
@@ -79,7 +82,7 @@ public:
wxBitmap* bitmapStatusSuccess;
wxBitmap* bitmapStatusWarning;
wxBitmap* bitmapStatusScanning;
- wxBitmap* bitmapStatusComparing;
+ wxBitmap* bitmapStatusBinCompare;
wxBitmap* bitmapStatusSyncing;
wxBitmap* bitmapLogo;
wxBitmap* bitmapStatusEdge;
@@ -103,6 +106,9 @@ public:
wxBitmap* bitmapSettingsSmall;
wxBitmap* bitmapRecycler;
wxBitmap* bitmapShift;
+ wxBitmap* bitmapSyncCfg;
+ wxBitmap* bitmapPreview;
+ wxBitmap* bitmapPreviewDisabled;
wxBitmap* bitmapQuestion;
wxBitmap* bitmapChina;
wxBitmap* bitmapHolland;
@@ -117,6 +123,29 @@ public:
wxBitmap* bitmapBrazil;
wxBitmap* bitmapSlovakia;
wxBitmap* bitmapSpain;
+ wxBitmap* bitmapSyncDirLeftAct;
+ wxBitmap* bitmapSyncDirLeftDeact;
+ wxBitmap* bitmapSyncDirRightAct;
+ wxBitmap* bitmapSyncDirRightDeact;
+ wxBitmap* bitmapSyncDirNoneAct;
+ wxBitmap* bitmapSyncDirNoneDeact;
+ wxBitmap* bitmapSyncDirLeftSmall;
+ wxBitmap* bitmapSyncDirRightSmall;
+ wxBitmap* bitmapSyncDirNoneSmall;
+ wxBitmap* bitmapLeftOnlySmall;
+ wxBitmap* bitmapRightOnlySmall;
+ wxBitmap* bitmapLeftNewerSmall;
+ wxBitmap* bitmapRightNewerSmall;
+ wxBitmap* bitmapEqualSmall;
+ wxBitmap* bitmapDifferentSmall;
+ wxBitmap* bitmapConflictSmall;
+ wxBitmap* bitmapCreate;
+ wxBitmap* bitmapUpdate;
+ wxBitmap* bitmapDelete;
+ wxBitmap* bitmapData;
+ wxBitmap* bitmapCmpView;
+ wxBitmap* bitmapSyncView;
+ wxBitmap* bitmapSwitchViewSmall;
wxAnimation* animationMoney;
wxAnimation* animationSync;
diff --git a/library/statusHandler.cpp b/library/statusHandler.cpp
index e19c9904..78dba057 100644
--- a/library/statusHandler.cpp
+++ b/library/statusHandler.cpp
@@ -16,8 +16,7 @@ void updateUiNow()
bool updateUiIsAllowed()
{
static wxLongLong lastExec = 0;
-
- wxLongLong newExec = wxGetLocalTimeMillis();
+ const wxLongLong newExec = wxGetLocalTimeMillis();
if (newExec - lastExec >= UI_UPDATE_INTERVAL) //perform ui updates not more often than necessary
{
diff --git a/library/statusHandler.h b/library/statusHandler.h
index 18d9f129..fe64f3cd 100644
--- a/library/statusHandler.h
+++ b/library/statusHandler.h
@@ -54,7 +54,7 @@ public:
virtual void forceUiRefresh() = 0;
void requestUiRefresh(bool allowAbort = true); //opportunity to abort must be implemented in a frequently executed method like requestUiRefresh()
- void requestAbortion(); //does NOT call abortThisProcess immediately, but when appropriate (e.g. async. processes finished)
+ void requestAbortion(); //this does NOT call abortThisProcess immediately, but when appropriate (e.g. async. processes finished)
bool abortIsRequested();
@@ -63,7 +63,7 @@ public:
virtual void reportFatalError(const Zstring& errorMessage) = 0; //non-recoverable error situation, implement abort!
virtual void reportWarning(const Zstring& warningMessage, bool& dontShowAgain) = 0;
-protected:
+private:
virtual void abortThisProcess() = 0;
bool abortRequested;
diff --git a/library/zstring.cpp b/library/zstring.cpp
index abded9d0..ddf1fc73 100644
--- a/library/zstring.cpp
+++ b/library/zstring.cpp
@@ -1,5 +1,4 @@
#include "zstring.h"
-#include <wx/intl.h>
#include "globalFunctions.h"
#ifdef FFS_WIN
@@ -124,6 +123,12 @@ bool Zstring::Matches(const DefaultChar* mask) const
}
+bool Zstring::Matches(const DefaultChar* name, const DefaultChar* mask)
+{
+ return matchesHelper(name, mask);
+}
+
+
Zstring& Zstring::Trim(bool fromRight)
{
const size_t thisLen = length();
diff --git a/library/zstring.h b/library/zstring.h
index 2b6bc475..007922d8 100644
--- a/library/zstring.h
+++ b/library/zstring.h
@@ -66,6 +66,7 @@ public:
Zstring BeforeLast(DefaultChar ch) const;
size_t Find(DefaultChar ch, bool fromEnd) const;
bool Matches(const DefaultChar* mask) const;
+ static bool Matches(const DefaultChar* name, const DefaultChar* mask);
Zstring& Trim(bool fromRight); //from right or left
Zstring& MakeLower();
bgstack15