summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 16:56:14 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 16:56:14 +0200
commit1046c195a9bbac24678c06310a4dd56b10347244 (patch)
tree89ad9f6fe3e538d65ef973b628ed9284b6c99e9f /library
parent1.14 (diff)
downloadFreeFileSync-1046c195a9bbac24678c06310a4dd56b10347244.tar.gz
FreeFileSync-1046c195a9bbac24678c06310a4dd56b10347244.tar.bz2
FreeFileSync-1046c195a9bbac24678c06310a4dd56b10347244.zip
1.15
Diffstat (limited to 'library')
-rw-r--r--library/CustomGrid.cpp879
-rw-r--r--library/CustomGrid.h118
-rw-r--r--library/customButton.cpp293
-rw-r--r--library/customButton.h40
-rw-r--r--library/fileHandling.cpp82
-rw-r--r--library/fileHandling.h8
-rw-r--r--library/globalFunctions.cpp20
-rw-r--r--library/globalFunctions.h22
-rw-r--r--library/misc.cpp32
-rw-r--r--library/misc.h5
-rw-r--r--library/multithreading.cpp1
-rw-r--r--library/processXml.cpp320
-rw-r--r--library/processXml.h79
-rw-r--r--library/resources.cpp12
-rw-r--r--library/resources.h9
-rw-r--r--library/sorting.h21
-rw-r--r--library/statusHandler.h8
-rw-r--r--library/zstring.cpp68
-rw-r--r--library/zstring.h197
19 files changed, 1581 insertions, 633 deletions
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp
index 25ceb537..95300a2b 100644
--- a/library/CustomGrid.cpp
+++ b/library/CustomGrid.cpp
@@ -3,24 +3,28 @@
#include "resources.h"
#include <wx/dc.h>
#include "../algorithm.h"
+#include "resources.h"
+
+using namespace xmlAccess;
+
-const unsigned int MinimumRows = 15;
+const unsigned int MIN_ROW_COUNT = 15;
//class containing pure grid data: basically the same as wxGridStringTable, but adds cell formatting
-class CustomGridTableBase : public wxGridStringTable
+class CustomGridTable : public wxGridTableBase
{
public:
- CustomGridTableBase(int numRows, int numCols) :
- wxGridStringTable(numRows, numCols),
+ CustomGridTable() :
+ wxGridTableBase(),
lightBlue(80, 110, 255),
lightGrey(212, 208, 200),
- gridIdentifier(0),
- gridRefUI(0),
- gridData(0),
- lastNrRows(MinimumRows) {}
+ gridRefUI(NULL),
+ gridData(NULL),
+ lastNrRows(0),
+ lastNrCols(0) {}
- ~CustomGridTableBase() {}
+ virtual ~CustomGridTable() {}
void setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData)
@@ -30,182 +34,56 @@ public:
}
- void SetGridIdentifier(int id)
- {
- gridIdentifier = id;
- }
-
//###########################################################################
//grid standard input output methods, redirected directly to gridData to improve performance
virtual int GetNumberRows()
{
if (gridRefUI)
- return max(gridRefUI->size(), MinimumRows);
+ return std::max(gridRefUI->size(), MIN_ROW_COUNT);
else
- return MinimumRows; //grid is initialized with this number of rows
+ return 0; //grid is initialized with zero number of rows
}
- virtual bool IsEmptyCell( int row, int col )
+ virtual int GetNumberCols() //virtual used by middle grid!
{
- return (GetValue(row, col) == wxEmptyString);
+ return columnPositions.size();
}
- wxString evaluateCmpResult(const CompareFilesResult result, const bool selectedForSynchronization)
+ virtual bool IsEmptyCell( int row, int col )
{
- if (selectedForSynchronization)
- switch (result)
- {
- case FILE_LEFT_SIDE_ONLY:
- return wxT("<|");
- break;
- case FILE_RIGHT_SIDE_ONLY:
- return wxT("|>");
- break;
- case FILE_RIGHT_NEWER:
- return wxT(">>");
- break;
- case FILE_LEFT_NEWER:
- return wxT("<<");
- break;
- case FILE_DIFFERENT:
- return wxT("!=");
- break;
- case FILE_EQUAL:
- return wxT("==");
- break;
- default:
- assert (false);
- return wxEmptyString;
- }
- else return wxT("(-)");
+ return (GetValue(row, col) == wxEmptyString);
}
- virtual wxString GetValue(int row, int col)
- {
- if (gridRefUI)
- {
- if (unsigned(row) < gridRefUI->size())
- {
- const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
- wxString fileSize; //tmp string
-
- switch (gridIdentifier)
- {
- case 1:
- if (col < 4)
- {
- if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
- {
- switch (col)
- {
- case 0: //filename
- return wxEmptyString;
- case 1: //relative path
- return gridLine.fileDescrLeft.relativeName;
- case 2: //file size
- return _("<Directory>");
- case 3: //date
- return wxEmptyString;
- }
- }
- else if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_FILE)
- {
- switch (col)
- {
- case 0: //filename
- return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 1: //relative path
- return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 2: //file size
- return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrLeft.fileSize.ToString());
- case 3: //date
- return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrLeft.lastWriteTimeRaw);
- }
- }
- }
- else
- assert (false);
-
- break;
-
- case 2:
- if (col < 4)
- {
- if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
- {
- switch (col)
- {
- case 0: //filename
- return wxEmptyString;
- case 1: //relative path
- return gridLine.fileDescrRight.relativeName;
- case 2: //file size
- return _("<Directory>");
- case 3: //date
- return wxEmptyString;
- }
- }
- else if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_FILE)
- {
- switch (col)
- {
- case 0: //filename
- return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 1: //relative path
- return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 2: //file size
- return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrRight.fileSize.ToString());
- case 3: //date
- return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrRight.lastWriteTimeRaw);
- }
- }
- }
- else
- assert (false);
-
- break;
+ virtual wxString GetValue(int row, int col) = 0;
- case 3:
- if (col < 1)
- return evaluateCmpResult(gridLine.cmpResult, gridLine.selectedForSynchronization);
- else
- assert (false);
- break;
- default:
- assert (false);
- break;
- }
- }
- }
- //if data is not found:
- return wxEmptyString;
- }
-
-
- virtual void SetValue( int row, int col, const wxString& value )
+ virtual void SetValue(int row, int col, const wxString& value)
{
assert (false); //should not be used, since values are retrieved directly from gridRefUI
}
+
virtual void Clear()
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
}
- virtual bool InsertRows( size_t pos = 0, size_t numRows = 1 )
+
+ virtual bool InsertRows(size_t pos = 0, size_t numRows = 1)
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
return true;
}
- virtual bool AppendRows( size_t numRows = 1 )
+
+ virtual bool AppendRows(size_t numRows = 1)
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
return true;
}
- virtual bool DeleteRows( size_t pos = 0, size_t numRows = 1 )
+
+ virtual bool DeleteRows(size_t pos = 0, size_t numRows = 1)
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
return true;
@@ -216,7 +94,7 @@ public:
{
if (gridRefUI)
{
- int currentNrRows = GetNumberRows();
+ const int currentNrRows = GetNumberRows();
if (lastNrRows < currentNrRows)
{
@@ -243,79 +121,326 @@ public:
}
lastNrRows = currentNrRows;
}
- }
-//###########################################################################
- enum RowColor {BLUE, GREY, NONE};
+ const int currentNrCols = GetNumberCols();
- inline //redundant command
- RowColor getRowColor(int row) //rows that are filtered out are shown in different color
- {
- if (gridRefUI)
+ if (lastNrCols < currentNrCols)
{
- if (unsigned(row) < gridRefUI->size())
+ if (GetView())
{
- const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
-
- //mark filtered rows
- if (!cmpLine.selectedForSynchronization)
- return BLUE;
- //mark directories
- else if (gridIdentifier == 1 && cmpLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
- return GREY;
- else if (gridIdentifier == 2 && cmpLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
- return GREY;
- else
- return NONE;
+ wxGridTableMessage msg(this,
+ wxGRIDTABLE_NOTIFY_COLS_APPENDED,
+ currentNrCols - lastNrCols);
+
+ GetView()->ProcessTableMessage( msg );
}
}
- return NONE;
+ else if (lastNrCols > currentNrCols)
+ {
+ if (GetView())
+ {
+ wxGridTableMessage msg(this,
+ wxGRIDTABLE_NOTIFY_COLS_DELETED,
+ 0,
+ lastNrCols - currentNrCols);
+
+ GetView()->ProcessTableMessage( msg );
+ }
+ }
+ lastNrCols = currentNrCols;
}
+//###########################################################################
- wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind)
+ virtual wxString GetColLabelValue( int col )
{
- wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind);
+ return CustomGrid::getTypeName(getTypeAtPos(col));
+ }
+
+
+ virtual wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind)
+ {
+ const wxColour& color = getRowColor(row);
- // MARK FILTERED ROWS:
+ //add color to some rows
+ wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind);
if (result)
- { //if kind is not a cell or row attribute, we have to clone the cell attribute, since we don't want to change e.g. all column attribs
- if (result->GetKind() != wxGridCellAttr::Cell && result->GetKind() != wxGridCellAttr::Row)
+ {
+ if (result->GetBackgroundColour() == color)
{
- wxGridCellAttr* attr = result->Clone();
+ return result;
+ }
+ else //grid attribute might be referenced by other nodes, so clone it!
+ {
+ wxGridCellAttr* attr = result->Clone(); //attr has ref-count 1
result->DecRef();
result = attr;
}
-
- RowColor color = getRowColor(row);
- if (color == BLUE)
- result->SetBackgroundColour(lightBlue);
- else if (color == GREY)
- result->SetBackgroundColour(lightGrey);
- else
- result->SetBackgroundColour(*wxWHITE);
}
else
- {
- result = new wxGridCellAttr;
+ result = new wxGridCellAttr; //created with ref-count 1
- RowColor color = getRowColor(row);
- if (color == BLUE)
- result->SetBackgroundColour(lightBlue);
- else if (color == GREY)
- result->SetBackgroundColour(lightGrey);
- }
+ result->SetBackgroundColour(color);
return result;
}
-private:
+
+ void setupColumns(const std::vector<xmlAccess::XmlGlobalSettings::ColumnTypes>& positions)
+ {
+ columnPositions = positions;
+ updateGridSizes(); //add or remove columns
+ }
+
+
+ XmlGlobalSettings::ColumnTypes getTypeAtPos(unsigned pos) const
+ {
+ if (pos < columnPositions.size())
+ return columnPositions[pos];
+ else
+ return XmlGlobalSettings::ColumnTypes(1000);
+ }
+
+
+protected:
+ virtual const wxColour& getRowColor(int row) = 0; //rows that are filtered out are shown in different color
+
+ std::vector<xmlAccess::XmlGlobalSettings::ColumnTypes> columnPositions;
+
wxColour lightBlue;
wxColour lightGrey;
- int gridIdentifier;
GridView* gridRefUI; //(very fast) access to underlying grid data :)
FileCompareResult* gridData;
int lastNrRows;
+ int lastNrCols;
+};
+
+
+class CustomGridTableLeft : public CustomGridTable
+{
+public:
+ CustomGridTableLeft() : CustomGridTable() {}
+ ~CustomGridTableLeft() {}
+
+ virtual const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
+ {
+ if (gridRefUI && unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ //mark filtered rows
+ if (!cmpLine.selectedForSynchronization)
+ return lightBlue;
+ //mark directories
+ else if (cmpLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
+ return lightGrey;
+ else
+ return *wxWHITE;
+ }
+ return *wxWHITE;
+ }
+
+
+ //virtual impl.
+ wxString GetValue(int row, int col)
+ {
+ if (gridRefUI)
+ {
+ if (unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
+
+ if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return wxEmptyString;
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrLeft.relativeName.c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ return _("<Directory>");
+ case XmlGlobalSettings::DATE: //date
+ return wxEmptyString;
+ }
+ }
+ else if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_FILE)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ {
+ wxString fileSize = gridLine.fileDescrLeft.fileSize.ToString(); //tmp string
+ return globalFunctions::includeNumberSeparator(fileSize);
+ }
+ case XmlGlobalSettings::DATE: //date
+ return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrLeft.lastWriteTimeRaw);
+ }
+ }
+ }
+ }
+ //if data is not found:
+ return wxEmptyString;
+ }
+};
+
+
+class CustomGridTableMiddle : public CustomGridTable
+{
+public:
+ CustomGridTableMiddle() : CustomGridTable()
+ {
+ lastNrCols = 1; //ensure CustomGridTable::updateGridSizes() is working correctly
+ }
+ ~CustomGridTableMiddle() {}
+
+ //virtual impl.
+ int GetNumberCols()
+ {
+ return 1;
+ }
+
+
+ int selectedForSynchronization(const unsigned int row) // 0 == false, 1 == true, -1 == not defined
+ {
+ if (gridRefUI && row < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ if (cmpLine.selectedForSynchronization)
+ return 1;
+ else
+ return 0;
+ }
+ return -1;
+ }
+
+
+ //virtual impl.
+ const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
+ {
+ if (gridRefUI && unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ //mark filtered rows
+ if (!cmpLine.selectedForSynchronization)
+ return lightBlue;
+ else
+ return *wxWHITE;
+ }
+ return *wxWHITE;
+ }
+
+ //virtual impl.
+ wxString GetValue(int row, int col)
+ {
+ if (gridRefUI)
+ {
+ if (unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
+
+ 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;
+ }
+};
+
+
+class CustomGridTableRight : public CustomGridTable
+{
+public:
+ CustomGridTableRight() : CustomGridTable() {}
+ ~CustomGridTableRight() {}
+
+ //virtual impl.
+ const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
+ {
+ if (gridRefUI && unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ //mark filtered rows
+ if (!cmpLine.selectedForSynchronization)
+ return lightBlue;
+ //mark directories
+ else if (cmpLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
+ return lightGrey;
+ else
+ return *wxWHITE;
+ }
+ return *wxWHITE;
+ }
+
+ //virtual impl.
+ wxString GetValue(int row, int col)
+ {
+ if (gridRefUI)
+ {
+ if (unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
+
+ if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return wxEmptyString;
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrRight.relativeName.c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ return _("<Directory>");
+ case XmlGlobalSettings::DATE: //date
+ return wxEmptyString;
+ }
+ }
+ else if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_FILE)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ {
+ wxString fileSize = gridLine.fileDescrRight.fileSize.ToString(); //tmp string
+ return globalFunctions::includeNumberSeparator(fileSize);
+ }
+ case XmlGlobalSettings::DATE: //date
+ return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrRight.lastWriteTimeRaw);
+ }
+ }
+ }
+ }
+ //if data is not found:
+ return wxEmptyString;
+ }
};
@@ -333,26 +458,33 @@ CustomGrid::CustomGrid(wxWindow *parent,
m_gridLeft(NULL), m_gridRight(NULL), m_gridMiddle(NULL),
gridDataTable(NULL),
currentSortColumn(-1),
- sortMarker(NULL) {}
-
-
-CustomGrid::~CustomGrid() {}
-
-
-bool CustomGrid::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+ sortMarker(NULL)
{
- //use custom wxGridTableBase class for management of large sets of formatted data.
- //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default.
-
- gridDataTable = new CustomGridTableBase(numRows, numCols);
- SetTable(gridDataTable, true, selmode); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
- return true;
+ //set color of selections
+ wxColour darkBlue(40, 35, 140);
+ SetSelectionBackground(darkBlue);
+ SetSelectionForeground(*wxWHITE);
}
-void CustomGrid::deactivateScrollbars()
+void CustomGrid::initSettings(bool enableScrollbars,
+ CustomGrid* gridLeft,
+ CustomGrid* gridRight,
+ CustomGrid* gridMiddle,
+ GridView* gridRefUI,
+ FileCompareResult* gridData)
{
- scrollbarsEnabled = false;
+ scrollbarsEnabled = enableScrollbars;
+
+ //these grids will scroll together
+ assert(gridLeft && gridRight && gridMiddle);
+ m_gridLeft = gridLeft;
+ m_gridRight = gridRight;
+ m_gridMiddle = gridMiddle;
+
+ //set underlying grid data
+ assert(gridDataTable);
+ gridDataTable->setGridDataTable(gridRefUI, gridData);
}
@@ -380,7 +512,7 @@ void CustomGrid::adjustGridHeights() //m_gridLeft, m_gridRight, m_gridMiddle are
if (y1 != y2 || y2 != y3)
{
- int yMax = max(y1, max(y2, y3));
+ int yMax = std::max(y1, std::max(y2, y3));
if (::leadGrid == m_gridLeft) //do not handle case (y1 == yMax) here!!! Avoid back coupling!
m_gridLeft->SetMargins(0, 0);
@@ -404,90 +536,311 @@ void CustomGrid::adjustGridHeights() //m_gridLeft, m_gridRight, m_gridMiddle are
}
-//this method is called when grid view changes: useful for parallel updating of multiple grids
-void CustomGrid::DoPrepareDC(wxDC& dc)
+void CustomGrid::updateGridSizes()
{
- wxScrollHelper::DoPrepareDC(dc);
+ assert(gridDataTable);
+ gridDataTable->updateGridSizes();
+}
- int x, y = 0;
- if (this == ::leadGrid) //avoid back coupling
- {
- if (this == m_gridLeft)
+
+void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap)
+{
+ currentSortColumn = sortColumn;
+ sortMarker = bitmap;
+}
+
+
+void CustomGrid::DrawColLabel(wxDC& dc, int col)
+{
+ wxGrid::DrawColLabel(dc, col);
+
+ if (col == currentSortColumn)
+ dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
+}
+
+
+void CustomGrid::setColumnAttributes(const xmlAccess::XmlGlobalSettings::ColumnAttributes& attr)
+{
+ //remove special alignment for column "size"
+ for (int i = 0; i < GetNumberCols(); ++i)
+ if (getTypeAtPos(i) == XmlGlobalSettings::SIZE)
{
- GetViewStart(&x, &y);
- m_gridRight->Scroll(x, y);
- m_gridMiddle->Scroll(-1, y); //scroll in y-direction only
- adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i);
+ cellAttributes->SetAlignment(wxALIGN_LEFT,wxALIGN_CENTRE);
+ SetColAttr(i, cellAttributes);
+ break;
}
- else if (this == m_gridRight)
+//----------------------------------------------------------------------------------
+ setSortMarker(-1); //clear sorting marker
+
+ columnSettings.clear();
+ if (attr.size() == 0)
+ { //default settings:
+ xmlAccess::XmlGlobalSettings::ColumnAttrib newEntry;
+ newEntry.type = xmlAccess::XmlGlobalSettings::FILENAME;
+ newEntry.visible = true;
+ newEntry.position = 0;
+ newEntry.width = 138;
+ columnSettings.push_back(newEntry);
+
+ newEntry.type = xmlAccess::XmlGlobalSettings::REL_PATH;
+ newEntry.position = 1;
+ newEntry.width = 118;
+ columnSettings.push_back(newEntry);
+
+ newEntry.type = xmlAccess::XmlGlobalSettings::SIZE;
+ newEntry.position = 2;
+ newEntry.width = 67;
+ columnSettings.push_back(newEntry);
+
+ newEntry.type = xmlAccess::XmlGlobalSettings::DATE;
+ newEntry.position = 3;
+ newEntry.width = 113;
+ columnSettings.push_back(newEntry);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i)
{
- GetViewStart(&x, &y);
- m_gridLeft->Scroll(x, y);
- m_gridMiddle->Scroll(-1, y);
- adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ XmlGlobalSettings::ColumnAttrib newEntry;
+
+ if (i < attr.size())
+ newEntry = attr[i];
+ else
+ {
+ newEntry.type = xmlAccess::XmlGlobalSettings::FILENAME;
+ newEntry.visible = true;
+ newEntry.position = i;
+ newEntry.width = 100;
+ }
+ columnSettings.push_back(newEntry);
}
- else if (this == m_gridMiddle)
+
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByType);
+ for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i) //just be sure that each type exists only once
+ columnSettings[i].type = XmlGlobalSettings::ColumnTypes(i);
+
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionOnly);
+ for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i) //just be sure that positions are numbered correctly
+ columnSettings[i].position = i;
+
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility);
+ }
+
+ std::vector<XmlGlobalSettings::ColumnTypes> newPositions;
+ for (unsigned int i = 0; i < columnSettings.size() && columnSettings[i].visible; ++i) //hidden columns are sorted to the end of vector!
+ newPositions.push_back(columnSettings[i].type);
+
+ //set column positions
+ assert(gridDataTable);
+ gridDataTable->setupColumns(newPositions);
+
+ //set column width (set them after setupColumns!)
+ for (unsigned int i = 0; i < newPositions.size(); ++i)
+ SetColSize(i, columnSettings[i].width);
+
+//--------------------------------------------------------------------------------------------------------
+ //set special alignment for column "size"
+ for (int i = 0; i < GetNumberCols(); ++i)
+ if (getTypeAtPos(i) == XmlGlobalSettings::SIZE)
{
- GetViewStart(&x, &y);
- m_gridLeft->Scroll(-1, y);
- m_gridRight->Scroll(-1, y);
- adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i);
+ cellAttributes->SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE);
+ SetColAttr(i, cellAttributes); //make filesize right justified on grids
+ break;
}
- }
+
+ ClearSelection();
+ ForceRefresh();
}
-//these classes will scroll together, hence the name ;)
-void CustomGrid::setScrollFriends(CustomGrid* gridLeft, CustomGrid* gridRight, CustomGrid* gridMiddle)
+xmlAccess::XmlGlobalSettings::ColumnAttributes CustomGrid::getColumnAttributes()
{
- assert(gridLeft && gridRight && gridMiddle);
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility);
- m_gridLeft = gridLeft;
- m_gridRight = gridRight;
- m_gridMiddle = gridMiddle;
+ xmlAccess::XmlGlobalSettings::ColumnAttributes output;
+ xmlAccess::XmlGlobalSettings::ColumnAttrib newEntry;
+ for (unsigned int i = 0; i < columnSettings.size(); ++i)
+ {
+ newEntry = columnSettings[i];
+ if (newEntry.visible) //hidden columns are sorted to the end of vector!
+ newEntry.width = GetColSize(i);
+ output.push_back(newEntry);
+ }
- assert(gridDataTable);
- if (this == m_gridLeft)
- gridDataTable->SetGridIdentifier(1);
- else if (this == m_gridRight)
- gridDataTable->SetGridIdentifier(2);
- else if (this == m_gridMiddle)
- gridDataTable->SetGridIdentifier(3);
- else
- assert (false);
+ return output;
}
-void CustomGrid::setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData)
-{ //set underlying grid data
+XmlGlobalSettings::ColumnTypes CustomGrid::getTypeAtPos(unsigned pos) const
+{
assert(gridDataTable);
- gridDataTable->setGridDataTable(gridRefUI, gridData);
+ return gridDataTable->getTypeAtPos(pos);
}
-void CustomGrid::updateGridSizes()
+wxString CustomGrid::getTypeName(XmlGlobalSettings::ColumnTypes colType)
{
- assert(gridDataTable);
- gridDataTable->updateGridSizes();
+ switch (colType)
+ {
+ case XmlGlobalSettings::FILENAME:
+ return _("Filename");
+ case XmlGlobalSettings::REL_PATH:
+ return _("Relative path");
+ case XmlGlobalSettings::SIZE:
+ return _("Size");
+ case XmlGlobalSettings::DATE:
+ return _("Date");
+ default:
+ return wxEmptyString;
+ }
}
+//############################################################################################
+//CustomGrid specializations
-void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap)
+CustomGridLeft::CustomGridLeft(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name) :
+ CustomGrid(parent, id, pos, size, style, name) {}
+
+
+bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
{
- currentSortColumn = sortColumn;
- sortMarker = bitmap;
+ //use custom wxGridTableBase class for management of large sets of formatted data.
+ //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default.
+ gridDataTable = new CustomGridTableLeft();
+ SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
+ return true;
}
-void CustomGrid::DrawColLabel(wxDC& dc, int col)
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+void CustomGridLeft::DoPrepareDC(wxDC& dc)
{
- assert(0 <= col && col < 4);
+ wxScrollHelper::DoPrepareDC(dc);
- wxGrid::DrawColLabel(dc, col);
+ int x, y = 0;
+ if (this == ::leadGrid) //avoid back coupling
+ {
+ GetViewStart(&x, &y);
+ m_gridMiddle->Scroll(-1, y); //scroll in y-direction only
+ m_gridRight->Scroll(x, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ }
+}
- if (col == currentSortColumn)
+
+//----------------------------------------------------------------------------------------
+CustomGridMiddle::CustomGridMiddle(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name) :
+ CustomGrid(parent, id, pos, size, style, name) {}
+
+
+bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+{
+ CustomGridTableMiddle* newTable = new CustomGridTableMiddle();
+ gridDataTable = newTable;
+ 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 GridCellRendererAddCheckbox(newTable)); //SetDefaultRenderer takes ownership!
+
+ return true;
+}
+
+
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+void CustomGridMiddle::DoPrepareDC(wxDC& dc)
+{
+ wxScrollHelper::DoPrepareDC(dc);
+
+ int x, y = 0;
+ if (this == ::leadGrid) //avoid back coupling
{
- dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
+ GetViewStart(&x, &y);
+ m_gridLeft->Scroll(-1, y);
+ m_gridRight->Scroll(-1, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
}
}
+
+void CustomGridMiddle::GridCellRendererAddCheckbox::Draw(wxGrid& grid,
+ wxGridCellAttr& attr,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected)
+{
+ const int selected = m_gridDataTable->selectedForSynchronization(row);
+ if (selected < 0) //no valid row
+ {
+ wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
+ return;
+ }
+
+ const int shift = std::min(11 + 3, rect.GetWidth()); //11 is width of checkbox image
+
+ wxRect rectShrinked(rect);
+
+ //clean first block of rect that will receive image of checkbox
+ rectShrinked.SetWidth(shift);
+ dc.SetPen(*wxWHITE_PEN);
+ dc.SetBrush(*wxWHITE_BRUSH);
+ dc.DrawRectangle(rectShrinked);
+
+ //print image into first block
+ rectShrinked.SetX(1);
+ if (selected > 0)
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+ else //if (selected == 0) -> redundant
+ 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(shift);
+ wxGridCellStringRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+}
+
+
+//----------------------------------------------------------------------------------------
+CustomGridRight::CustomGridRight(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name) :
+ CustomGrid(parent, id, pos, size, style, name) {}
+
+
+bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+{
+ gridDataTable = new CustomGridTableRight();
+ SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
+ return true;
+}
+
+
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+void CustomGridRight::DoPrepareDC(wxDC& dc)
+{
+ wxScrollHelper::DoPrepareDC(dc);
+
+ int x, y = 0;
+ if (this == ::leadGrid) //avoid back coupling
+ {
+ GetViewStart(&x, &y);
+ m_gridLeft->Scroll(x, y);
+ m_gridMiddle->Scroll(-1, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ }
+}
diff --git a/library/CustomGrid.h b/library/CustomGrid.h
index bd2f3fa8..97642159 100644
--- a/library/CustomGrid.h
+++ b/library/CustomGrid.h
@@ -4,12 +4,13 @@
#include <vector>
#include <wx/grid.h>
#include "../FreeFileSync.h"
+#include "processXml.h"
using namespace FreeFileSync;
-class CustomGridTableBase;
-
+class CustomGridTable;
+class CustomGridTableMiddle;
//##################################################################################
extern const wxGrid* leadGrid; //this global variable is not very nice...
@@ -24,35 +25,128 @@ public:
long style = wxWANTS_CHARS,
const wxString& name = wxGridNameStr);
- ~CustomGrid();
+ virtual ~CustomGrid() {}
- virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
//overwrite virtual method to finally get rid of the scrollbars
virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh = true);
- //this method is called when grid view changes: useful for parallel updating of multiple grids
- virtual void DoPrepareDC(wxDC& dc);
+
virtual void DrawColLabel(wxDC& dc, int col);
- void deactivateScrollbars();
- void setScrollFriends(CustomGrid* gridLeft, CustomGrid* gridRight, CustomGrid* gridMiddle);
- void setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData);
+ void initSettings(bool enableScrollbars,
+ CustomGrid* gridLeft,
+ CustomGrid* gridRight,
+ CustomGrid* gridMiddle,
+ GridView* gridRefUI,
+ FileCompareResult* gridData);
+
+ //notify wxGrid that underlying table size has changed
void updateGridSizes();
+
//set sort direction indicator on UI
void setSortMarker(const int sortColumn, const wxBitmap* bitmap = &wxNullBitmap);
-private:
+ //set visibility, position and width of columns
+ void setColumnAttributes(const xmlAccess::XmlGlobalSettings::ColumnAttributes& attr);
+ xmlAccess::XmlGlobalSettings::ColumnAttributes getColumnAttributes();
+
+ xmlAccess::XmlGlobalSettings::ColumnTypes getTypeAtPos(unsigned pos) const;
+
+ static wxString getTypeName(xmlAccess::XmlGlobalSettings::ColumnTypes colType);
+
+ static const unsigned COLUMN_TYPE_COUNT = 4;
+
+protected:
+ //set visibility, position and width of columns
+ xmlAccess::XmlGlobalSettings::ColumnAttributes columnSettings;
+
+
void adjustGridHeights();
bool scrollbarsEnabled;
-
CustomGrid* m_gridLeft;
CustomGrid* m_gridRight;
CustomGrid* m_gridMiddle;
- CustomGridTableBase* gridDataTable;
+ CustomGridTable* gridDataTable;
int currentSortColumn;
const wxBitmap* sortMarker;
};
+
+class CustomGridLeft : public CustomGrid
+{
+public:
+ CustomGridLeft(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxWANTS_CHARS,
+ const wxString& name = wxGridNameStr);
+
+ ~CustomGridLeft() {}
+
+ //this method is called when grid view changes: useful for parallel updating of multiple grids
+ virtual void DoPrepareDC(wxDC& dc);
+
+ virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
+};
+
+
+class CustomGridMiddle : public CustomGrid
+{
+public:
+ CustomGridMiddle(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxWANTS_CHARS,
+ const wxString& name = wxGridNameStr);
+
+ ~CustomGridMiddle() {}
+
+ //this method is called when grid view changes: useful for parallel updating of multiple grids
+ virtual void DoPrepareDC(wxDC& dc);
+
+ virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
+
+private:
+
+ class GridCellRendererAddCheckbox : public wxGridCellStringRenderer
+ {
+ public:
+ GridCellRendererAddCheckbox(CustomGridTableMiddle* gridDataTable) : m_gridDataTable(gridDataTable) {};
+
+
+ virtual void Draw(wxGrid& grid,
+ wxGridCellAttr& attr,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected);
+
+ private:
+ CustomGridTableMiddle* m_gridDataTable;
+ };
+};
+
+
+class CustomGridRight : public CustomGrid
+{
+public:
+ CustomGridRight(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxWANTS_CHARS,
+ const wxString& name = wxGridNameStr);
+
+ ~CustomGridRight() {}
+
+ //this method is called when grid view changes: useful for parallel updating of multiple grids
+ virtual void DoPrepareDC(wxDC& dc);
+
+ virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
+};
+
#endif // CUSTOMGRID_H_INCLUDED
diff --git a/library/customButton.cpp b/library/customButton.cpp
new file mode 100644
index 00000000..5cfa8a5a
--- /dev/null
+++ b/library/customButton.cpp
@@ -0,0 +1,293 @@
+#include "customButton.h"
+#include <wx/dcmemory.h>
+#include <wx/image.h>
+
+wxButtonWithImage::wxButtonWithImage(wxWindow *parent,
+ wxWindowID id,
+ const wxString& label,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& validator,
+ const wxString& name) :
+ wxBitmapButton(parent, id, wxNullBitmap, pos, size, style | wxBU_AUTODRAW, validator, name)
+{
+ setTextLabel(label);
+}
+
+
+void wxButtonWithImage::setBitmapFront(const wxBitmap& bitmap)
+{
+ bitmapFront = bitmap;
+ refreshButtonLabel();
+}
+
+
+void wxButtonWithImage::setTextLabel(const wxString& text)
+{
+ textLabel = text;
+ wxBitmapButton::SetLabel(text);
+ refreshButtonLabel();
+}
+
+
+void wxButtonWithImage::setBitmapBack(const wxBitmap& bitmap)
+{
+ bitmapBack = bitmap;
+ refreshButtonLabel();
+}
+
+
+void makeWhiteTransparent(const wxColor exceptColor, wxImage& image)
+{
+ unsigned char* alphaData = image.GetAlpha();
+ if (alphaData)
+ {
+ assert(exceptColor.Red() != 255);
+
+ unsigned char exCol = exceptColor.Red(); //alpha value can be extracted from any one of (red/green/blue)
+ unsigned char* imageStart = image.GetData();
+
+ unsigned char* j = alphaData;
+ const unsigned char* const rowEnd = j + image.GetWidth() * image.GetHeight();
+ while (j != rowEnd)
+ {
+ const unsigned char* imagePixel = imageStart + (j - alphaData) * 3; //each pixel consists of three chars
+ //exceptColor(red,green,blue) becomes fully opaque(255), while white(255,255,255) becomes transparent(0)
+ *(j++) = ((255 - imagePixel[0]) * wxIMAGE_ALPHA_OPAQUE) / (255 - exCol);
+ }
+ }
+}
+
+
+wxSize getSizeNeeded(const wxString& text, wxFont& font)
+{
+ wxCoord width, height;
+ wxMemoryDC dc;
+
+ wxString textFormatted = text;
+ textFormatted.Replace(wxT("&"), wxT(""), false); //remove accelerator
+ dc.GetMultiLineTextExtent(textFormatted, &width, &height , NULL, &font);
+ return wxSize(width, height);
+}
+
+/*
+inline
+void linearInterpolationHelper(const int shift, wxImage& img)
+{
+ unsigned char* const data = img.GetData();
+ const int width = img.GetWidth();
+ if (width < 2)
+ return;
+
+ const float intensity = 0.25;
+
+ for (int y = 1; y < img.GetHeight() - 1; ++y)
+ {
+ float back = 0;
+ float middle = 0;
+ float front = 0;
+
+ unsigned char* location = data + 3 * (y * width) + shift;
+ const unsigned char* const endPos = location + 3 * width;
+
+ middle = (*location + *(location - 3 * width) + *(location + 3 * width)) / 3;;
+ front = (*(location + 3) + *(location + 3 * (1 - width)) + *(location + 3 * (1 + width))) / 3;
+ *location += ((middle + front) / 2 - *location) * intensity;
+ location += 3;
+
+ while (location < endPos - 3)
+ {
+ back = middle;
+ middle = front;
+ front = (*(location + 3) + *(location + 3 * (1 - width)) + *(location + 3 * (1 + width))) / 3;
+ *location += ((back + middle + front) / 3 - *location) * intensity;
+ location += 3;
+ }
+
+ back = middle;
+ middle = front;
+ *location += ((back + middle) / 2 - *location) * intensity;
+ }
+}
+
+
+void linearInterpolation(wxImage& img)
+{
+ linearInterpolationHelper(0, img); //red channel
+ linearInterpolationHelper(1, img); //green channel
+ linearInterpolationHelper(2, img); //blue channel
+}
+*/
+
+wxBitmap wxButtonWithImage::createBitmapFromText(const wxString& text)
+{
+ wxFont currentFont = wxBitmapButton::GetFont();
+ wxColor textColor = wxBitmapButton::GetForegroundColour();
+
+ wxSize sizeNeeded = getSizeNeeded(text, currentFont);
+ wxBitmap newBitmap(sizeNeeded.GetWidth(), sizeNeeded.GetHeight());
+
+ wxMemoryDC dc;
+ dc.SelectObject(newBitmap);
+
+ //set up white background
+ dc.SetBackground(*wxWHITE_BRUSH);
+ dc.Clear();
+
+ //find position of accelerator
+ int indexAccel = -1;
+ size_t accelPos;
+ wxString textLabelFormatted = text;
+ if ((accelPos = text.find(wxT("&"))) != wxString::npos)
+ {
+ textLabelFormatted.Replace(wxT("&"), wxT(""), false); //remove accelerator
+ indexAccel = accelPos;
+ }
+
+ dc.SetTextForeground(textColor);
+ dc.SetTextBackground(*wxWHITE);
+ dc.SetFont(currentFont);
+ dc.DrawLabel(textLabelFormatted, wxNullBitmap, wxRect(0, 0, newBitmap.GetWidth(), newBitmap.GetHeight()), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, indexAccel);
+
+ dc.SelectObject(wxNullBitmap);
+
+ //add alpha channel to image
+ wxImage finalImage(newBitmap.ConvertToImage());
+ finalImage.SetAlpha();
+
+ //linearInterpolation(finalImage);
+
+ //make white background transparent
+ makeWhiteTransparent(textColor, finalImage);
+
+ return wxBitmap(finalImage);
+}
+
+
+//copy one image into another, allowing arbitrary overlapping! (pos may contain negative numbers)
+void writeToImage(const wxImage& source, const wxPoint pos, wxImage& target)
+{
+ //determine startpositions in source and target image, as well as width and height to be copied
+ wxPoint posSrc, posTrg;
+ int width, height;
+
+ //X-axis
+ if (pos.x < 0)
+ {
+ posSrc.x = -pos.x;
+ posTrg.x = 0;
+ width = std::min(pos.x + source.GetWidth(), target.GetWidth());
+ }
+ else
+ {
+ posSrc.x = 0;
+ posTrg.x = pos.x;
+ width = std::min(target.GetWidth() - pos.x, source.GetWidth());
+ }
+
+ //Y-axis
+ if (pos.y < 0)
+ {
+ posSrc.y = -pos.y;
+ posTrg.y = 0;
+ height = std::min(pos.y + source.GetHeight(), target.GetHeight());
+ }
+ else
+ {
+ posSrc.y = 0;
+ posTrg.y = pos.y;
+ height = std::min(target.GetHeight() - pos.y, source.GetHeight());
+ }
+
+
+ if (width > 0 && height > 0)
+ {
+ //copy source to target respecting overlapping parts
+ const unsigned char* sourcePtr = source.GetData() + 3 * (posSrc.x + posSrc.y * source.GetWidth());
+ const unsigned char* const sourcePtrEnd = source.GetData() + 3 * (posSrc.x + (posSrc.y + height) * source.GetWidth());
+ unsigned char* targetPtr = target.GetData() + 3 * (posTrg.x + posTrg.y * target.GetWidth());
+
+ while (sourcePtr < sourcePtrEnd)
+ {
+ memcpy(targetPtr, sourcePtr, 3 * width);
+ sourcePtr += 3 * source.GetWidth();
+ targetPtr += 3 * target.GetWidth();
+ }
+
+ //handle different cases concerning alpha channel
+ if (source.HasAlpha())
+ {
+ if (!target.HasAlpha())
+ {
+ target.SetAlpha();
+ unsigned char* alpha = target.GetAlpha();
+ memset(alpha, wxIMAGE_ALPHA_OPAQUE, target.GetWidth() * target.GetHeight());
+ }
+
+ //copy alpha channel
+ const unsigned char* sourcePtr = source.GetAlpha() + (posSrc.x + posSrc.y * source.GetWidth());
+ const unsigned char* const sourcePtrEnd = source.GetAlpha() + (posSrc.x + (posSrc.y + height) * source.GetWidth());
+ unsigned char* targetPtr = target.GetAlpha() + (posTrg.x + posTrg.y * target.GetWidth());
+
+ while (sourcePtr < sourcePtrEnd)
+ {
+ memcpy(targetPtr, sourcePtr, width);
+ sourcePtr += source.GetWidth();
+ targetPtr += target.GetWidth();
+ }
+ }
+ else if (target.HasAlpha())
+ {
+ unsigned char* targetPtr = target.GetAlpha() + (posTrg.x + posTrg.y * target.GetWidth());
+ const unsigned char* const targetPtrEnd = target.GetAlpha() + (posTrg.x + (posTrg.y + height) * target.GetWidth());
+
+ while (targetPtr < targetPtrEnd)
+ {
+ memset(targetPtr, wxIMAGE_ALPHA_OPAQUE, width);
+ targetPtr += target.GetWidth();
+ }
+ }
+ }
+}
+
+
+void wxButtonWithImage::refreshButtonLabel()
+{
+ wxBitmap bitmapText = createBitmapFromText(textLabel);
+
+ //calculate dimensions of new button
+ const int height = std::max(std::max(bitmapFront.GetHeight(), bitmapText.GetHeight()), bitmapBack.GetHeight());
+ const int width = bitmapFront.GetWidth() + bitmapText.GetWidth() + bitmapBack.GetWidth();
+
+ //create a transparent image
+ wxImage transparentImage(width, height, false);
+ transparentImage.SetAlpha();
+ unsigned char* alpha = transparentImage.GetAlpha();
+ memset(alpha, wxIMAGE_ALPHA_TRANSPARENT, width * height);
+
+ //wxDC::DrawLabel() unfortunately isn't working for transparent images on Linux, so we need to use custom image-concatenation
+ if (bitmapFront.IsOk())
+ writeToImage(wxImage(bitmapFront.ConvertToImage()),
+ wxPoint(0, (transparentImage.GetHeight() - bitmapFront.GetHeight()) / 2),
+ transparentImage);
+
+ if (bitmapText.IsOk())
+ writeToImage(wxImage(bitmapText.ConvertToImage()),
+ wxPoint(bitmapFront.GetWidth(), (transparentImage.GetHeight() - bitmapText.GetHeight()) / 2),
+ transparentImage);
+
+ if (bitmapBack.IsOk())
+ writeToImage(wxImage(bitmapBack.ConvertToImage()),
+ wxPoint(bitmapFront.GetWidth() + bitmapText.GetWidth(), (transparentImage.GetHeight() - bitmapBack.GetHeight()) / 2),
+ transparentImage);
+
+ //adjust button size
+ wxSize minSize = GetMinSize();
+
+ //SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work corretly
+ wxBitmapButton::SetMinSize(wxSize(std::max(width + 10, minSize.GetWidth()), std::max(height + 5, minSize.GetHeight())));
+
+ //finally set bitmap
+ wxBitmapButton::SetBitmapLabel(wxBitmap(transparentImage));
+}
diff --git a/library/customButton.h b/library/customButton.h
new file mode 100644
index 00000000..1f3f50ec
--- /dev/null
+++ b/library/customButton.h
@@ -0,0 +1,40 @@
+/***************************************************************
+ * Purpose: wxButton with bitmap label
+ * Author: ZenJu (zhnmju123@gmx.de)
+ * Created: Feb. 2009
+ **************************************************************/
+
+#ifndef CUSTOMBUTTON_H_INCLUDED
+#define CUSTOMBUTTON_H_INCLUDED
+
+#include <wx/bmpbuttn.h>
+
+
+//wxButtonWithImage behaves like wxButton but optionally adds bitmap labels
+class wxButtonWithImage : public wxBitmapButton
+{
+public:
+ wxButtonWithImage(wxWindow *parent,
+ wxWindowID id,
+ const wxString& label,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = 0,
+ const wxValidator& validator = wxDefaultValidator,
+ const wxString& name = wxButtonNameStr);
+
+ void setBitmapFront(const wxBitmap& bitmap);
+ void setTextLabel( const wxString& text);
+ void setBitmapBack( const wxBitmap& bitmap);
+
+private:
+ wxBitmap createBitmapFromText(const wxString& text);
+ void refreshButtonLabel();
+
+ wxBitmap bitmapFront;
+ wxString textLabel;
+ wxBitmap bitmapBack;
+};
+
+
+#endif // CUSTOMBUTTON_H_INCLUDED
diff --git a/library/fileHandling.cpp b/library/fileHandling.cpp
index eb14b2f6..688d3640 100644
--- a/library/fileHandling.cpp
+++ b/library/fileHandling.cpp
@@ -8,9 +8,9 @@
#endif // FFS_WIN
inline
-bool endsWithPathSeparator(const wxChar* name)
+bool endsWithPathSeparator(const Zstring& name)
{
- size_t len = wxStrlen(name);
+ const size_t len = name.length();
return len && (name[len - 1] == GlobalResources::FILE_NAME_SEPARATOR);
}
@@ -84,12 +84,12 @@ bool moveToRecycleBin(const Zstring& filename) throw(RuntimeException)
inline
void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin)
{
- if (!wxFileExists(filename)) return; //this is NOT an error situation: the manual deletion relies on it!
+ if (!wxFileExists(filename.c_str())) return; //this is NOT an error situation: the manual deletion relies on it!
if (useRecycleBin)
{
if (!moveToRecycleBin(filename))
- throw FileError(wxString(_("Error moving to recycle bin:")) + wxT(" \"") + filename.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error moving to recycle bin:")) + wxT(" \"") + filename + wxT("\""));
return;
}
@@ -97,11 +97,11 @@ void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin)
if (!SetFileAttributes(
filename.c_str(), //address of filename
FILE_ATTRIBUTE_NORMAL //attributes to set
- )) throw FileError(wxString(_("Error deleting file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
+ )) throw FileError(Zstring(_("Error deleting file:")) + wxT(" \"") + filename + wxT("\""));
#endif //FFS_WIN
- if (!wxRemoveFile(filename))
- throw FileError(wxString(_("Error deleting file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
+ if (!wxRemoveFile(filename.c_str()))
+ throw FileError(Zstring(_("Error deleting file:")) + wxT(" \"") + filename + wxT("\""));
}
@@ -112,12 +112,12 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc
if (useRecycleBin)
{
if (!moveToRecycleBin(directory))
- throw FileError(wxString(_("Error moving to recycle bin:")) + wxT(" \"") + directory.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error moving to recycle bin:")) + wxT(" \"") + directory + wxT("\""));
return;
}
- vector<Zstring> fileList;
- vector<Zstring> dirList;
+ std::vector<Zstring> fileList;
+ std::vector<Zstring> dirList;
try
{ //should be executed in own scope so that directory access does not disturb deletion!
@@ -125,7 +125,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc
}
catch (const FileError& e)
{
- throw FileError(wxString(_("Error deleting directory:")) + wxT(" \"") + directory.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error deleting directory:")) + wxT(" \"") + directory + wxT("\""));
}
for (unsigned int j = 0; j < fileList.size(); ++j)
@@ -139,11 +139,11 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc
if (!SetFileAttributes(
dirList[j].c_str(), // address of directory name
FILE_ATTRIBUTE_NORMAL)) // attributes to set
- throw FileError(wxString(_("Error deleting directory:")) + wxT(" \"") + dirList[j].c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error deleting directory:")) + wxT(" \"") + dirList[j] + wxT("\""));
#endif // FFS_WIN
- if (!wxRmdir(dirList[j]))
- throw FileError(wxString(_("Error deleting directory:")) + wxT(" \"") + dirList[j].c_str() + wxT("\""));
+ if (!wxRmdir(dirList[j].c_str()))
+ throw FileError(Zstring(_("Error deleting directory:")) + wxT(" \"") + dirList[j] + wxT("\""));
}
}
@@ -157,12 +157,12 @@ void FreeFileSync::createDirectory(const Zstring& directory, const int level)
return;
//try to create directory
- if (wxMkdir(directory))
+ if (wxMkdir(directory.c_str()))
return;
//if not successfull try to create parent folders first
Zstring parentDir;
- if (endsWithPathSeparator(directory.c_str())) //may be valid on first level of recursion at most! Usually never true!
+ if (endsWithPathSeparator(directory)) //may be valid on first level of recursion at most! Usually never true!
{
parentDir = directory.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
parentDir = parentDir.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
@@ -176,10 +176,10 @@ void FreeFileSync::createDirectory(const Zstring& directory, const int level)
createDirectory(parentDir, level + 1);
//now creation should be possible
- if (!wxMkdir(directory))
+ if (!wxMkdir(directory.c_str()))
{
if (level == 0)
- throw FileError(wxString(_("Error creating directory:")) + wxT(" \"") + directory.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error creating directory:")) + wxT(" \"") + directory + wxT("\""));
}
}
@@ -189,12 +189,12 @@ void FreeFileSync::copyFolderAttributes(const Zstring& source, const Zstring& ta
#ifdef FFS_WIN
DWORD attr = GetFileAttributes(source.c_str()); // address of the name of a file or directory
if (attr == 0xFFFFFFFF)
- throw FileError(wxString(_("Error reading file attributes:")) + wxT(" \"") + source.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error reading folder attributes:")) + wxT(" \"") + source + wxT("\""));
if (!SetFileAttributes(
target.c_str(), // address of filename
attr)) // address of attributes to set
- throw FileError(wxString(_("Error writing file attributes:")) + wxT(" \"") + target.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error writing folder attributes:")) + wxT(" \"") + target + wxT("\""));
#elif defined FFS_LINUX
//Linux doesn't use attributes for files or folders
#endif
@@ -204,19 +204,19 @@ void FreeFileSync::copyFolderAttributes(const Zstring& source, const Zstring& ta
class GetAllFilesSimple : public wxDirTraverser
{
public:
- GetAllFilesSimple(vector<Zstring>& files, vector<Zstring>& subDirectories) :
+ GetAllFilesSimple(std::vector<Zstring>& files, std::vector<Zstring>& subDirectories) :
m_files(files),
m_dirs(subDirectories) {}
wxDirTraverseResult OnDir(const wxString& dirname)
{
- m_dirs.push_back(dirname);
+ m_dirs.push_back(dirname.c_str());
return wxDIR_CONTINUE;
}
wxDirTraverseResult OnFile(const wxString& filename)
{
- m_files.push_back(filename);
+ m_files.push_back(filename.c_str());
return wxDIR_CONTINUE;
}
@@ -227,22 +227,22 @@ public:
}
private:
- vector<Zstring>& m_files;
- vector<Zstring>& m_dirs;
+ std::vector<Zstring>& m_files;
+ std::vector<Zstring>& m_dirs;
};
-void FreeFileSync::getAllFilesAndDirs(const Zstring& sourceDir, vector<Zstring>& files, vector<Zstring>& directories) throw(FileError)
+void FreeFileSync::getAllFilesAndDirs(const Zstring& sourceDir, std::vector<Zstring>& files, std::vector<Zstring>& directories) throw(FileError)
{
files.clear();
directories.clear();
//get all files and directories from current directory (and subdirectories)
- wxDir dir(sourceDir);
+ wxDir dir(sourceDir.c_str());
GetAllFilesSimple traverser(files, directories);
if (dir.Traverse(traverser) == (size_t)-1)
- throw FileError(wxString(_("Error traversing directory:")) + wxT(" \"") + sourceDir.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error traversing directory:")) + wxT(" \"") + sourceDir + wxT("\""));
}
@@ -267,10 +267,10 @@ void getWin32FileInformation(const WIN32_FIND_DATA& input, FreeFileSync::FileInf
{
//convert UTC FILETIME to ANSI C format (number of seconds since Jan. 1st 1970 UTC)
wxULongLong writeTimeLong(input.ftLastWriteTime.dwHighDateTime, input.ftLastWriteTime.dwLowDateTime);
- writeTimeLong /= 10000000; //reduce precision to 1 second (FILETIME has unit 10^-7 s)
- writeTimeLong -= wxULongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s
- output.lastWriteTimeRaw = writeTimeLong.GetLo(); //it should fit into a 32bit variable now
- assert(writeTimeLong.GetHi() == 0);
+ writeTimeLong /= 10000000; //reduce precision to 1 second (FILETIME has unit 10^-7 s)
+ writeTimeLong -= wxULongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s
+ assert(writeTimeLong.GetHi() == 0); //it should fit into a 32bit variable now
+ output.lastWriteTimeRaw = writeTimeLong.GetLo();
output.fileSize = wxULongLong(input.nFileSizeHigh, input.nFileSizeLow);
}
@@ -281,7 +281,7 @@ class EnhancedFileTraverser : public wxDirTraverser
public:
EnhancedFileTraverser(FreeFileSync::FullDetailFileTraverser* sink) : m_sink(sink) {}
- virtual wxDirTraverseResult OnFile(const wxString& filename)
+ wxDirTraverseResult OnFile(const wxString& filename) //virtual impl.
{
struct stat fileInfo;
if (stat(filename.c_str(), &fileInfo) != 0)
@@ -291,17 +291,17 @@ public:
details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second
details.fileSize = fileInfo.st_size;
- return m_sink->OnFile(filename, details);
+ return m_sink->OnFile(filename.c_str(), details);
}
- virtual wxDirTraverseResult OnDir(const wxString& dirname)
+ wxDirTraverseResult OnDir(const wxString& dirname) //virtual impl.
{
- return m_sink->OnDir(dirname);
+ return m_sink->OnDir(dirname.c_str());
}
- virtual wxDirTraverseResult OnOpenError(const wxString& errorText)
+ wxDirTraverseResult OnOpenError(const wxString& errorText) //virtual impl.
{
- return m_sink->OnError(errorText);
+ return m_sink->OnError(errorText.c_str());
}
private:
@@ -322,7 +322,7 @@ bool FreeFileSync::traverseInDetail(const Zstring& directory, FullDetailFileTrav
}
Zstring directoryFormatted = directory;
- if (!endsWithPathSeparator(directoryFormatted.c_str()))
+ if (!endsWithPathSeparator(directoryFormatted))
directoryFormatted += GlobalResources::FILE_NAME_SEPARATOR;
const Zstring filespec = directoryFormatted + wxT("*.*");
@@ -403,10 +403,10 @@ bool FreeFileSync::traverseInDetail(const Zstring& directory, FullDetailFileTrav
#elif defined FFS_LINUX
//use standard file traverser and enrich output with additional file information
- //could be improved with own traversing algorithm for optimized performance
+ //could be improved with custom traversing algorithm for optimized performance
EnhancedFileTraverser traverser(sink);
- wxDir dir(directory);
+ wxDir dir(directory.c_str());
if (dir.IsOpened())
dir.Traverse(traverser);
diff --git a/library/fileHandling.h b/library/fileHandling.h
index cd86333b..5578ce91 100644
--- a/library/fileHandling.h
+++ b/library/fileHandling.h
@@ -8,21 +8,21 @@
class FileError //Exception class used to notify file/directory copy/delete errors
{
public:
- FileError(const wxString& txt) : errorMessage(txt) {}
+ FileError(const Zstring& txt) : errorMessage(txt) {}
- wxString show() const
+ Zstring show() const
{
return errorMessage;
}
private:
- wxString errorMessage;
+ Zstring errorMessage;
};
namespace FreeFileSync
{
- void getAllFilesAndDirs(const Zstring& sourceDir, vector<Zstring>& files, vector<Zstring>& directories) throw(FileError);
+ void getAllFilesAndDirs(const Zstring& sourceDir, std::vector<Zstring>& files, std::vector<Zstring>& directories) throw(FileError);
//recycler
bool recycleBinExists(); //test existence of Recycle Bin API on current system
diff --git a/library/globalFunctions.cpp b/library/globalFunctions.cpp
index 7f8b57c0..eed6dfe9 100644
--- a/library/globalFunctions.cpp
+++ b/library/globalFunctions.cpp
@@ -11,27 +11,27 @@ int globalFunctions::round(const double d)
}
-string globalFunctions::numberToString(const unsigned int number)
+std::string globalFunctions::numberToString(const unsigned int number)
{
char result[100];
sprintf(result, "%u", number);
- return string(result);
+ return std::string(result);
}
-string globalFunctions::numberToString(const int number)
+std::string globalFunctions::numberToString(const int number)
{
char result[100];
sprintf(result, "%d", number);
- return string(result);
+ return std::string(result);
}
-string globalFunctions::numberToString(const float number)
+std::string globalFunctions::numberToString(const float number)
{
char result[100];
sprintf(result, "%f", number);
- return string(result);
+ return std::string(result);
}
@@ -53,14 +53,14 @@ wxString globalFunctions::numberToWxString(const float number)
}
-int globalFunctions::stringToInt(const string& number)
+int globalFunctions::stringToInt(const std::string& number)
{
return atoi(number.c_str());
}
inline
-double globalFunctions::stringToDouble(const string& number)
+double globalFunctions::stringToDouble(const std::string& number)
{
return atof(number.c_str());
}
@@ -96,7 +96,7 @@ wxString& globalFunctions::includeNumberSeparator(wxString& number)
}
-int globalFunctions::readInt(ifstream& stream)
+int globalFunctions::readInt(std::ifstream& stream)
{
int result = 0;
char* buffer = reinterpret_cast<char*>(&result);
@@ -105,7 +105,7 @@ int globalFunctions::readInt(ifstream& stream)
}
-void globalFunctions::writeInt(ofstream& stream, const int number)
+void globalFunctions::writeInt(std::ofstream& stream, const int number)
{
const char* buffer = reinterpret_cast<const char*>(&number);
stream.write(buffer, sizeof(int));
diff --git a/library/globalFunctions.h b/library/globalFunctions.h
index f46a5906..b4ccba5c 100644
--- a/library/globalFunctions.h
+++ b/library/globalFunctions.h
@@ -10,8 +10,6 @@
#include <wx/stream.h>
#include <wx/stopwatch.h>
-using namespace std;
-
namespace globalFunctions
{
@@ -23,24 +21,24 @@ namespace globalFunctions
return(d<0?-d:d);
}
- string numberToString(const unsigned int number); //convert number to string
- string numberToString(const int number); //convert number to string
- string numberToString(const float number); //convert number to string
+ std::string numberToString(const unsigned int number); //convert number to string
+ std::string numberToString(const int number); //convert number to string
+ std::string numberToString(const float number); //convert number to string
wxString numberToWxString(const unsigned int number); //convert number to wxString
wxString numberToWxString(const int number); //convert number to wxString
wxString numberToWxString(const float number); //convert number to wxString
- int stringToInt( const string& number); //convert String to number
- double stringToDouble(const string& number); //convert String to number
+ int stringToInt( const std::string& number); //convert String to number
+ double stringToDouble(const std::string& number); //convert String to number
int wxStringToInt( const wxString& number); //convert wxString to number
double wxStringToDouble(const wxString& number); //convert wxString to number
wxString& includeNumberSeparator(wxString& number);
- int readInt(ifstream& stream); //read int from file stream
- void writeInt(ofstream& stream, const int number); //write int to filestream
+ int readInt(std::ifstream& stream); //read int from file stream
+ void writeInt(std::ofstream& stream, const int number); //write int to filestream
int readInt(wxInputStream& stream); //read int from file stream
void writeInt(wxOutputStream& stream, const int number); //write int to filestream
@@ -108,12 +106,12 @@ private:
//Note: the following lines are a performance optimization for deleting elements from a vector. It is incredibly faster to create a new
//vector and leave specific elements out than to delete row by row and force recopying of most elements for each single deletion (linear vs quadratic runtime)
template <class T>
-void removeRowsFromVector(vector<T>& grid, const set<int>& rowsToRemove)
+void removeRowsFromVector(std::vector<T>& grid, const std::set<int>& rowsToRemove)
{
- vector<T> temp;
+ std::vector<T> temp;
int rowToSkip = -1; //keep it an INT!
- set<int>::iterator rowToSkipIndex = rowsToRemove.begin();
+ std::set<int>::iterator rowToSkipIndex = rowsToRemove.begin();
if (rowToSkipIndex != rowsToRemove.end())
rowToSkip = *rowToSkipIndex;
diff --git a/library/misc.cpp b/library/misc.cpp
index 050be108..f5c562c7 100644
--- a/library/misc.cpp
+++ b/library/misc.cpp
@@ -19,8 +19,7 @@ void exchangeEscapeChars(wxString& data)
{
//read next character
++input;
- value = *input;
- if (value == wxChar(0))
+ if ((value = *input) == wxChar(0))
break;
switch (value)
@@ -60,23 +59,32 @@ void CustomLocale::setLanguage(const int language)
{
currentLanguage = language;
- string languageFile;
+ std::string languageFile;
switch (language)
{
- case wxLANGUAGE_GERMAN:
- languageFile = "german.lng";
+ case wxLANGUAGE_CHINESE_SIMPLIFIED:
+ languageFile = "Languages/chinese_simple.lng";
+ break;
+ case wxLANGUAGE_DUTCH:
+ languageFile = "Languages/dutch.lng";
break;
case wxLANGUAGE_FRENCH:
- languageFile = "french.lng";
+ languageFile = "Languages/french.lng";
+ break;
+ case wxLANGUAGE_GERMAN:
+ languageFile = "Languages/german.lng";
+ break;
+ case wxLANGUAGE_ITALIAN:
+ languageFile = "Languages/italian.lng";
break;
case wxLANGUAGE_JAPANESE:
- languageFile = "japanese.lng";
+ languageFile = "Languages/japanese.lng";
break;
- case wxLANGUAGE_DUTCH:
- languageFile = "dutch.lng";
+ case wxLANGUAGE_POLISH:
+ languageFile = "Languages/polish.lng";
break;
- case wxLANGUAGE_CHINESE_SIMPLIFIED:
- languageFile = "chinese_simple.lng";
+ case wxLANGUAGE_PORTUGUESE:
+ languageFile = "Languages/portuguese.lng";
break;
default:
languageFile.clear();
@@ -96,7 +104,7 @@ void CustomLocale::setLanguage(const int language)
char temp[bufferSize];
if (!languageFile.empty())
{
- ifstream langFile(languageFile.c_str(), ios::binary);
+ std::ifstream langFile(languageFile.c_str(), std::ios::binary);
if (langFile)
{
TranslationLine currentLine;
diff --git a/library/misc.h b/library/misc.h
index 5fa2c943..c3e960ff 100644
--- a/library/misc.h
+++ b/library/misc.h
@@ -6,7 +6,6 @@
#include <wx/intl.h>
#include <wx/panel.h>
-using namespace std;
struct TranslationLine
{
@@ -26,7 +25,7 @@ struct TranslationLine
return (original == b.original);
}
};
-typedef set<TranslationLine> Translation;
+typedef std::set<TranslationLine> Translation;
class CustomLocale : public wxLocale
@@ -44,7 +43,7 @@ public:
const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const;
- static const string FfsLanguageDat;
+ static const std::string FfsLanguageDat;
private:
Translation translationDB;
diff --git a/library/multithreading.cpp b/library/multithreading.cpp
index bf5918d2..f7f5ed04 100644
--- a/library/multithreading.cpp
+++ b/library/multithreading.cpp
@@ -39,6 +39,7 @@ class WorkerThread : public wxThread
public:
WorkerThread(UpdateWhileExecuting* handler) :
+ wxThread(wxTHREAD_DETACHED),
readyToBeginProcessing(),
beginProcessing(readyToBeginProcessing),
threadIsInitialized(false),
diff --git a/library/processXml.cpp b/library/processXml.cpp
index 04048124..80ac190b 100644
--- a/library/processXml.cpp
+++ b/library/processXml.cpp
@@ -8,16 +8,16 @@ using namespace globalFunctions;
using namespace xmlAccess;
//small helper functions
-bool readXmlElementValue(string& output, const TiXmlElement* parent, const string& name);
-bool readXmlElementValue(int& output, const TiXmlElement* parent, const string& name);
-bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const string& name);
-bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const string& name);
-bool readXmlElementValue(bool& output, const TiXmlElement* parent, const string& name);
+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(bool& output, const TiXmlElement* parent, const std::string& name);
-void addXmlElement(TiXmlElement* parent, const string& name, const string& value);
-void addXmlElement(TiXmlElement* parent, const string& name, const int value);
-void addXmlElement(TiXmlElement* parent, const string& name, const SyncConfiguration::Direction value);
-void addXmlElement(TiXmlElement* parent, const string& name, const bool value);
+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 bool value);
class XmlConfigInput
@@ -40,7 +40,7 @@ public:
private:
//read basic FreefileSync settings (used by commandline and GUI), return true if ALL values have been retrieved successfully
- bool readXmlMainConfig(MainConfiguration& mainCfg, vector<FolderPair>& directoryPairs);
+ bool readXmlMainConfig(MainConfiguration& mainCfg, std::vector<FolderPair>& directoryPairs);
TiXmlDocument doc;
bool loadSuccess;
@@ -56,15 +56,15 @@ public:
bool writeToFile();
//write gui settings
- bool writeXmlGuiConfig(const XmlGuiConfig& inputCfg);
+ bool writeXmlGuiConfig(const XmlGuiConfig& outputCfg);
//write batch settings
- bool writeXmlBatchConfig(const XmlBatchConfig& inputCfg);
+ bool writeXmlBatchConfig(const XmlBatchConfig& outputCfg);
//write global settings
- bool writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg);
+ bool writeXmlGlobalSettings(const XmlGlobalSettings& outputCfg);
private:
//write basic FreefileSync settings (used by commandline and GUI), return true if everything was written successfully
- bool writeXmlMainConfig(const MainConfiguration& mainCfg, const vector<FolderPair>& directoryPairs);
+ bool writeXmlMainConfig(const MainConfiguration& mainCfg, const std::vector<FolderPair>& directoryPairs);
TiXmlDocument doc;
const wxString& m_fileName;
@@ -89,18 +89,18 @@ XmlType xmlAccess::getXmlType(const wxString& filename)
TiXmlElement* root = doc.RootElement();
- if (!root || (root->ValueStr() != string("FreeFileSync"))) //check for FFS configuration xml
+ if (!root || (root->ValueStr() != std::string("FreeFileSync"))) //check for FFS configuration xml
return XML_OTHER;
const char* cfgType = root->Attribute("XmlType");
if (!cfgType)
return XML_OTHER;
- if (string(cfgType) == "BATCH")
+ if (std::string(cfgType) == "BATCH")
return XML_BATCH_CONFIG;
- else if (string(cfgType) == "GUI")
+ else if (std::string(cfgType) == "GUI")
return XML_GUI_CONFIG;
- else if (string(cfgType) == "GLOBAL")
+ else if (std::string(cfgType) == "GLOBAL")
return XML_GLOBAL_SETTINGS;
else
return XML_OTHER;
@@ -115,10 +115,10 @@ XmlGuiConfig xmlAccess::readGuiConfig(const wxString& filename)
XmlGuiConfig outputCfg;
if (!inputFile.loadedSuccessfully())
- throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename + wxT("\""));
+ throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
if (!inputFile.readXmlGuiConfig(outputCfg)) //read GUI layout configuration
- throw FileError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + filename + wxT("\""));
+ throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
return outputCfg;
}
@@ -132,10 +132,10 @@ XmlBatchConfig xmlAccess::readBatchConfig(const wxString& filename)
XmlBatchConfig outputCfg;
if (!inputFile.loadedSuccessfully())
- throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename + wxT("\""));
+ throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
if (!inputFile.readXmlBatchConfig(outputCfg))
- throw FileError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + filename + wxT("\""));
+ throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
return outputCfg;
}
@@ -149,47 +149,47 @@ XmlGlobalSettings xmlAccess::readGlobalSettings()
XmlGlobalSettings outputCfg;
if (!inputFile.loadedSuccessfully())
- throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\""));
+ throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE.c_str() + wxT("\""));
if (!inputFile.readXmlGlobalSettings(outputCfg))
- throw FileError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\""));
+ throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE.c_str() + wxT("\""));
return outputCfg;
}
-void xmlAccess::writeGuiConfig(const wxString& filename, const XmlGuiConfig& inputCfg)
+void xmlAccess::writeGuiConfig(const wxString& filename, const XmlGuiConfig& outputCfg)
{
XmlConfigOutput outputFile(filename, XML_GUI_CONFIG);
//populate and write XML tree
- if ( !outputFile.writeXmlGuiConfig(inputCfg) || //add GUI layout configuration settings
+ if ( !outputFile.writeXmlGuiConfig(outputCfg) || //add GUI layout configuration settings
!outputFile.writeToFile()) //save XML
- throw FileError(wxString(_("Error writing file:")) + wxT(" \"") + filename + wxT("\""));
+ throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
return;
}
-void xmlAccess::writeBatchConfig(const wxString& filename, const XmlBatchConfig& inputCfg)
+void xmlAccess::writeBatchConfig(const wxString& filename, const XmlBatchConfig& outputCfg)
{
XmlConfigOutput outputFile(filename, XML_BATCH_CONFIG);
//populate and write XML tree
- if ( !outputFile.writeXmlBatchConfig(inputCfg) || //add GUI layout configuration settings
+ if ( !outputFile.writeXmlBatchConfig(outputCfg) || //add GUI layout configuration settings
!outputFile.writeToFile()) //save XML
- throw FileError(wxString(_("Error writing file:")) + wxT(" \"") + filename + wxT("\""));
+ throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + filename.c_str() + wxT("\""));
return;
}
-void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& inputCfg)
+void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& outputCfg)
{
XmlConfigOutput outputFile(FreeFileSync::GLOBAL_CONFIG_FILE, XML_GLOBAL_SETTINGS);
//populate and write XML tree
- if ( !outputFile.writeXmlGlobalSettings(inputCfg) || //add GUI layout configuration settings
+ if ( !outputFile.writeXmlGlobalSettings(outputCfg) || //add GUI layout configuration settings
!outputFile.writeToFile()) //save XML
- throw FileError(wxString(_("Error writing file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\""));
+ throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE.c_str() + wxT("\""));
return;
}
@@ -212,17 +212,17 @@ XmlConfigInput::XmlConfigInput(const wxString& fileName, const XmlType type) :
{
TiXmlElement* root = doc.RootElement();
- if (root && (root->ValueStr() == string("FreeFileSync"))) //check for FFS configuration xml
+ if (root && (root->ValueStr() == std::string("FreeFileSync"))) //check for FFS configuration xml
{
const char* cfgType = root->Attribute("XmlType");
if (cfgType)
{
if (type == XML_GUI_CONFIG)
- loadSuccess = string(cfgType) == "GUI";
+ loadSuccess = std::string(cfgType) == "GUI";
else if (type == XML_BATCH_CONFIG)
- loadSuccess = string(cfgType) == "BATCH";
+ loadSuccess = std::string(cfgType) == "BATCH";
else if (type == XML_GLOBAL_SETTINGS)
- loadSuccess = string(cfgType) == "GLOBAL";
+ loadSuccess = std::string(cfgType) == "GLOBAL";
}
}
}
@@ -230,7 +230,7 @@ XmlConfigInput::XmlConfigInput(const wxString& fileName, const XmlType type) :
}
-bool readXmlElementValue(string& output, const TiXmlElement* parent, const string& name)
+bool readXmlElementValue(std::string& output, const TiXmlElement* parent, const std::string& name)
{
if (parent)
{
@@ -250,9 +250,9 @@ bool readXmlElementValue(string& output, const TiXmlElement* parent, const strin
}
-bool readXmlElementValue(int& output, const TiXmlElement* parent, const string& name)
+bool readXmlElementValue(int& output, const TiXmlElement* parent, const std::string& name)
{
- string temp;
+ std::string temp;
if (readXmlElementValue(temp, parent, name))
{
output = stringToInt(temp);
@@ -263,7 +263,7 @@ bool readXmlElementValue(int& output, const TiXmlElement* parent, const string&
}
-bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const string& name)
+bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const std::string& name)
{
int dummy = 0;
if (readXmlElementValue(dummy, parent, name))
@@ -276,9 +276,9 @@ bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, con
}
-bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const string& name)
+bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const std::string& name)
{
- string dummy;
+ std::string dummy;
if (readXmlElementValue(dummy, parent, name))
{
if (dummy == "left")
@@ -295,9 +295,9 @@ bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElemen
}
-bool readXmlElementValue(bool& output, const TiXmlElement* parent, const string& name)
+bool readXmlElementValue(bool& output, const TiXmlElement* parent, const std::string& name)
{
- string dummy;
+ std::string dummy;
if (readXmlElementValue(dummy, parent, name))
{
output = (dummy == "true");
@@ -308,7 +308,7 @@ bool readXmlElementValue(bool& output, const TiXmlElement* parent, const string&
}
-bool XmlConfigInput::readXmlMainConfig(MainConfiguration& mainCfg, vector<FolderPair>& directoryPairs)
+bool XmlConfigInput::readXmlMainConfig(MainConfiguration& mainCfg, std::vector<FolderPair>& directoryPairs)
{
TiXmlElement* root = doc.RootElement();
if (!root) return false;
@@ -323,7 +323,7 @@ bool XmlConfigInput::readXmlMainConfig(MainConfiguration& mainCfg, vector<Folder
if (!cmpSettings || !syncConfig || !miscSettings || !filter)
return false;
- string tempString;
+ std::string tempString;
//###########################################################
//read compare variant
if (!readXmlElementValue(mainCfg.compareVar, cmpSettings, "Variant")) return false;
@@ -435,7 +435,7 @@ bool XmlConfigInput::readXmlGlobalSettings(XmlGlobalSettings& outputCfg)
#ifdef FFS_WIN
//daylight saving time check
- readXmlElementValue(outputCfg.global.dstCheckActive, global, "DaylightSavingTimeCheckActive");
+ readXmlElementValue(outputCfg.global.handleDstOnFat32, global, "HandleDaylightSavingTimeOnFAT");
#endif
//folder dependency check
@@ -453,50 +453,78 @@ bool XmlConfigInput::readXmlGlobalSettings(XmlGlobalSettings& outputCfg)
readXmlElementValue(outputCfg.gui.isMaximized, mainWindow, "Maximized");
//###########################################################
- //read column widths
- TiXmlElement* leftColumn = TiXmlHandle(mainWindow).FirstChild("LeftColumns").FirstChild("Width").ToElement();
+ //read column attributes
+ TiXmlElement* leftColumn = TiXmlHandle(mainWindow).FirstChild("LeftColumns").FirstChild("Column").ToElement();
+ unsigned int colType = 0;
while (leftColumn)
{
- const char* width = leftColumn->GetText();
- if (width) //may be NULL!!
- outputCfg.gui.columnWidthLeft.push_back(stringToInt(width));
+ const char* visible = leftColumn->Attribute("Visible");
+ const char* position = leftColumn->Attribute("Position");
+ const char* width = leftColumn->Attribute("Width");
+
+ if (visible && position && width) //may be NULL!!
+ {
+ XmlGlobalSettings::ColumnAttrib newAttrib;
+ newAttrib.type = XmlGlobalSettings::ColumnTypes(colType);
+ newAttrib.visible = std::string(visible) != std::string("false");
+ newAttrib.position = stringToInt(position);
+ newAttrib.width = stringToInt(width);
+ outputCfg.gui.columnAttribLeft.push_back(newAttrib);
+ }
else
break;
+
leftColumn = leftColumn->NextSiblingElement();
+ ++colType;
}
- TiXmlElement* rightColumn = TiXmlHandle(mainWindow).FirstChild("RightColumns").FirstChild("Width").ToElement();
+ TiXmlElement* rightColumn = TiXmlHandle(mainWindow).FirstChild("RightColumns").FirstChild("Column").ToElement();
+ colType = 0;
while (rightColumn)
{
- const char* width = rightColumn->GetText();
- if (width) //may be NULL!!
- outputCfg.gui.columnWidthRight.push_back(stringToInt(width));
+ const char* visible = rightColumn->Attribute("Visible");
+ const char* position = rightColumn->Attribute("Position");
+ const char* width = rightColumn->Attribute("Width");
+
+ if (visible && position && width) //may be NULL!!
+ {
+ XmlGlobalSettings::ColumnAttrib newAttrib;
+ newAttrib.type = XmlGlobalSettings::ColumnTypes(colType);
+ newAttrib.visible = std::string(visible) != std::string("false");
+ newAttrib.position = stringToInt(position);
+ newAttrib.width = stringToInt(width);
+ outputCfg.gui.columnAttribRight.push_back(newAttrib);
+ }
else
break;
+
rightColumn = rightColumn->NextSiblingElement();
+ ++colType;
}
+ }
- //read column positions
- TiXmlElement* leftColumnPos = TiXmlHandle(mainWindow).FirstChild("LeftColumnPositions").FirstChild("Position").ToElement();
- while (leftColumnPos)
- {
- const char* width = leftColumnPos->GetText();
- if (width) //may be NULL!!
- outputCfg.gui.columnPositionsLeft.push_back(stringToInt(width));
- else
- break;
- leftColumnPos = leftColumnPos->NextSiblingElement();
- }
+ TiXmlElement* gui = hRoot.FirstChild("Gui").ToElement();
+ if (gui)
+ {
+ //commandline for file manager integration
+ std::string tempString;
+ if (readXmlElementValue(tempString, gui, "FileManager"))
+ outputCfg.gui.commandLineFileManager = wxString::FromUTF8(tempString.c_str());
+ }
- TiXmlElement* rightColumnPos = TiXmlHandle(mainWindow).FirstChild("RightColumnPositions").FirstChild("Position").ToElement();
- while (rightColumnPos)
+ //load config file history
+ TiXmlElement* cfgHistory = hRoot.FirstChild("Gui").FirstChild("History").ToElement();
+ if (cfgHistory)
+ {
+ TiXmlElement* cfgFile = TiXmlHandle(cfgHistory).FirstChild("File").ToElement();
+ while (cfgFile)
{
- const char* width = rightColumnPos->GetText();
- if (width) //may be NULL!!
- outputCfg.gui.columnPositionsRight.push_back(stringToInt(width));
+ const char* fileName = cfgFile->GetText();
+ if (fileName) //may be NULL!!
+ outputCfg.gui.cfgFileHistory.push_back(wxString::FromUTF8(fileName));
else
break;
- rightColumnPos = rightColumnPos->NextSiblingElement();
+ cfgFile = cfgFile->NextSiblingElement();
}
}
@@ -546,7 +574,7 @@ bool XmlConfigOutput::writeToFile()
}
-void addXmlElement(TiXmlElement* parent, const string& name, const string& value)
+void addXmlElement(TiXmlElement* parent, const std::string& name, const std::string& value)
{
if (parent)
{
@@ -557,35 +585,35 @@ void addXmlElement(TiXmlElement* parent, const string& name, const string& value
}
-void addXmlElement(TiXmlElement* parent, const string& name, const int value)
+void addXmlElement(TiXmlElement* parent, const std::string& name, const int value)
{
addXmlElement(parent, name, numberToString(value));
}
-void addXmlElement(TiXmlElement* parent, const string& name, const SyncConfiguration::Direction value)
+void addXmlElement(TiXmlElement* parent, const std::string& name, const SyncConfiguration::Direction value)
{
if (value == SyncConfiguration::SYNC_DIR_LEFT)
- addXmlElement(parent, name, string("left"));
+ addXmlElement(parent, name, std::string("left"));
else if (value == SyncConfiguration::SYNC_DIR_RIGHT)
- addXmlElement(parent, name, string("right"));
+ addXmlElement(parent, name, std::string("right"));
else if (value == SyncConfiguration::SYNC_DIR_NONE)
- addXmlElement(parent, name, string("none"));
+ addXmlElement(parent, name, std::string("none"));
else
assert(false);
}
-void addXmlElement(TiXmlElement* parent, const string& name, const bool value)
+void addXmlElement(TiXmlElement* parent, const std::string& name, const bool value)
{
if (value)
- addXmlElement(parent, name, string("true"));
+ addXmlElement(parent, name, std::string("true"));
else
- addXmlElement(parent, name, string("false"));
+ addXmlElement(parent, name, std::string("false"));
}
-bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const vector<FolderPair>& directoryPairs)
+bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const std::vector<FolderPair>& directoryPairs)
{
TiXmlElement* root = doc.RootElement();
if (!root) return false;
@@ -605,13 +633,13 @@ bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const
cmpSettings->LinkEndChild(folders);
//write folder pairs
- for (vector<FolderPair>::const_iterator i = directoryPairs.begin(); i != directoryPairs.end(); ++i)
+ for (std::vector<FolderPair>::const_iterator i = directoryPairs.begin(); i != directoryPairs.end(); ++i)
{
TiXmlElement* folderPair = new TiXmlElement("Pair");
folders->LinkEndChild(folderPair);
- addXmlElement(folderPair, "Left", string(wxString(i->leftDirectory.c_str()).ToUTF8()));
- addXmlElement(folderPair, "Right", string(wxString(i->rightDirectory.c_str()).ToUTF8()));
+ addXmlElement(folderPair, "Left", std::string(wxString(i->leftDirectory.c_str()).ToUTF8()));
+ addXmlElement(folderPair, "Right", std::string(wxString(i->rightDirectory.c_str()).ToUTF8()));
}
//###########################################################
@@ -637,8 +665,8 @@ bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const
miscSettings->LinkEndChild(filter);
addXmlElement(filter, "Active", mainCfg.filterIsActive);
- addXmlElement(filter, "Include", string((mainCfg.includeFilter).ToUTF8()));
- addXmlElement(filter, "Exclude", string((mainCfg.excludeFilter).ToUTF8()));
+ addXmlElement(filter, "Include", std::string((mainCfg.includeFilter).ToUTF8()));
+ addXmlElement(filter, "Exclude", std::string((mainCfg.excludeFilter).ToUTF8()));
//other
addXmlElement(miscSettings, "UseRecycler", mainCfg.useRecycleBin);
@@ -649,10 +677,10 @@ bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const
}
-bool XmlConfigOutput::writeXmlGuiConfig(const XmlGuiConfig& inputCfg)
+bool XmlConfigOutput::writeXmlGuiConfig(const XmlGuiConfig& outputCfg)
{
//write main config
- if (!writeXmlMainConfig(inputCfg.mainCfg, inputCfg.directoryPairs))
+ if (!writeXmlMainConfig(outputCfg.mainCfg, outputCfg.directoryPairs))
return false;
//write GUI specific config
@@ -668,16 +696,16 @@ bool XmlConfigOutput::writeXmlGuiConfig(const XmlGuiConfig& inputCfg)
TiXmlElement* mainWindow = new TiXmlElement("Main");
windows->LinkEndChild(mainWindow);
- addXmlElement(mainWindow, "HideFiltered", inputCfg.hideFilteredElements);
+ addXmlElement(mainWindow, "HideFiltered", outputCfg.hideFilteredElements);
return true;
}
-bool XmlConfigOutput::writeXmlBatchConfig(const XmlBatchConfig& inputCfg)
+bool XmlConfigOutput::writeXmlBatchConfig(const XmlBatchConfig& outputCfg)
{
//write main config
- if (!writeXmlMainConfig(inputCfg.mainCfg, inputCfg.directoryPairs))
+ if (!writeXmlMainConfig(outputCfg.mainCfg, outputCfg.directoryPairs))
return false;
//write GUI specific config
@@ -687,13 +715,13 @@ bool XmlConfigOutput::writeXmlBatchConfig(const XmlBatchConfig& inputCfg)
TiXmlElement* batchConfig = new TiXmlElement("BatchConfig");
root->LinkEndChild(batchConfig);
- addXmlElement(batchConfig, "Silent", inputCfg.silent);
+ addXmlElement(batchConfig, "Silent", outputCfg.silent);
return true;
}
-bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg)
+bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& outputCfg)
{
TiXmlElement* root = doc.RootElement();
if (!root) return false;
@@ -704,64 +732,83 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg)
root->LinkEndChild(global);
//program language
- addXmlElement(global, "Language", inputCfg.global.programLanguage);
+ addXmlElement(global, "Language", outputCfg.global.programLanguage);
#ifdef FFS_WIN
//daylight saving time check
- addXmlElement(global, "DaylightSavingTimeCheckActive", inputCfg.global.dstCheckActive);
+ addXmlElement(global, "HandleDaylightSavingTimeOnFAT", outputCfg.global.handleDstOnFat32);
#endif
//folder dependency check
- addXmlElement(global, "FolderDependencyCheckActive", inputCfg.global.folderDependCheckActive);
+ addXmlElement(global, "FolderDependencyCheckActive", outputCfg.global.folderDependCheckActive);
+
//###################################################################
- //write gui settings
- TiXmlElement* guiLayout = new TiXmlElement("Gui");
- root->LinkEndChild(guiLayout);
+ //write global gui settings
+ TiXmlElement* gui = new TiXmlElement("Gui");
+ root->LinkEndChild(gui);
TiXmlElement* windows = new TiXmlElement("Windows");
- guiLayout->LinkEndChild(windows);
+ gui->LinkEndChild(windows);
TiXmlElement* mainWindow = new TiXmlElement("Main");
windows->LinkEndChild(mainWindow);
//window size
- addXmlElement(mainWindow, "Width", inputCfg.gui.widthNotMaximized);
- addXmlElement(mainWindow, "Height", inputCfg.gui.heightNotMaximized);
+ addXmlElement(mainWindow, "Width", outputCfg.gui.widthNotMaximized);
+ addXmlElement(mainWindow, "Height", outputCfg.gui.heightNotMaximized);
//window position
- addXmlElement(mainWindow, "PosX", inputCfg.gui.posXNotMaximized);
- addXmlElement(mainWindow, "PosY", inputCfg.gui.posYNotMaximized);
- addXmlElement(mainWindow, "Maximized", inputCfg.gui.isMaximized);
+ addXmlElement(mainWindow, "PosX", outputCfg.gui.posXNotMaximized);
+ addXmlElement(mainWindow, "PosY", outputCfg.gui.posYNotMaximized);
+ addXmlElement(mainWindow, "Maximized", outputCfg.gui.isMaximized);
- //write column sizes
+ //write column attributes
TiXmlElement* leftColumn = new TiXmlElement("LeftColumns");
mainWindow->LinkEndChild(leftColumn);
-
- for (unsigned int i = 0; i < inputCfg.gui.columnWidthLeft.size(); ++i)
- addXmlElement(leftColumn, "Width", inputCfg.gui.columnWidthLeft[i]);
+ XmlGlobalSettings::ColumnAttributes columnAtrribLeftCopy = outputCfg.gui.columnAttribLeft; //can't change const vector
+ sort(columnAtrribLeftCopy.begin(), columnAtrribLeftCopy.end(), xmlAccess::sortByType);
+ for (unsigned int i = 0; i < columnAtrribLeftCopy.size(); ++i)
+ {
+ TiXmlElement* subElement = new TiXmlElement("Column");
+ leftColumn->LinkEndChild(subElement);
+
+ const XmlGlobalSettings::ColumnAttrib& colAttrib = columnAtrribLeftCopy[i];
+ 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);
+ XmlGlobalSettings::ColumnAttributes columnAtrribRightCopy = outputCfg.gui.columnAttribRight;
+ sort(columnAtrribRightCopy.begin(), columnAtrribRightCopy.end(), xmlAccess::sortByType);
+ for (unsigned int i = 0; i < columnAtrribRightCopy.size(); ++i)
+ {
+ TiXmlElement* subElement = new TiXmlElement("Column");
+ rightColumn->LinkEndChild(subElement);
+
+ const XmlGlobalSettings::ColumnAttrib& colAttrib = columnAtrribRightCopy[i];
+ if (colAttrib.visible) subElement->SetAttribute("Visible", "true");
+ else subElement->SetAttribute("Visible", "false");
+ subElement->SetAttribute("Position", colAttrib.position);
+ subElement->SetAttribute("Width", colAttrib.width);
+ }
- for (unsigned int i = 0; i < inputCfg.gui.columnWidthRight.size(); ++i)
- addXmlElement(rightColumn, "Width", inputCfg.gui.columnWidthRight[i]);
-
- //write column positions
- TiXmlElement* leftColumnPos = new TiXmlElement("LeftColumnPositions");
- mainWindow->LinkEndChild(leftColumnPos);
+ //commandline for file manager integration
+ addXmlElement(gui, "FileManager", std::string((outputCfg.gui.commandLineFileManager).ToUTF8()));
- for (unsigned int i = 0; i < inputCfg.gui.columnPositionsLeft.size(); ++i)
- addXmlElement(leftColumnPos, "Position", inputCfg.gui.columnPositionsLeft[i]);
+ //write config file history
+ TiXmlElement* cfgHistory = new TiXmlElement("History");
+ gui->LinkEndChild(cfgHistory);
- TiXmlElement* rightColumnPos = new TiXmlElement("RightColumnPositions");
- mainWindow->LinkEndChild(rightColumnPos);
+ for (unsigned int i = 0; i < outputCfg.gui.cfgFileHistory.size(); ++i)
+ addXmlElement(cfgHistory, "File", std::string(outputCfg.gui.cfgFileHistory[i].ToUTF8()));
- for (unsigned int i = 0; i < inputCfg.gui.columnPositionsRight.size(); ++i)
- addXmlElement(rightColumnPos, "Position", inputCfg.gui.columnPositionsRight[i]);
//###################################################################
- //write batch settings
+ //write global batch settings
TiXmlElement* batch = new TiXmlElement("Batch");
root->LinkEndChild(batch);
@@ -770,12 +817,13 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg)
}
-int xmlAccess::retrieveSystemLanguage() //map language dialects
+int xmlAccess::retrieveSystemLanguage()
{
const int lang = wxLocale::GetSystemLanguage();
- switch (lang)
+ switch (lang) //map language dialects
{
+ //variants of wxLANGUAGE_GERMAN
case wxLANGUAGE_GERMAN_AUSTRIAN:
case wxLANGUAGE_GERMAN_BELGIUM:
case wxLANGUAGE_GERMAN_LIECHTENSTEIN:
@@ -783,6 +831,7 @@ int xmlAccess::retrieveSystemLanguage() //map language dialects
case wxLANGUAGE_GERMAN_SWISS:
return wxLANGUAGE_GERMAN;
+ //variants of wxLANGUAGE_FRENCH
case wxLANGUAGE_FRENCH_BELGIAN:
case wxLANGUAGE_FRENCH_CANADIAN:
case wxLANGUAGE_FRENCH_LUXEMBOURG:
@@ -790,11 +839,15 @@ int xmlAccess::retrieveSystemLanguage() //map language dialects
case wxLANGUAGE_FRENCH_SWISS:
return wxLANGUAGE_FRENCH;
- //case wxLANGUAGE_JAPANESE:
-
+ //variants of wxLANGUAGE_DUTCH
case wxLANGUAGE_DUTCH_BELGIAN:
return wxLANGUAGE_DUTCH;
+ //variants of wxLANGUAGE_ITALIAN
+ case wxLANGUAGE_ITALIAN_SWISS:
+ return wxLANGUAGE_ITALIAN;
+
+ //variants of wxLANGUAGE_CHINESE_SIMPLIFIED
case wxLANGUAGE_CHINESE:
case wxLANGUAGE_CHINESE_TRADITIONAL:
case wxLANGUAGE_CHINESE_HONGKONG:
@@ -803,7 +856,16 @@ int xmlAccess::retrieveSystemLanguage() //map language dialects
case wxLANGUAGE_CHINESE_TAIWAN:
return wxLANGUAGE_CHINESE_SIMPLIFIED;
+ //variants of wxLANGUAGE_PORTUGUESE
+ case wxLANGUAGE_PORTUGUESE_BRAZILIAN:
+ return wxLANGUAGE_PORTUGUESE;
+
+ //case wxLANGUAGE_JAPANESE:
+ //case wxLANGUAGE_POLISH:
+
+
default:
+ //all the rest: wxLANGUAGE_ENGLISH;
return lang;
}
}
diff --git a/library/processXml.h b/library/processXml.h
index bc81556e..5f3f8ef9 100644
--- a/library/processXml.h
+++ b/library/processXml.h
@@ -25,7 +25,7 @@ namespace xmlAccess
XmlGuiConfig() : hideFilteredElements(false) {} //initialize values
MainConfiguration mainCfg;
- vector<FolderPair> directoryPairs;
+ std::vector<FolderPair> directoryPairs;
bool hideFilteredElements;
};
@@ -36,31 +36,53 @@ namespace xmlAccess
XmlBatchConfig() : silent(false) {}
MainConfiguration mainCfg;
- vector<FolderPair> directoryPairs;
+ std::vector<FolderPair> directoryPairs;
bool silent;
};
int retrieveSystemLanguage();
+
struct XmlGlobalSettings
{
+//---------------------------------------------------------------------
+//internal structures:
+ enum ColumnTypes
+ {
+ FILENAME = 0,
+ REL_PATH,
+ SIZE,
+ DATE
+ };
+
+ struct ColumnAttrib
+ {
+ ColumnTypes type;
+ bool visible;
+ unsigned position;
+ int width;
+ };
+ typedef std::vector<ColumnAttrib> ColumnAttributes;
+
+//---------------------------------------------------------------------
struct _Global
{
_Global() :
programLanguage(retrieveSystemLanguage()),
#ifdef FFS_WIN
- dstCheckActive(true),
+ handleDstOnFat32(true),
#endif
folderDependCheckActive(true) {}
int programLanguage;
#ifdef FFS_WIN
- bool dstCheckActive;
+ bool handleDstOnFat32;
#endif
bool folderDependCheckActive;
} global;
+//---------------------------------------------------------------------
struct _Gui
{
_Gui() :
@@ -68,30 +90,63 @@ namespace xmlAccess
heightNotMaximized(wxDefaultCoord),
posXNotMaximized(wxDefaultCoord),
posYNotMaximized(wxDefaultCoord),
- isMaximized(false) {}
+ isMaximized(false),
+#ifdef FFS_WIN
+ commandLineFileManager(wxT("explorer /select, %x"))
+#elif defined FFS_LINUX
+ commandLineFileManager(wxT("konqueror \"%path\""))
+#endif
+ {}
int widthNotMaximized;
int heightNotMaximized;
int posXNotMaximized;
int posYNotMaximized;
bool isMaximized;
- vector<int> columnWidthLeft;
- vector<int> columnWidthRight;
- vector<int> columnPositionsLeft;
- vector<int> columnPositionsRight;
+
+ ColumnAttributes columnAttribLeft;
+ ColumnAttributes columnAttribRight;
+ std::vector<wxString> cfgFileHistory;
+ wxString commandLineFileManager;
} gui;
+//---------------------------------------------------------------------
//struct _Batch
};
+ inline
+ bool sortByType(const XmlGlobalSettings::ColumnAttrib& a, const XmlGlobalSettings::ColumnAttrib& b)
+ {
+ return a.type < b.type;
+ }
+
+
+ inline
+ bool sortByPositionOnly(const XmlGlobalSettings::ColumnAttrib& a, const XmlGlobalSettings::ColumnAttrib& b)
+ {
+ return a.position < b.position;
+ }
+
+
+ inline
+ bool sortByPositionAndVisibility(const XmlGlobalSettings::ColumnAttrib& a, const XmlGlobalSettings::ColumnAttrib& b)
+ {
+ if (a.visible == false) //hidden elements shall appear at end of vector
+ return false;
+ if (b.visible == false)
+ return true;
+ return a.position < b.position;
+ }
+
+
XmlGuiConfig readGuiConfig(const wxString& filename);
XmlBatchConfig readBatchConfig(const wxString& filename);
XmlGlobalSettings readGlobalSettings(); //used for both GUI and batch mode, independent from configuration instance
- void writeGuiConfig(const wxString& filename, const XmlGuiConfig& inputCfg);
- void writeBatchConfig(const wxString& filename, const XmlBatchConfig& inputCfg);
- void writeGlobalSettings(const XmlGlobalSettings& inputCfg);
+ void writeGuiConfig(const wxString& filename, const XmlGuiConfig& outputCfg);
+ void writeBatchConfig(const wxString& filename, const XmlBatchConfig& outputCfg);
+ void writeGlobalSettings(const XmlGlobalSettings& outputCfg);
}
diff --git a/library/resources.cpp b/library/resources.cpp
index 9169bf85..c60c259c 100644
--- a/library/resources.cpp
+++ b/library/resources.cpp
@@ -92,6 +92,12 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("filter.png")] = (bitmapFilter = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("batch.png")] = (bitmapBatch = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("batch_small.png")] = (bitmapBatchSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("move up.png")] = (bitmapMoveUp = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("move down.png")] = (bitmapMoveDown = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("checkbox true.png")] = (bitmapCheckBoxTrue = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("checkbox false.png")] = (bitmapCheckBoxFalse = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("settings.png")] = (bitmapSettings = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("settings_small.png")] = (bitmapSettingsSmall = new wxBitmap(wxNullBitmap));
//init all the other resource files
animationMoney = new wxAnimation(wxNullAnimation);
@@ -102,7 +108,7 @@ GlobalResources::GlobalResources()
GlobalResources::~GlobalResources()
{
//free bitmap resources
- for (map<wxString, wxBitmap*>::iterator i = bitmapResource.begin(); i != bitmapResource.end(); ++i)
+ for (std::map<wxString, wxBitmap*>::iterator i = bitmapResource.begin(); i != bitmapResource.end(); ++i)
delete i->second;
//free other resources
@@ -117,7 +123,7 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation* animation)
//Workaround for wxWidgets:
//construct seekable input stream (zip-input stream is non-seekable) for wxAnimation::Load()
//luckily this method call is very fast: below measurement precision!
- vector<unsigned char> data;
+ std::vector<unsigned char> data;
data.reserve(10000);
int newValue = 0;
@@ -141,7 +147,7 @@ void GlobalResources::load()
wxZipInputStream resourceFile(input);
wxZipEntry* entry = NULL;
- map<wxString, wxBitmap*>::iterator bmp;
+ std::map<wxString, wxBitmap*>::iterator bmp;
while ((entry = resourceFile.GetNextEntry()))
{
wxString name = entry->GetName();
diff --git a/library/resources.h b/library/resources.h
index d08ce0ce..4eec185e 100644
--- a/library/resources.h
+++ b/library/resources.h
@@ -6,7 +6,6 @@
#include <wx/string.h>
#include <map>
-using namespace std;
class GlobalResources
{
@@ -92,6 +91,12 @@ public:
wxBitmap* bitmapFilter;
wxBitmap* bitmapBatch;
wxBitmap* bitmapBatchSmall;
+ wxBitmap* bitmapMoveUp;
+ wxBitmap* bitmapMoveDown;
+ wxBitmap* bitmapCheckBoxTrue;
+ wxBitmap* bitmapCheckBoxFalse;
+ wxBitmap* bitmapSettings;
+ wxBitmap* bitmapSettingsSmall;
wxAnimation* animationMoney;
wxAnimation* animationSync;
@@ -100,7 +105,7 @@ public:
private:
//resource mapping
- map<wxString, wxBitmap*> bitmapResource;
+ std::map<wxString, wxBitmap*> bitmapResource;
};
diff --git a/library/sorting.h b/library/sorting.h
index 560e246a..fabdad1f 100644
--- a/library/sorting.h
+++ b/library/sorting.h
@@ -5,6 +5,7 @@
#include "resources.h"
#include "globalFunctions.h"
+using namespace FreeFileSync;
enum SideToSort
{
@@ -115,11 +116,11 @@ bool sortByFileName(const FileCompareLine& a, const FileCompareLine& b)
const wxChar* stringB = descrLineB->relativeName.c_str();
size_t pos = descrLineA->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end
- if (pos != string::npos)
+ if (pos != std::string::npos)
stringA += pos + 1;
pos = descrLineB->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end
- if (pos != string::npos)
+ if (pos != std::string::npos)
stringB += pos + 1;
return stringSmallerThan<sortAscending>(stringA, stringB);
@@ -250,4 +251,20 @@ bool sortByDate(const FileCompareLine& a, const FileCompareLine& b)
}
+template <bool sortAscending>
+inline
+bool sortByCmpResult(const FileCompareLine& a, const FileCompareLine& b)
+{
+ //presort result: equal shall appear at end of list
+ if (a.cmpResult == FILE_EQUAL)
+ return false;
+ if (b.cmpResult == FILE_EQUAL)
+ return true;
+
+ return sortAscending ?
+ a.cmpResult < b.cmpResult :
+ a.cmpResult > b.cmpResult;
+}
+
+
#endif // SORTING_H_INCLUDED
diff --git a/library/statusHandler.h b/library/statusHandler.h
index 4c12035d..bae1de8e 100644
--- a/library/statusHandler.h
+++ b/library/statusHandler.h
@@ -1,7 +1,7 @@
#ifndef STATUSHANDLER_H_INCLUDED
#define STATUSHANDLER_H_INCLUDED
-#include <wx/string.h>
+#include "zstring.h"
const int UI_UPDATE_INTERVAL = 100; //perform ui updates not more often than necessary, 100 seems to be a good value with only a minimal performance loss
@@ -24,7 +24,7 @@ public:
IGNORE_ERROR = 10,
RETRY
};
- virtual Response reportError(const wxString& text) = 0;
+ virtual Response reportError(const Zstring& text) = 0;
};
@@ -45,10 +45,10 @@ public:
};
//these methods have to be implemented in the derived classes to handle error and status information
- virtual void updateStatusText(const wxString& text) = 0;
+ virtual void updateStatusText(const Zstring& text) = 0;
virtual void initNewProcess(int objectsTotal, double dataTotal, Process processID) = 0; //informs about the total amount of data that will be processed from now on
virtual void updateProcessedData(int objectsProcessed, double dataProcessed) = 0; //called periodically after data was processed
- virtual ErrorHandler::Response reportError(const wxString& text) = 0;
+ virtual ErrorHandler::Response reportError(const Zstring& text) = 0;
//this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events
virtual void forceUiRefresh() = 0;
diff --git a/library/zstring.cpp b/library/zstring.cpp
index b84c9512..35704b01 100644
--- a/library/zstring.cpp
+++ b/library/zstring.cpp
@@ -44,14 +44,14 @@ int FreeFileSync::compareStringsWin32(const wchar_t* a, const wchar_t* b, const
bCount); //size, in bytes or characters, of second string
if (rv == 0)
- throw RuntimeException(wxString(_("Error comparing strings!")));
+ throw RuntimeException(wxString(wxT("Error comparing strings!")));
else
return rv - 2;
}
#endif
-size_t Zstring::Replace(const defaultChar* old, const defaultChar* replacement, bool replaceAll)
+size_t Zstring::Replace(const DefaultChar* old, const DefaultChar* replacement, bool replaceAll)
{
const size_t oldLen = defaultLength(old);
const size_t replacementLen = defaultLength(replacement);
@@ -77,29 +77,29 @@ size_t Zstring::Replace(const defaultChar* old, const defaultChar* replacement,
}
-bool matchesHelper(const defaultChar* string, const defaultChar* mask)
+bool matchesHelper(const DefaultChar* string, const DefaultChar* mask)
{
- for (defaultChar ch; (ch = *mask) != 0; ++mask)
+ for (DefaultChar ch; (ch = *mask) != 0; ++mask)
{
switch (ch)
{
- case defaultChar('?'):
+ case DefaultChar('?'):
if (*string == 0)
return false;
else
++string;
break;
- case defaultChar('*'):
+ case DefaultChar('*'):
//advance to next non-*/? char
do
{
++mask;
ch = *mask;
}
- while (ch == defaultChar('*') || ch == defaultChar('?'));
+ while (ch == DefaultChar('*') || ch == DefaultChar('?'));
//if match ends with '*':
- if (ch == defaultChar(0))
+ if (ch == DefaultChar(0))
return true;
++mask;
@@ -123,7 +123,7 @@ bool matchesHelper(const defaultChar* string, const defaultChar* mask)
}
-bool Zstring::Matches(const defaultChar* mask) const
+bool Zstring::Matches(const DefaultChar* mask) const
{
return matchesHelper(c_str(), mask);
}
@@ -137,7 +137,7 @@ Zstring& Zstring::Trim(bool fromRight)
if (fromRight)
{
- const defaultChar* cursor = data + thisLen - 1;
+ const DefaultChar* cursor = data + thisLen - 1;
while (cursor != data - 1 && defaultIsWhiteSpace(*cursor)) //break when pointing one char further than last skipped element
--cursor;
++cursor;
@@ -153,8 +153,8 @@ Zstring& Zstring::Trim(bool fromRight)
}
else
{
- defaultChar* cursor = data;
- defaultChar ch;
+ DefaultChar* cursor = data;
+ DefaultChar ch;
while ((ch = *cursor) != 0 && defaultIsWhiteSpace(ch))
++cursor;
@@ -185,7 +185,7 @@ Zstring& Zstring::MakeLower()
if (descr->refCount > 1) //allocate new string
{
StringDescriptor* newDescr;
- defaultChar* newData;
+ DefaultChar* newData;
const size_t newCapacity = getCapacityToAllocate(thisLen);
allocate(1, thisLen, newCapacity, newDescr, newData);
@@ -224,7 +224,7 @@ Zstring Zstring::substr(size_t pos, size_t len) const
}
-size_t Zstring::rfind(const defaultChar ch, size_t pos) const
+size_t Zstring::rfind(const DefaultChar ch, size_t pos) const
{
const size_t thisLen = length();
if (thisLen == 0)
@@ -245,7 +245,7 @@ size_t Zstring::rfind(const defaultChar ch, size_t pos) const
}
-Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t n2)
+Zstring& Zstring::replace(size_t pos1, size_t n1, const DefaultChar* str, size_t n2)
{
assert(str < c_str() || c_str() + length() < str); //str mustn't point to data in this string
assert(n1 <= length() - pos1);
@@ -265,15 +265,15 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t
const size_t newCapacity = getCapacityToAllocate(newLen);
StringDescriptor* newDescr;
- defaultChar* newData;
+ DefaultChar* newData;
allocate(1, newLen, newCapacity, newDescr, newData);
//StringDescriptor* newDescr = new StringDescriptor(1, newLen, newCapacity);
- //defaultChar* newData = new defaultChar[newCapacity + 1];
+ //DefaultChar* newData = new DefaultChar[newCapacity + 1];
//assemble new string with replacement
- memcpy(newData, data, pos1 * sizeof(defaultChar));
- memcpy(newData + pos1, str, n2 * sizeof(defaultChar));
- memcpy(newData + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(defaultChar));
+ memcpy(newData, data, pos1 * sizeof(DefaultChar));
+ memcpy(newData + pos1, str, n2 * sizeof(DefaultChar));
+ memcpy(newData + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(DefaultChar));
newData[newLen] = 0;
decRef();
@@ -282,10 +282,10 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t
}
else
{ //overwrite current string
- memcpy(data + pos1, str, n2 * sizeof(defaultChar));
+ memcpy(data + pos1, str, n2 * sizeof(DefaultChar));
if (n1 > n2)
{
- memmove(data + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(defaultChar));
+ memmove(data + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(DefaultChar));
data[newLen] = 0;
descr->length = newLen;
}
@@ -295,7 +295,7 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t
}
-Zstring& Zstring::operator=(const defaultChar* source)
+Zstring& Zstring::operator=(const DefaultChar* source)
{
const size_t sourceLen = defaultLength(source);
if (sourceLen == 0)
@@ -305,7 +305,7 @@ Zstring& Zstring::operator=(const defaultChar* source)
*this = Zstring(source, sourceLen);
else
{ //overwrite this string
- memcpy(data, source, sourceLen * sizeof(defaultChar));
+ memcpy(data, source, sourceLen * sizeof(DefaultChar));
data[sourceLen] = 0;
descr->length = sourceLen;
}
@@ -322,7 +322,7 @@ Zstring& Zstring::operator+=(const Zstring& other)
const size_t newLen = thisLen + otherLen;
copyBeforeWrite(newLen);
- memcpy(data + thisLen, other.c_str(), otherLen * sizeof(defaultChar));
+ memcpy(data + thisLen, other.c_str(), otherLen * sizeof(DefaultChar));
data[newLen] = 0;
descr->length = newLen;
}
@@ -330,7 +330,7 @@ Zstring& Zstring::operator+=(const Zstring& other)
}
-Zstring& Zstring::operator+=(const defaultChar* other)
+Zstring& Zstring::operator+=(const DefaultChar* other)
{
const size_t otherLen = defaultLength(other);
if (otherLen != 0)
@@ -339,7 +339,7 @@ Zstring& Zstring::operator+=(const defaultChar* other)
const size_t newLen = thisLen + otherLen;
copyBeforeWrite(newLen);
- memcpy(data + thisLen, other, otherLen * sizeof(defaultChar));
+ memcpy(data + thisLen, other, otherLen * sizeof(DefaultChar));
data[newLen] = 0;
descr->length = newLen;
}
@@ -347,7 +347,7 @@ Zstring& Zstring::operator+=(const defaultChar* other)
}
-Zstring& Zstring::operator+=(defaultChar ch)
+Zstring& Zstring::operator+=(DefaultChar ch)
{
const size_t oldLen = length();
copyBeforeWrite(oldLen + 1);
@@ -368,15 +368,13 @@ void Zstring::copyBeforeWrite(const size_t capacityNeeded)
const size_t newCapacity = getCapacityToAllocate(capacityNeeded);
StringDescriptor* newDescr;
- defaultChar* newData;
+ DefaultChar* newData;
allocate(1, oldLength, newCapacity, newDescr, newData);
- //StringDescriptor* newDescr = new StringDescriptor(1, oldLength, newCapacity);
- //defaultChar* newData = new defaultChar[newCapacity + 1];
if (oldLength)
{
assert(oldLength <= newCapacity);
- memcpy(newData, data, oldLength * sizeof(defaultChar));
+ memcpy(newData, data, oldLength * sizeof(DefaultChar));
newData[oldLength] = 0;
}
decRef();
@@ -387,10 +385,10 @@ void Zstring::copyBeforeWrite(const size_t capacityNeeded)
{ //try to resize the current string (allocate anew if necessary)
const size_t newCapacity = getCapacityToAllocate(capacityNeeded);
- descr = (StringDescriptor*) realloc(descr, sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(defaultChar));
+ descr = (StringDescriptor*) realloc(descr, sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar));
if (descr == NULL)
- throw; //std::bad_alloc& e
- data = (defaultChar*)(descr + 1);
+ throw std::bad_alloc();
+ data = (DefaultChar*)(descr + 1);
descr->capacity = newCapacity;
}
}
diff --git a/library/zstring.h b/library/zstring.h
index 00590d4f..9013dd22 100644
--- a/library/zstring.h
+++ b/library/zstring.h
@@ -7,7 +7,8 @@
#ifndef ZSTRING_H_INCLUDED
#define ZSTRING_H_INCLUDED
-#include <wx/string.h>
+#include <string>
+
namespace FreeFileSync
{
@@ -18,6 +19,7 @@ namespace FreeFileSync
#endif //FFS_WIN
}
+
#ifdef FFS_WIN
#define ZSTRING_WIDE_CHAR //use wide character strings
@@ -27,89 +29,93 @@ namespace FreeFileSync
#ifdef ZSTRING_CHAR
-typedef char defaultChar;
+typedef char DefaultChar;
#elif defined ZSTRING_WIDE_CHAR
-typedef wchar_t defaultChar;
+typedef wchar_t DefaultChar;
#endif
+
class Zstring
{
public:
Zstring();
- Zstring(const defaultChar* source); //string is copied: O(length)
- Zstring(const defaultChar* source, size_t length); //string is copied: O(length)
+ Zstring(const DefaultChar* source); //string is copied: O(length)
+ Zstring(const DefaultChar* source, size_t length); //string is copied: O(length)
Zstring(const Zstring& source); //reference-counting => O(1)
- Zstring(const wxString& source); //string is copied: O(length)
~Zstring();
- operator const defaultChar*() const; //implicit conversion to C string
- operator const wxString() const; //implicit conversion to wxString
+ operator const DefaultChar*() const; //implicit conversion to C string
//wxWidgets functions
- bool StartsWith(const defaultChar* begin) const;
+ bool StartsWith(const DefaultChar* begin) const;
bool StartsWith(const Zstring& begin) const;
- bool EndsWith(const defaultChar* end) const;
+ bool EndsWith(const DefaultChar* end) const;
bool EndsWith(const Zstring& end) const;
#ifdef FFS_WIN
- int CmpNoCase(const defaultChar* other) const;
+ int CmpNoCase(const DefaultChar* other) const;
int CmpNoCase(const Zstring& other) const;
#endif
- int Cmp(const defaultChar* other) const;
+ int Cmp(const DefaultChar* other) const;
int Cmp(const Zstring& other) const;
- size_t Replace(const defaultChar* old, const defaultChar* replacement, bool replaceAll = true);
- Zstring AfterLast(defaultChar ch) const;
- Zstring BeforeLast(defaultChar ch) const;
- size_t Find(defaultChar ch, bool fromEnd) const;
- bool Matches(const defaultChar* mask) const;
+ size_t Replace(const DefaultChar* old, const DefaultChar* replacement, bool replaceAll = true);
+ Zstring AfterLast(DefaultChar ch) const;
+ Zstring BeforeLast(DefaultChar ch) const;
+ size_t Find(DefaultChar ch, bool fromEnd) const;
+ bool Matches(const DefaultChar* mask) const;
Zstring& Trim(bool fromRight); //from right or left
Zstring& MakeLower();
//std::string functions
size_t length() const;
- const defaultChar* c_str() const;
+ const DefaultChar* c_str() const;
Zstring substr(size_t pos = 0, size_t len = npos) const;
bool empty() const;
- int compare(const defaultChar* other) const;
+ int compare(const DefaultChar* other) const;
int compare(const Zstring& other) const;
- int compare(const size_t pos1, const size_t n1, const defaultChar* other) const;
- size_t find(const defaultChar* str, const size_t pos = 0 ) const;
- size_t find(const defaultChar ch, const size_t pos = 0) const;
- size_t rfind(const defaultChar ch, size_t pos = npos) const;
- Zstring& replace(size_t pos1, size_t n1, const defaultChar* str, size_t n2);
+ int compare(const size_t pos1, const size_t n1, const DefaultChar* other) const;
+ size_t find(const DefaultChar* str, const size_t pos = 0 ) const;
+ size_t find(const DefaultChar ch, const size_t pos = 0) const;
+ size_t rfind(const DefaultChar ch, size_t pos = npos) const;
+ Zstring& replace(size_t pos1, size_t n1, const DefaultChar* str, size_t n2);
+ size_t size() const;
Zstring& operator=(const Zstring& source);
- Zstring& operator=(const defaultChar* source);
+ Zstring& operator=(const DefaultChar* source);
bool operator==(const Zstring& other) const;
- bool operator==(const defaultChar* other) const;
+ bool operator==(const DefaultChar* other) const;
+ bool operator!=(const Zstring& other) const;
+ bool operator!=(const DefaultChar* other) const;
+
+ DefaultChar operator[](const size_t pos) const;
Zstring& operator+=(const Zstring& other);
- Zstring& operator+=(const defaultChar* other);
- Zstring& operator+=(defaultChar ch);
+ Zstring& operator+=(const DefaultChar* other);
+ Zstring& operator+=(DefaultChar ch);
Zstring operator+(const Zstring& string2) const;
- Zstring operator+(const defaultChar* string2) const;
- Zstring operator+(const defaultChar ch) const;
+ Zstring operator+(const DefaultChar* string2) const;
+ Zstring operator+(const DefaultChar ch) const;
static const size_t npos = static_cast<size_t>(-1);
private:
- void initAndCopy(const defaultChar* source, size_t length);
- void incRef(); //support for reference-counting
+ void initAndCopy(const DefaultChar* source, size_t length);
+ void incRef() const; //support for reference-counting
void decRef(); //
void copyBeforeWrite(const size_t capacityNeeded); //and copy-on-write
struct StringDescriptor
{
StringDescriptor(const unsigned int refC, const size_t len, const size_t cap) : refCount(refC), length(len), capacity(cap) {}
- unsigned int refCount;
+ mutable unsigned int refCount;
size_t length;
size_t capacity; //allocated length without null-termination
};
- static void allocate(const unsigned int newRefCount, const size_t newLength, const size_t newCapacity, Zstring::StringDescriptor*& newDescr, defaultChar*& newData);
+ static void allocate(const unsigned int newRefCount, const size_t newLength, const size_t newCapacity, Zstring::StringDescriptor*& newDescr, DefaultChar*& newData);
StringDescriptor* descr;
- defaultChar* data;
+ DefaultChar* data;
};
@@ -151,13 +157,13 @@ inline
bool defaultIsWhiteSpace(const char ch)
{
// some compilers (e.g. VC++ 6.0) return true for a call to isspace('\xEA') => exclude char(128) to char(255)
- return (ch < 128) && isspace(ch) != 0;
+ return ((unsigned char)ch < 128) && isspace((unsigned char)ch) != 0;
}
inline
char defaultToLower(const char ch)
{
- return tolower(ch);
+ return tolower((unsigned char)ch); //caution: although tolower() has int as input parameter it expects unsigned chars!
}
#elif defined ZSTRING_WIDE_CHAR
@@ -217,20 +223,20 @@ void Zstring::allocate(const unsigned int newRefCount,
const size_t newLength,
const size_t newCapacity,
StringDescriptor*& newDescr,
- defaultChar*& newData)
+ DefaultChar*& newData)
{ //allocate and set data for new string
if (newCapacity)
{
- newDescr = (StringDescriptor*) malloc( sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(defaultChar));
+ newDescr = (StringDescriptor*) malloc( sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar));
if (newDescr == NULL)
- throw; //std::bad_alloc& e
- newData = (defaultChar*)(newDescr + 1);
+ throw std::bad_alloc();
+ newData = (DefaultChar*)(newDescr + 1);
}
else
{
newDescr = (StringDescriptor*) malloc( sizeof(StringDescriptor));
if (newDescr == NULL)
- throw; //std::bad_alloc& e
+ throw std::bad_alloc();
newData = NULL;
}
@@ -259,14 +265,14 @@ Zstring::Zstring()
inline
-Zstring::Zstring(const defaultChar* source)
+Zstring::Zstring(const DefaultChar* source)
{
initAndCopy(source, defaultLength(source));
}
inline
-Zstring::Zstring(const defaultChar* source, size_t length)
+Zstring::Zstring(const DefaultChar* source, size_t length)
{
initAndCopy(source, length);
}
@@ -282,13 +288,6 @@ Zstring::Zstring(const Zstring& source)
inline
-Zstring::Zstring(const wxString& source)
-{
- initAndCopy(source.c_str(), source.length());
-}
-
-
-inline
Zstring::~Zstring()
{
decRef();
@@ -303,17 +302,17 @@ size_t getCapacityToAllocate(const size_t length)
inline
-void Zstring::initAndCopy(const defaultChar* source, size_t length)
+void Zstring::initAndCopy(const DefaultChar* source, size_t length)
{
const size_t newCapacity = getCapacityToAllocate(length);
allocate(1, length, newCapacity, descr, data);
- memcpy(data, source, length * sizeof(defaultChar));
+ memcpy(data, source, length * sizeof(DefaultChar));
data[length] = 0;
}
inline
-void Zstring::incRef()
+void Zstring::incRef() const
{
assert(descr);
++descr->refCount;
@@ -337,7 +336,7 @@ void Zstring::decRef()
#ifdef FFS_WIN
inline
-int Zstring::CmpNoCase(const defaultChar* other) const
+int Zstring::CmpNoCase(const DefaultChar* other) const
{
return FreeFileSync::compareStringsWin32(c_str(), other); //way faster than wxString::CmpNoCase()!!
}
@@ -352,7 +351,7 @@ int Zstring::CmpNoCase(const Zstring& other) const
inline
-Zstring::operator const defaultChar*() const
+Zstring::operator const DefaultChar*() const
{
return c_str();
}
@@ -361,19 +360,17 @@ Zstring::operator const defaultChar*() const
inline
Zstring& Zstring::operator=(const Zstring& source)
{
- if (this != &source)
- {
- decRef();
- descr = source.descr;
- data = source.data;
- incRef();
- }
+ source.incRef(); //implicitly handle case "this == &source" and avoid this check
+ decRef(); //
+ descr = source.descr;
+ data = source.data;
+
return *this;
}
inline
-size_t Zstring::Find(defaultChar ch, bool fromEnd) const
+size_t Zstring::Find(DefaultChar ch, bool fromEnd) const
{
if (fromEnd)
return rfind(ch, npos);
@@ -385,7 +382,7 @@ size_t Zstring::Find(defaultChar ch, bool fromEnd) const
// get all characters after the last occurence of ch
// (returns the whole string if ch not found)
inline
-Zstring Zstring::AfterLast(defaultChar ch) const
+Zstring Zstring::AfterLast(DefaultChar ch) const
{
size_t pos = rfind(ch, npos);
if (pos == npos )
@@ -398,7 +395,7 @@ Zstring Zstring::AfterLast(defaultChar ch) const
// get all characters before the last occurence of ch
// (returns empty string if ch not found)
inline
-Zstring Zstring::BeforeLast(defaultChar ch) const
+Zstring Zstring::BeforeLast(DefaultChar ch) const
{
size_t pos = rfind(ch, npos);
@@ -410,7 +407,7 @@ Zstring Zstring::BeforeLast(defaultChar ch) const
inline
-bool Zstring::StartsWith(const defaultChar* begin) const
+bool Zstring::StartsWith(const DefaultChar* begin) const
{
const size_t beginLength = defaultLength(begin);
if (length() < beginLength)
@@ -430,7 +427,7 @@ bool Zstring::StartsWith(const Zstring& begin) const
inline
-bool Zstring::EndsWith(const defaultChar* end) const
+bool Zstring::EndsWith(const DefaultChar* end) const
{
const size_t thisLength = length();
const size_t endLength = defaultLength(end);
@@ -452,57 +449,64 @@ bool Zstring::EndsWith(const Zstring& end) const
inline
-size_t Zstring::find(const defaultChar* str, const size_t pos) const
+size_t Zstring::find(const DefaultChar* str, const size_t pos) const
{
assert(pos <= length());
- const defaultChar* thisStr = c_str();
- const defaultChar* found = defaultStrFind(thisStr + pos, str);
+ const DefaultChar* thisStr = c_str();
+ const DefaultChar* found = defaultStrFind(thisStr + pos, str);
return found == NULL ? npos : found - thisStr;
}
inline
-size_t Zstring::find(const defaultChar ch, const size_t pos) const
+size_t Zstring::find(const DefaultChar ch, const size_t pos) const
{
assert(pos <= length());
- const defaultChar* thisStr = c_str();
- const defaultChar* found = defaultStrFind(thisStr + pos, ch);
+ const DefaultChar* thisStr = c_str();
+ const DefaultChar* found = defaultStrFind(thisStr + pos, ch);
return found == NULL ? npos : found - thisStr;
}
inline
-Zstring::operator const wxString() const
+int Zstring::Cmp(const DefaultChar* other) const
{
- return wxString(c_str());
+ return compare(other);
}
inline
-int Zstring::Cmp(const defaultChar* other) const
+int Zstring::Cmp(const Zstring& other) const
{
- return compare(other);
+ return defaultCompare(c_str(), other.c_str()); //overload using strcmp(char*, char*) should be fastest!
}
inline
-int Zstring::Cmp(const Zstring& other) const
+bool Zstring::operator==(const Zstring& other) const
{
- return defaultCompare(c_str(), other.c_str()); //overload using strcmp(char*, char*) should be fastest!
+ return length() != other.length() ? false : defaultCompare(c_str(), other.c_str()) == 0;
}
inline
-bool Zstring::operator==(const Zstring& other) const
+bool Zstring::operator==(const DefaultChar* other) const
{
- return defaultCompare(c_str(), other.c_str()) == 0; //overload using strcmp(char*, char*) should be fastest!
+ return defaultCompare(c_str(), other) == 0; //overload using strcmp(char*, char*) should be fastest!
}
inline
-bool Zstring::operator==(const defaultChar* other) const
+bool Zstring::operator!=(const Zstring& other) const
{
- return compare(other) == 0;
+ return length() != other.length() ? true: defaultCompare(c_str(), other.c_str()) != 0;
+}
+
+
+inline
+bool Zstring::operator!=(const DefaultChar* other) const
+{
+ return defaultCompare(c_str(), other) != 0; //overload using strcmp(char*, char*) should be fastest!
}
@@ -514,14 +518,14 @@ int Zstring::compare(const Zstring& other) const
inline
-int Zstring::compare(const defaultChar* other) const
+int Zstring::compare(const DefaultChar* other) const
{
return defaultCompare(c_str(), other); //overload using strcmp(char*, char*) should be fastest!
}
inline
-int Zstring::compare(const size_t pos1, const size_t n1, const defaultChar* other) const
+int Zstring::compare(const size_t pos1, const size_t n1, const DefaultChar* other) const
{
assert(length() - pos1 >= n1);
return defaultCompare(c_str() + pos1, other, n1);
@@ -536,7 +540,14 @@ size_t Zstring::length() const
inline
-const defaultChar* Zstring::c_str() const
+size_t Zstring::size() const
+{
+ return descr->length;
+}
+
+
+inline
+const DefaultChar* Zstring::c_str() const
{
if (length())
return data;
@@ -557,6 +568,14 @@ bool Zstring::empty() const
inline
+DefaultChar Zstring::operator[](const size_t pos) const
+{
+ assert(pos < length());
+ return data[pos];
+}
+
+
+inline
Zstring Zstring::operator+(const Zstring& string2) const
{
return Zstring(*this)+=string2;
@@ -564,14 +583,14 @@ Zstring Zstring::operator+(const Zstring& string2) const
inline
-Zstring Zstring::operator+(const defaultChar* string2) const
+Zstring Zstring::operator+(const DefaultChar* string2) const
{
return Zstring(*this)+=string2;
}
inline
-Zstring Zstring::operator+(const defaultChar ch) const
+Zstring Zstring::operator+(const DefaultChar ch) const
{
return Zstring(*this)+=ch;
}
bgstack15