diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/Batch.ico | bin | 15086 -> 139831 bytes | |||
-rw-r--r-- | library/FreeFileSync.ico | bin | 82726 -> 132167 bytes | |||
-rw-r--r-- | library/SyncDB.ico | bin | 82726 -> 145378 bytes | |||
-rw-r--r-- | library/custom_grid.cpp | 956 | ||||
-rw-r--r-- | library/custom_grid.h | 13 | ||||
-rw-r--r-- | library/detect_renaming.cpp | 84 | ||||
-rw-r--r-- | library/dir_lock.cpp | 31 | ||||
-rw-r--r-- | library/error_log.cpp | 68 | ||||
-rw-r--r-- | library/error_log.h | 39 | ||||
-rw-r--r-- | library/filter.cpp | 70 | ||||
-rw-r--r-- | library/icon_buffer.cpp | 139 | ||||
-rw-r--r-- | library/icon_buffer.h | 11 | ||||
-rw-r--r-- | library/pch.h | 16 | ||||
-rw-r--r-- | library/process_xml.cpp | 165 | ||||
-rw-r--r-- | library/process_xml.h | 21 | ||||
-rw-r--r-- | library/resources.cpp | 14 | ||||
-rw-r--r-- | library/resources.h | 10 | ||||
-rw-r--r-- | library/soft_filter.h | 2 | ||||
-rw-r--r-- | library/statistics.cpp | 4 | ||||
-rw-r--r-- | library/status_handler.h | 3 |
20 files changed, 910 insertions, 736 deletions
diff --git a/library/Batch.ico b/library/Batch.ico Binary files differindex 580be81f..7b33067a 100644 --- a/library/Batch.ico +++ b/library/Batch.ico diff --git a/library/FreeFileSync.ico b/library/FreeFileSync.ico Binary files differindex bfa8ffc4..b87789a7 100644 --- a/library/FreeFileSync.ico +++ b/library/FreeFileSync.ico diff --git a/library/SyncDB.ico b/library/SyncDB.ico Binary files differindex e70a3a16..eee91c14 100644 --- a/library/SyncDB.ico +++ b/library/SyncDB.ico diff --git a/library/custom_grid.cpp b/library/custom_grid.cpp index 274ef778..7b853138 100644 --- a/library/custom_grid.cpp +++ b/library/custom_grid.cpp @@ -68,8 +68,8 @@ public: } -//########################################################################### -//grid standard input output methods, redirected directly to gridData to improve performance + //########################################################################### + //grid standard input output methods, redirected directly to gridData to improve performance virtual int GetNumberRows() { @@ -150,7 +150,7 @@ public: } lastNrCols = currentNrCols; } -//########################################################################### + //########################################################################### virtual wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) @@ -277,27 +277,27 @@ protected: { switch (colType_) { - case xmlAccess::FULL_PATH: - value = zToWx(fileObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); - break; - case xmlAccess::FILENAME: //filename - value = zToWx(fileObj.getShortName<side>()); - break; - case xmlAccess::REL_PATH: //relative path - value = zToWx(fileObj.getParentRelativeName()); - break; - case xmlAccess::DIRECTORY: - value = zToWx(fileObj.getBaseDirPf<side>()); - break; - case xmlAccess::SIZE: //file size - value = ffs3::numberToStringSep(fileObj.getFileSize<side>()); - break; - case xmlAccess::DATE: //date - value = ffs3::utcTimeToLocalString(fileObj.getLastWriteTime<side>()); - break; - case xmlAccess::EXTENSION: //file extension - value = zToWx(fileObj.getExtension<side>()); - break; + case xmlAccess::FULL_PATH: + value = zToWx(fileObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); + break; + case xmlAccess::FILENAME: //filename + value = zToWx(fileObj.getShortName<side>()); + break; + case xmlAccess::REL_PATH: //relative path + value = zToWx(fileObj.getParentRelativeName()); + break; + case xmlAccess::DIRECTORY: + value = zToWx(fileObj.getBaseDirPf<side>()); + break; + case xmlAccess::SIZE: //file size + value = ffs3::numberToStringSep(fileObj.getFileSize<side>()); + break; + case xmlAccess::DATE: //date + value = ffs3::utcTimeToLocalString(fileObj.getLastWriteTime<side>()); + break; + case xmlAccess::EXTENSION: //file extension + value = zToWx(fileObj.getExtension<side>()); + break; } } @@ -305,27 +305,27 @@ protected: { switch (colType_) { - case xmlAccess::FULL_PATH: - value = zToWx(linkObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); - break; - case xmlAccess::FILENAME: //filename - value = zToWx(linkObj.getShortName<side>()); - break; - case xmlAccess::REL_PATH: //relative path - value = zToWx(linkObj.getParentRelativeName()); - break; - case xmlAccess::DIRECTORY: - value = zToWx(linkObj.getBaseDirPf<side>()); - break; - case xmlAccess::SIZE: //file size - value = _("<Symlink>"); - break; - case xmlAccess::DATE: //date - value = ffs3::utcTimeToLocalString(linkObj.getLastWriteTime<side>()); - break; - case xmlAccess::EXTENSION: //file extension - value = wxEmptyString; - break; + case xmlAccess::FULL_PATH: + value = zToWx(linkObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); + break; + case xmlAccess::FILENAME: //filename + value = zToWx(linkObj.getShortName<side>()); + break; + case xmlAccess::REL_PATH: //relative path + value = zToWx(linkObj.getParentRelativeName()); + break; + case xmlAccess::DIRECTORY: + value = zToWx(linkObj.getBaseDirPf<side>()); + break; + case xmlAccess::SIZE: //file size + value = _("<Symlink>"); + break; + case xmlAccess::DATE: //date + value = ffs3::utcTimeToLocalString(linkObj.getLastWriteTime<side>()); + break; + case xmlAccess::EXTENSION: //file extension + value = wxEmptyString; + break; } } @@ -333,27 +333,27 @@ protected: { switch (colType_) { - case xmlAccess::FULL_PATH: - value = zToWx(dirObj.getFullName<side>()); - break; - case xmlAccess::FILENAME: - value = zToWx(dirObj.getShortName<side>()); - break; - case xmlAccess::REL_PATH: - value = zToWx(dirObj.getParentRelativeName()); - break; - case xmlAccess::DIRECTORY: - value = zToWx(dirObj.getBaseDirPf<side>()); - break; - case xmlAccess::SIZE: //file size - value = _("<Directory>"); - break; - case xmlAccess::DATE: //date - value = wxEmptyString; - break; - case xmlAccess::EXTENSION: //file extension - value = wxEmptyString; - break; + case xmlAccess::FULL_PATH: + value = zToWx(dirObj.getFullName<side>()); + break; + case xmlAccess::FILENAME: + value = zToWx(dirObj.getShortName<side>()); + break; + case xmlAccess::REL_PATH: + value = zToWx(dirObj.getParentRelativeName()); + break; + case xmlAccess::DIRECTORY: + value = zToWx(dirObj.getBaseDirPf<side>()); + break; + case xmlAccess::SIZE: //file size + value = _("<Directory>"); + break; + case xmlAccess::DATE: //date + value = wxEmptyString; + break; + case xmlAccess::EXTENSION: //file extension + value = wxEmptyString; + break; } } xmlAccess::ColumnTypes colType_; @@ -477,7 +477,7 @@ public: class CustomGridTableMiddle : public CustomGridTable { public: -//middle grid is created (first wxWidgets internal call to GetNumberCols()) with one column + //middle grid is created (first wxWidgets internal call to GetNumberCols()) with one column CustomGridTableMiddle() : CustomGridTable(0, GetNumberCols()), //attention: static binding to virtual GetNumberCols() in a Constructor! syncPreviewActive(false) {} @@ -529,43 +529,43 @@ private: { switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction { - case SO_CREATE_NEW_LEFT: - case SO_DELETE_LEFT: - case SO_OVERWRITE_LEFT: - return COLOR_SYNC_BLUE; - case SO_COPY_METADATA_TO_LEFT: - return COLOR_SYNC_BLUE_LIGHT; - case SO_CREATE_NEW_RIGHT: - case SO_DELETE_RIGHT: - case SO_OVERWRITE_RIGHT: - return COLOR_SYNC_GREEN; - case SO_COPY_METADATA_TO_RIGHT: - return COLOR_SYNC_GREEN_LIGHT; - case SO_UNRESOLVED_CONFLICT: - return COLOR_YELLOW; - case SO_DO_NOTHING: - case SO_EQUAL: - return *wxWHITE; + case SO_CREATE_NEW_LEFT: + case SO_DELETE_LEFT: + case SO_OVERWRITE_LEFT: + return COLOR_SYNC_BLUE; + case SO_COPY_METADATA_TO_LEFT: + return COLOR_SYNC_BLUE_LIGHT; + case SO_CREATE_NEW_RIGHT: + case SO_DELETE_RIGHT: + case SO_OVERWRITE_RIGHT: + return COLOR_SYNC_GREEN; + case SO_COPY_METADATA_TO_RIGHT: + return COLOR_SYNC_GREEN_LIGHT; + case SO_UNRESOLVED_CONFLICT: + return COLOR_YELLOW; + case SO_DO_NOTHING: + case SO_EQUAL: + return *wxWHITE; } } else //comparison results view { switch (fsObj->getCategory()) { - case FILE_LEFT_SIDE_ONLY: - case FILE_RIGHT_SIDE_ONLY: - return COLOR_CMP_GREEN; - case FILE_LEFT_NEWER: - case FILE_RIGHT_NEWER: - return COLOR_CMP_BLUE; - case FILE_DIFFERENT: - return COLOR_CMP_RED; - case FILE_EQUAL: - return *wxWHITE; - case FILE_CONFLICT: - return COLOR_YELLOW; - case FILE_DIFFERENT_METADATA: - return COLOR_YELLOW_LIGHT; + case FILE_LEFT_SIDE_ONLY: + case FILE_RIGHT_SIDE_ONLY: + return COLOR_CMP_GREEN; + case FILE_LEFT_NEWER: + case FILE_RIGHT_NEWER: + return COLOR_CMP_BLUE; + case FILE_DIFFERENT: + return COLOR_CMP_RED; + case FILE_EQUAL: + return *wxWHITE; + case FILE_CONFLICT: + return COLOR_YELLOW; + case FILE_DIFFERENT_METADATA: + return COLOR_YELLOW_LIGHT; } } } @@ -580,11 +580,11 @@ private: //######################################################################################################## -CustomGrid::CustomGrid(wxWindow *parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, +CustomGrid::CustomGrid(wxWindow* parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, const wxString& name) : wxGrid(parent, id, pos, size, style, name), m_gridLeft(NULL), @@ -664,7 +664,7 @@ void CustomGrid::OnPaintGrid(wxEvent& event) } -void moveCursorWhileSelecting(const int anchor, const int oldPos, const int newPos, wxGrid* grid) +void moveCursorWhileSelecting(int anchor, int oldPos, int newPos, wxGrid* grid) { //note: all positions are valid in this context! @@ -693,8 +693,8 @@ void moveCursorWhileSelecting(const int anchor, const int oldPos, const int newP void execGridCommands(wxEvent& event, wxGrid* grid) { static int anchorRow = 0; - if ( grid->GetNumberRows() == 0 || - grid->GetNumberCols() == 0) + if (grid->GetNumberRows() == 0 || + grid->GetNumberCols() == 0) return; const wxKeyEvent* keyEvent = dynamic_cast<const wxKeyEvent*> (&event); @@ -705,139 +705,184 @@ void execGridCommands(wxEvent& event, wxGrid* grid) const int cursorOldColumn = std::max(std::min(grid->GetGridCursorCol(), grid->GetNumberCols() - 1), 0); const bool shiftPressed = keyEvent->ShiftDown(); - const bool altPressed = keyEvent->AltDown(); const bool ctrlPressed = keyEvent->ControlDown(); - const bool noModPressed = !shiftPressed && !altPressed && !ctrlPressed; const int keyCode = keyEvent->GetKeyCode(); - //SHIFT + X - if (shiftPressed && keyCode == WXK_UP) - { - const int cursorNewPos = std::max(cursorOldPos - 1, 0); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - return; //no event.Skip() - } - else if (shiftPressed && keyCode == WXK_DOWN) - { - const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - return; //no event.Skip() - } - else if (shiftPressed && keyCode == WXK_LEFT) - { - const int cursorColumn = std::max(cursorOldColumn - 1, 0); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - return; //no event.Skip() - } - else if (shiftPressed && keyCode == WXK_RIGHT) - { - const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - return; //no event.Skip() - } - else if (shiftPressed && (keyCode == WXK_PAGEUP || keyCode == WXK_NUMPAD_PAGEUP)) - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - return; //no event.Skip() - } - else if (shiftPressed && (keyCode == WXK_PAGEDOWN || keyCode == WXK_NUMPAD_PAGEDOWN)) - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - return; //no event.Skip() - } - else if (shiftPressed && (keyCode == WXK_HOME || keyCode == WXK_NUMPAD_HOME)) - { - const int cursorNewPos = 0; - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - return; //no event.Skip() - } - else if (shiftPressed && (keyCode == WXK_END || keyCode == WXK_NUMPAD_END)) - { - const int cursorNewPos = grid->GetNumberRows() - 1; - moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); - return; //no event.Skip() - } + if (shiftPressed) + switch (keyCode) + { + case WXK_UP: + case WXK_NUMPAD_UP: + { + const int cursorNewPos = std::max(cursorOldPos - 1, 0); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); + return; //no event.Skip() + } + case WXK_DOWN: + case WXK_NUMPAD_DOWN: + { + const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); + return; //no event.Skip() + } + case WXK_LEFT: + case WXK_NUMPAD_LEFT: + { + const int cursorColumn = std::max(cursorOldColumn - 1, 0); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); + return; //no event.Skip() + } + case WXK_RIGHT: + case WXK_NUMPAD_RIGHT: + { + const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); + return; //no event.Skip() + } + case WXK_PAGEUP: + case WXK_NUMPAD_PAGEUP: + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); + return; //no event.Skip() + } + case WXK_PAGEDOWN: + case WXK_NUMPAD_PAGEDOWN: + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); + return; //no event.Skip() + } + case WXK_HOME: + case WXK_NUMPAD_HOME: + { + const int cursorNewPos = 0; + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); + return; //no event.Skip() + } + case WXK_END: + case WXK_NUMPAD_END: + { + const int cursorNewPos = grid->GetNumberRows() - 1; + moveCursorWhileSelecting(anchorRow, cursorOldPos, cursorNewPos, grid); + return; //no event.Skip() + } + } //CTRL + X - else if (ctrlPressed && keyCode == WXK_LEFT) - { - grid->SetGridCursor(grid->GetGridCursorRow(), 0); - grid->MakeCellVisible(grid->GetGridCursorRow(), 0); - return; //no event.Skip() - } - else if (ctrlPressed && keyCode == WXK_RIGHT) - { - grid->SetGridCursor(grid->GetGridCursorRow(), grid->GetNumberCols() - 1); - grid->MakeCellVisible(grid->GetGridCursorRow(), grid->GetNumberCols() - 1); - return; //no event.Skip() - } - else if ((ctrlPressed && keyCode == WXK_UP) || - ((noModPressed || ctrlPressed) && (keyCode == WXK_HOME || keyCode == WXK_NUMPAD_HOME))) - { - grid->SetGridCursor(0, grid->GetGridCursorCol()); - grid->MakeCellVisible(0, grid->GetGridCursorCol()); - return; //no event.Skip() - } - else if ((ctrlPressed && keyCode == WXK_DOWN) || - ((noModPressed || ctrlPressed) && (keyCode == WXK_END || keyCode == WXK_NUMPAD_END))) + if (ctrlPressed) + switch (keyCode) + { + case WXK_UP: + case WXK_NUMPAD_UP: + { + grid->SetGridCursor(0, grid->GetGridCursorCol()); + grid->MakeCellVisible(0, grid->GetGridCursorCol()); + return; //no event.Skip() + } + case WXK_DOWN: + case WXK_NUMPAD_DOWN: + { + grid->SetGridCursor(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); + grid->MakeCellVisible(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); + return; //no event.Skip() + } + case WXK_LEFT: + case WXK_NUMPAD_LEFT: + { + grid->SetGridCursor(grid->GetGridCursorRow(), 0); + grid->MakeCellVisible(grid->GetGridCursorRow(), 0); + return; //no event.Skip() + } + case WXK_RIGHT: + case WXK_NUMPAD_RIGHT: + { + grid->SetGridCursor(grid->GetGridCursorRow(), grid->GetNumberCols() - 1); + grid->MakeCellVisible(grid->GetGridCursorRow(), grid->GetNumberCols() - 1); + return; //no event.Skip() + } + } + + //button with or without control keys pressed + switch (keyCode) { - grid->SetGridCursor(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); - grid->MakeCellVisible(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); - return; //no event.Skip() + case WXK_HOME: + case WXK_NUMPAD_HOME: + { + grid->SetGridCursor(0, grid->GetGridCursorCol()); + grid->MakeCellVisible(0, grid->GetGridCursorCol()); + return; //no event.Skip() + } + case WXK_END: + case WXK_NUMPAD_END: + { + grid->SetGridCursor(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); + grid->MakeCellVisible(grid->GetNumberRows() - 1, grid->GetGridCursorCol()); + return; //no event.Skip() + } + + case WXK_PAGEUP: + case WXK_NUMPAD_PAGEUP: + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); + return; //no event.Skip() + } + case WXK_PAGEDOWN: + case WXK_NUMPAD_PAGEDOWN: + { + const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); + const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); + return; //no event.Skip() + } } //button without additonal control keys pressed - else if (noModPressed && keyCode == WXK_UP) - { - const int cursorNewPos = std::max(cursorOldPos - 1, 0); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - return; //no event.Skip() - } - else if (noModPressed && keyCode == WXK_DOWN) - { - const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - return; //no event.Skip() - } - else if (noModPressed && keyCode == WXK_LEFT) - { - const int cursorColumn = std::max(cursorOldColumn - 1, 0); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - return; //no event.Skip() - } - else if (noModPressed && keyCode == WXK_RIGHT) - { - const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); - grid->SetGridCursor(cursorOldPos, cursorColumn); - grid->MakeCellVisible(cursorOldPos, cursorColumn); - return; //no event.Skip() - } - else if ((noModPressed || ctrlPressed) && (keyCode == WXK_PAGEUP || keyCode == WXK_NUMPAD_PAGEUP)) - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::max(cursorOldPos - rowsPerPage, 0); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - return; //no event.Skip() - } - else if ((noModPressed || ctrlPressed) && (keyCode == WXK_PAGEDOWN || keyCode == WXK_NUMPAD_PAGEDOWN)) - { - const int rowsPerPage = grid->GetGridWindow()->GetSize().GetHeight() / grid->GetDefaultRowSize(); - const int cursorNewPos = std::min(cursorOldPos + rowsPerPage, grid->GetNumberRows() - 1); - grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); - return; //no event.Skip() - } + if (keyEvent->GetModifiers() == wxMOD_NONE) + switch (keyCode) + { + case WXK_UP: + case WXK_NUMPAD_UP: + { + const int cursorNewPos = std::max(cursorOldPos - 1, 0); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); + return; //no event.Skip() + } + case WXK_DOWN: + case WXK_NUMPAD_DOWN: + { + const int cursorNewPos = std::min(cursorOldPos + 1, grid->GetNumberRows() - 1); + grid->SetGridCursor(cursorNewPos, grid->GetGridCursorCol()); + grid->MakeCellVisible(cursorNewPos, grid->GetGridCursorCol()); + return; //no event.Skip() + } + case WXK_LEFT: + case WXK_NUMPAD_LEFT: + { + const int cursorColumn = std::max(cursorOldColumn - 1, 0); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); + return; //no event.Skip() + } + case WXK_RIGHT: + case WXK_NUMPAD_RIGHT: + { + const int cursorColumn = std::min(cursorOldColumn + 1, grid->GetNumberCols() - 1); + grid->SetGridCursor(cursorOldPos, cursorColumn); + grid->MakeCellVisible(cursorOldPos, cursorColumn); + return; //no event.Skip() + } + } } anchorRow = grid->GetGridCursorRow(); @@ -869,23 +914,29 @@ bool gridsShouldBeCleared(const wxEvent& event) switch (keyEvent->GetKeyCode()) { - case WXK_TAB: - case WXK_RETURN: - case WXK_ESCAPE: - case WXK_NUMPAD_ENTER: - case WXK_LEFT: - case WXK_UP: - case WXK_RIGHT: - case WXK_DOWN: - case WXK_PAGEUP: - case WXK_PAGEDOWN: - case WXK_NUMPAD_PAGEUP: - case WXK_NUMPAD_PAGEDOWN: - case WXK_HOME: - case WXK_END: - case WXK_NUMPAD_HOME: - case WXK_NUMPAD_END: - return true; + //default navigation keys + case WXK_UP: + case WXK_DOWN: + case WXK_LEFT: + case WXK_RIGHT: + case WXK_PAGEUP: + case WXK_PAGEDOWN: + case WXK_HOME: + case WXK_END: + case WXK_NUMPAD_UP: + case WXK_NUMPAD_DOWN: + case WXK_NUMPAD_LEFT: + case WXK_NUMPAD_RIGHT: + case WXK_NUMPAD_PAGEUP: + case WXK_NUMPAD_PAGEDOWN: + case WXK_NUMPAD_HOME: + case WXK_NUMPAD_END: + //other keys + case WXK_TAB: + case WXK_RETURN: + case WXK_NUMPAD_ENTER: + case WXK_ESCAPE: + return true; } return false; @@ -901,9 +952,9 @@ void CustomGrid::onGridAccess(wxEvent& event) if (!isLeading) { //notify other grids of new user focus - m_gridLeft->isLeading = m_gridLeft == this; + m_gridLeft ->isLeading = m_gridLeft == this; m_gridMiddle->isLeading = m_gridMiddle == this; - m_gridRight->isLeading = m_gridRight == this; + m_gridRight ->isLeading = m_gridRight == this; wxGrid::SetFocus(); } @@ -911,13 +962,13 @@ void CustomGrid::onGridAccess(wxEvent& event) //clear grids if (gridsShouldBeCleared(event)) { - m_gridLeft->ClearSelection(); + m_gridLeft ->ClearSelection(); m_gridMiddle->ClearSelection(); - m_gridRight->ClearSelection(); + m_gridRight ->ClearSelection(); } //update row labels NOW (needed when scrolling if buttons keep being pressed) - m_gridLeft->GetGridRowLabelWindow()->Update(); + m_gridLeft ->GetGridRowLabelWindow()->Update(); m_gridRight->GetGridRowLabelWindow()->Update(); //support for custom short-cuts (overwriting wxWidgets functionality!) @@ -935,8 +986,8 @@ void CustomGrid::adjustGridHeights(wxEvent& event) int y3 = 0; int dummy = 0; - m_gridLeft->GetViewStart(&dummy, &y1); - m_gridRight->GetViewStart(&dummy, &y2); + m_gridLeft ->GetViewStart(&dummy, &y1); + m_gridRight ->GetViewStart(&dummy, &y2); m_gridMiddle->GetViewStart(&dummy, &y3); if (y1 != y2 || y2 != y3) @@ -958,8 +1009,8 @@ void CustomGrid::adjustGridHeights(wxEvent& event) else if (y3 < yMax) m_gridMiddle->SetMargins(0, 30); - m_gridLeft->ForceRefresh(); - m_gridRight->ForceRefresh(); + m_gridLeft ->ForceRefresh(); + m_gridRight ->ForceRefresh(); m_gridMiddle->ForceRefresh(); } } @@ -985,9 +1036,9 @@ void CustomGrid::DrawColLabel(wxDC& dc, int col) if (col == m_marker.first) { if (m_marker.second == ASCENDING) - dc.DrawBitmap(GlobalResources::getInstance().getImageByName(wxT("smallUp")), GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border + dc.DrawBitmap(GlobalResources::instance().getImage(wxT("smallUp")), GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border else - dc.DrawBitmap(GlobalResources::getInstance().getImageByName(wxT("smallDown")), GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border + dc.DrawBitmap(GlobalResources::instance().getImage(wxT("smallDown")), GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border } } @@ -1081,8 +1132,8 @@ public: { //############## show windows explorer file icons ###################### - if ( showFileIcons && //evaluate at compile time - m_gridDataTable->getTypeAtPos(col) == xmlAccess::FILENAME) + if (showFileIcons && //evaluate at compile time + m_gridDataTable->getTypeAtPos(col) == xmlAccess::FILENAME) { if (rect.GetWidth() >= IconBuffer::ICON_SIZE) { @@ -1117,37 +1168,42 @@ public: { wxIcon icon; bool iconDrawnFully = false; - const bool iconLoaded = IconBuffer::getInstance().requestFileIcon(fileName, &icon); //returns false if icon is not in buffer - if (iconLoaded) { - dc.DrawIcon(icon, rectShrinked.GetX() + LEFT_BORDER, rectShrinked.GetY()); - - //----------------------------------------------------------------------------------------------- - //only mark as successful if icon was drawn fully! - //(attention: when scrolling, rows get partially updated, which can result in the upper half being blank!) + const bool loadSuccess = IconBuffer::getInstance().requestFileIcon(fileName, &icon); //returns false if icon is not in buffer + if (loadSuccess) + { + //----------------------------------------------------------------------------------------------- + //only mark as successful if icon was drawn fully! + //(attention: when scrolling, rows get partially updated, which can result in the upper half being blank!) - //rect where icon was placed - wxRect iconRect(rect); //unscrolled - iconRect.x += LEFT_BORDER; - iconRect.SetWidth(IconBuffer::ICON_SIZE); + //rect where icon was placed + wxRect iconRect(rect); //unscrolled + iconRect.x += LEFT_BORDER; + iconRect.SetWidth(IconBuffer::ICON_SIZE); - //convert to scrolled coordinates - grid.CalcScrolledPosition(iconRect.x, iconRect.y, &iconRect.x, &iconRect.y); + //convert to scrolled coordinates + grid.CalcScrolledPosition(iconRect.x, iconRect.y, &iconRect.x, &iconRect.y); - wxRegionIterator regionsInv(grid.GetGridWindow()->GetUpdateRegion()); - while (regionsInv) - { - if (regionsInv.GetRect().Contains(iconRect)) + wxRegionIterator regionsInv(grid.GetGridWindow()->GetUpdateRegion()); + while (regionsInv) { - iconDrawnFully = true; - break; + if (regionsInv.GetRect().Contains(iconRect)) + { + iconDrawnFully = true; + break; + } + ++regionsInv; } - ++regionsInv; } + else + icon = IconBuffer::getFileIcon(); //better than nothing } + + dc.DrawIcon(icon, rectShrinked.GetX() + LEFT_BORDER, rectShrinked.GetY()); + //----------------------------------------------------------------------------------------------- //save status of last icon load -> used for async. icon loading - m_loadIconSuccess[row] = iconLoaded && iconDrawnFully; + m_loadIconSuccess[row] = iconDrawnFully; } } return; @@ -1164,8 +1220,8 @@ public: wxDC& dc, int row, int col) { - if ( showFileIcons && //evaluate at compile time - m_gridDataTable->getTypeAtPos(col) == xmlAccess::FILENAME) + if (showFileIcons && //evaluate at compile time + m_gridDataTable->getTypeAtPos(col) == xmlAccess::FILENAME) { wxSize rv = wxGridCellStringRenderer::GetBestSize(grid, attr, dc, row, col); rv.SetWidth(rv.GetWidth() + LEFT_BORDER + IconBuffer::ICON_SIZE); @@ -1186,7 +1242,7 @@ private: //---------------------------------------------------------------------------------------- -CustomGridRim::CustomGridRim(wxWindow *parent, +CustomGridRim::CustomGridRim(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -1374,7 +1430,7 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) SetColAttr(i, cellAttributes); break; } -//---------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------- columnSettings.clear(); if (attr.size() == 0) @@ -1422,7 +1478,7 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) for (size_t i = 0; i < newPositions.size(); ++i) SetColSize(static_cast<int>(i), columnSettings[i].width); -//-------------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------------- //set special alignment for column "size" if (GetLayoutDirection() != wxLayout_RightToLeft) //don't change for RTL languages for (int i = 0; i < GetNumberCols(); ++i) @@ -1452,20 +1508,20 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType) { switch (colType) { - case xmlAccess::FULL_PATH: - return _("Full path"); - case xmlAccess::FILENAME: - return _("Filename"); - case xmlAccess::REL_PATH: - return _("Relative path"); - case xmlAccess::DIRECTORY: - return _("Directory"); - case xmlAccess::SIZE: - return _("Size"); - case xmlAccess::DATE: - return _("Date"); - case xmlAccess::EXTENSION: - return _("Extension"); + case xmlAccess::FULL_PATH: + return _("Full path"); + case xmlAccess::FILENAME: + return _("Filename"); + case xmlAccess::REL_PATH: + return _("Relative path"); + case xmlAccess::DIRECTORY: + return _("Directory"); + case xmlAccess::SIZE: + return _("Size"); + case xmlAccess::DATE: + return _("Date"); + case xmlAccess::EXTENSION: + return _("Extension"); } return wxEmptyString; //dummy @@ -1648,7 +1704,7 @@ void IconUpdater::loadIconsAsynchronously(wxEvent& event) //loads all (not yet) //merge vectors newLoad.insert(newLoad.end(), iconsLeft.begin(), iconsLeft.end()); - ffs3::IconBuffer::getInstance().setWorkload(newLoad); //attention: newLoad is invalidated after this call!!! + ffs3::IconBuffer::getInstance().setWorkload(newLoad); //event.Skip(); } @@ -1656,7 +1712,7 @@ void IconUpdater::loadIconsAsynchronously(wxEvent& event) //loads all (not yet) //---------------------------------------------------------------------------------------- -CustomGridLeft::CustomGridLeft(wxWindow *parent, +CustomGridLeft::CustomGridLeft(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -1706,7 +1762,7 @@ CustomGridTable* CustomGridLeft::getGridDataTable() const //---------------------------------------------------------------------------------------- -CustomGridRight::CustomGridRight(wxWindow *parent, +CustomGridRight::CustomGridRight(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -1784,7 +1840,7 @@ const int CHECK_BOX_WIDTH = CHECK_BOX_IMAGE + 3; //width of first block // ---------------------------------- -CustomGridMiddle::CustomGridMiddle(wxWindow *parent, +CustomGridMiddle::CustomGridMiddle(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -1918,35 +1974,35 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) const SyncOperation syncOp = fsObj->getSyncOperation(); switch (syncOp) { - case SO_CREATE_NEW_LEFT: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncCreateLeftAct"))); - break; - case SO_CREATE_NEW_RIGHT: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncCreateRightAct"))); - break; - case SO_DELETE_LEFT: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDeleteLeftAct"))); - break; - case SO_DELETE_RIGHT: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDeleteRightAct"))); - break; - case SO_OVERWRITE_LEFT: - case SO_COPY_METADATA_TO_LEFT: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDirLeftAct"))); - break; - case SO_OVERWRITE_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDirRightAct"))); - break; - case SO_DO_NOTHING: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDirNoneAct"))); - break; - case SO_EQUAL: - toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("equalAct"))); - break; - case SO_UNRESOLVED_CONFLICT: - toolTip->show(fsObj->getSyncOpConflict(), pos, &GlobalResources::getInstance().getImageByName(wxT("conflictAct"))); - break; + case SO_CREATE_NEW_LEFT: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("syncCreateLeftAct"))); + break; + case SO_CREATE_NEW_RIGHT: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("syncCreateRightAct"))); + break; + case SO_DELETE_LEFT: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("syncDeleteLeftAct"))); + break; + case SO_DELETE_RIGHT: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("syncDeleteRightAct"))); + break; + case SO_OVERWRITE_LEFT: + case SO_COPY_METADATA_TO_LEFT: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("syncDirLeftAct"))); + break; + case SO_OVERWRITE_RIGHT: + case SO_COPY_METADATA_TO_RIGHT: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("syncDirRightAct"))); + break; + case SO_DO_NOTHING: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("syncDirNoneAct"))); + break; + case SO_EQUAL: + toolTip->show(getDescription(syncOp), pos, &GlobalResources::instance().getImage(wxT("equalAct"))); + break; + case SO_UNRESOLVED_CONFLICT: + toolTip->show(fsObj->getSyncOpConflict(), pos, &GlobalResources::instance().getImage(wxT("conflictAct"))); + break; }; } else @@ -1954,30 +2010,30 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) const CompareFilesResult cmpRes = fsObj->getCategory(); switch (cmpRes) { - case FILE_LEFT_SIDE_ONLY: - toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("leftOnlyAct"))); - break; - case FILE_RIGHT_SIDE_ONLY: - toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("rightOnlyAct"))); - break; - case FILE_LEFT_NEWER: - toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("leftNewerAct"))); - break; - case FILE_RIGHT_NEWER: - toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("rightNewerAct"))); - break; - case FILE_DIFFERENT: - toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("differentAct"))); - break; - case FILE_EQUAL: - toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("equalAct"))); - break; - case FILE_DIFFERENT_METADATA: - toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("conflictAct"))); - break; - case FILE_CONFLICT: - toolTip->show(fsObj->getCatConflict(), pos, &GlobalResources::getInstance().getImageByName(wxT("conflictAct"))); - break; + case FILE_LEFT_SIDE_ONLY: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::instance().getImage(wxT("leftOnlyAct"))); + break; + case FILE_RIGHT_SIDE_ONLY: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::instance().getImage(wxT("rightOnlyAct"))); + break; + case FILE_LEFT_NEWER: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::instance().getImage(wxT("leftNewerAct"))); + break; + case FILE_RIGHT_NEWER: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::instance().getImage(wxT("rightNewerAct"))); + break; + case FILE_DIFFERENT: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::instance().getImage(wxT("differentAct"))); + break; + case FILE_EQUAL: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::instance().getImage(wxT("equalAct"))); + break; + case FILE_DIFFERENT_METADATA: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::instance().getImage(wxT("conflictAct"))); + break; + case FILE_CONFLICT: + toolTip->show(fsObj->getCatConflict(), pos, &GlobalResources::instance().getImage(wxT("conflictAct"))); + break; } } } @@ -1998,34 +2054,34 @@ void CustomGridMiddle::OnLeftMouseUp(wxMouseEvent& event) { switch (selectionPos) { - case BLOCKPOS_CHECK_BOX: - { - //create a custom event - FFSCheckRowsEvent evt(selectionRowBegin, rowEndFiltering); - AddPendingEvent(evt); - } - break; - case BLOCKPOS_LEFT: - { - //create a custom event - FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_LEFT); - AddPendingEvent(evt); - } - break; - case BLOCKPOS_MIDDLE: - { - //create a custom event - FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_NONE); - AddPendingEvent(evt); - } - break; - case BLOCKPOS_RIGHT: - { - //create a custom event - FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_RIGHT); - AddPendingEvent(evt); - } - break; + case BLOCKPOS_CHECK_BOX: + { + //create a custom event + FFSCheckRowsEvent evt(selectionRowBegin, rowEndFiltering); + AddPendingEvent(evt); + } + break; + case BLOCKPOS_LEFT: + { + //create a custom event + FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_LEFT); + AddPendingEvent(evt); + } + break; + case BLOCKPOS_MIDDLE: + { + //create a custom event + FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_NONE); + AddPendingEvent(evt); + } + break; + case BLOCKPOS_RIGHT: + { + //create a custom event + FFSSyncDirectionEvent evt(selectionRowBegin, rowEndFiltering, SYNC_DIR_RIGHT); + AddPendingEvent(evt); + } + break; } } selectionRowBegin = -1; @@ -2057,9 +2113,9 @@ int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) if (row >= 0) { const FileSystemObject* const fsObj = getGridDataTableMiddle()->getRawData(row); - if ( fsObj != NULL && //if valid row... - getGridDataTableMiddle()->syncPreviewIsActive() && - fsObj->getSyncOperation() != SO_EQUAL) //in sync-preview equal files shall be treated as in cmp result, i.e. as full checkbox + if (fsObj != NULL && //if valid row... + getGridDataTableMiddle()->syncPreviewIsActive() && + fsObj->getSyncOperation() != SO_EQUAL) //in sync-preview equal files shall be treated as in cmp result, i.e. as full checkbox { // cell: // ---------------------------------- @@ -2125,19 +2181,19 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, rectShrinked.SetX(rect.GetX() + 1); //HIGHLIGHTNING (checkbox): - if ( rowIsHighlighted && - m_gridMiddle.highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) + if (rowIsHighlighted && + m_gridMiddle.highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) { if (fsObj->isActive()) - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("checkboxTrueFocus")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("checkboxTrueFocus")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); else - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("checkboxFalseFocus")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("checkboxFalseFocus")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); } //default else if (fsObj->isActive()) - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("checkboxTrue")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("checkboxTrue")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); else - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("checkboxFalse")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("checkboxFalse")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); //clean remaining block of rect that will receive image of checkbox/directions rectShrinked.SetWidth(rect.GetWidth() - CHECK_BOX_WIDTH); @@ -2150,21 +2206,21 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, //print sync direction into second block //HIGHLIGHTNING (sync direction): - if ( rowIsHighlighted && - m_gridMiddle.highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files + if (rowIsHighlighted && + m_gridMiddle.highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files switch (m_gridMiddle.highlightedPos) { - case CustomGridMiddle::BLOCKPOS_CHECK_BOX: - break; - case CustomGridMiddle::BLOCKPOS_LEFT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_LEFT)), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - break; - case CustomGridMiddle::BLOCKPOS_MIDDLE: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_NONE)), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case CustomGridMiddle::BLOCKPOS_RIGHT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_RIGHT)), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - break; + case CustomGridMiddle::BLOCKPOS_CHECK_BOX: + break; + case CustomGridMiddle::BLOCKPOS_LEFT: + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_LEFT)), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + break; + case CustomGridMiddle::BLOCKPOS_MIDDLE: + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_NONE)), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; + case CustomGridMiddle::BLOCKPOS_RIGHT: + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_RIGHT)), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + break; } else //default { @@ -2176,28 +2232,28 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, { switch (fsObj->getCategory()) { - case FILE_LEFT_SIDE_ONLY: - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("leftOnlySmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_RIGHT_SIDE_ONLY: - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("rightOnlySmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_LEFT_NEWER: - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("leftNewerSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_RIGHT_NEWER: - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("rightNewerSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_DIFFERENT: - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("differentSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_EQUAL: - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("equalSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_CONFLICT: - case FILE_DIFFERENT_METADATA: - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("conflictSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; + case FILE_LEFT_SIDE_ONLY: + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("leftOnlySmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; + case FILE_RIGHT_SIDE_ONLY: + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("rightOnlySmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; + case FILE_LEFT_NEWER: + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("leftNewerSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; + case FILE_RIGHT_NEWER: + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("rightNewerSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; + case FILE_DIFFERENT: + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("differentSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; + case FILE_EQUAL: + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("equalSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; + case FILE_CONFLICT: + case FILE_DIFFERENT_METADATA: + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("conflictSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + break; } } @@ -2231,9 +2287,9 @@ void CustomGridMiddle::DrawColLabel(wxDC& dc, int col) const wxRect rect(GetColLeft(col), 0, GetColWidth(col), GetColLabelSize()); if (getGridDataTableMiddle()->syncPreviewIsActive()) - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("syncViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("syncViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); else - dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("cmpViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, GlobalResources::instance().getImage(wxT("cmpViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); } @@ -2241,26 +2297,26 @@ const wxBitmap& ffs3::getSyncOpImage(SyncOperation syncOp) { switch (syncOp) //evaluate comparison result and sync direction { - case SO_CREATE_NEW_LEFT: - return GlobalResources::getInstance().getImageByName(wxT("createLeftSmall")); - case SO_CREATE_NEW_RIGHT: - return GlobalResources::getInstance().getImageByName(wxT("createRightSmall")); - case SO_DELETE_LEFT: - return GlobalResources::getInstance().getImageByName(wxT("deleteLeftSmall")); - case SO_DELETE_RIGHT: - return GlobalResources::getInstance().getImageByName(wxT("deleteRightSmall")); - case SO_OVERWRITE_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: - return GlobalResources::getInstance().getImageByName(wxT("syncDirRightSmall")); - case SO_OVERWRITE_LEFT: - case SO_COPY_METADATA_TO_LEFT: - return GlobalResources::getInstance().getImageByName(wxT("syncDirLeftSmall")); - case SO_DO_NOTHING: - return GlobalResources::getInstance().getImageByName(wxT("syncDirNoneSmall")); - case SO_EQUAL: - return GlobalResources::getInstance().getImageByName(wxT("equalSmall")); - case SO_UNRESOLVED_CONFLICT: - return GlobalResources::getInstance().getImageByName(wxT("conflictSmall")); + case SO_CREATE_NEW_LEFT: + return GlobalResources::instance().getImage(wxT("createLeftSmall")); + case SO_CREATE_NEW_RIGHT: + return GlobalResources::instance().getImage(wxT("createRightSmall")); + case SO_DELETE_LEFT: + return GlobalResources::instance().getImage(wxT("deleteLeftSmall")); + case SO_DELETE_RIGHT: + return GlobalResources::instance().getImage(wxT("deleteRightSmall")); + case SO_OVERWRITE_RIGHT: + case SO_COPY_METADATA_TO_RIGHT: + return GlobalResources::instance().getImage(wxT("syncDirRightSmall")); + case SO_OVERWRITE_LEFT: + case SO_COPY_METADATA_TO_LEFT: + return GlobalResources::instance().getImage(wxT("syncDirLeftSmall")); + case SO_DO_NOTHING: + return GlobalResources::instance().getImage(wxT("syncDirNoneSmall")); + case SO_EQUAL: + return GlobalResources::instance().getImage(wxT("equalSmall")); + case SO_UNRESOLVED_CONFLICT: + return GlobalResources::instance().getImage(wxT("conflictSmall")); } return wxNullBitmap; //dummy diff --git a/library/custom_grid.h b/library/custom_grid.h index 1517230b..e8138bfc 100644 --- a/library/custom_grid.h +++ b/library/custom_grid.h @@ -54,7 +54,7 @@ CustomGridLeft CustomGridRight CustomGridMiddle class CustomGrid : public wxGrid { public: - CustomGrid(wxWindow *parent, + CustomGrid(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, @@ -97,12 +97,13 @@ protected: virtual CustomGridTable* getGridDataTable() const = 0; private: + void onGridAccess(wxEvent& event); + //this method is called when grid view changes: useful for parallel updating of multiple grids void OnPaintGrid(wxEvent& event); virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) = 0; - void onGridAccess(wxEvent& event); void adjustGridHeights(wxEvent& event); CustomGrid* m_gridLeft; @@ -144,7 +145,7 @@ class CustomGridRim : public CustomGrid friend class GridCellRenderer; public: - CustomGridRim(wxWindow *parent, + CustomGridRim(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -201,7 +202,7 @@ private: class CustomGridLeft : public CustomGridRim { public: - CustomGridLeft(wxWindow *parent, + CustomGridLeft(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, @@ -224,7 +225,7 @@ private: class CustomGridRight : public CustomGridRim { public: - CustomGridRight(wxWindow *parent, + CustomGridRight(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, @@ -249,7 +250,7 @@ class CustomGridMiddle : public CustomGrid friend class GridCellRendererMiddle; public: - CustomGridMiddle(wxWindow *parent, + CustomGridMiddle(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, diff --git a/library/detect_renaming.cpp b/library/detect_renaming.cpp index 3c491ae3..0e19451c 100644 --- a/library/detect_renaming.cpp +++ b/library/detect_renaming.cpp @@ -126,7 +126,7 @@ void FindDBAssoc::recurse(const DirContainer& leftSide, const DirContainer& righ } } -//----------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------------------- for (DirContainer::SubDirList::const_iterator i = leftSide.getSubDirs().begin(); i != leftSide.getSubDirs().end(); ++i) { const DirContainer::SubDirList::const_iterator j = rightSide.getSubDirs().find(i->first); @@ -172,35 +172,35 @@ private: { switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction { - case SO_CREATE_NEW_LEFT: - if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL - createLeft[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(), - fileObj.getLastWriteTime<RIGHT_SIDE>(), - fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj; - break; - - case SO_CREATE_NEW_RIGHT: - if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL - createRight.push_back(&fileObj); - break; - - case SO_DELETE_LEFT: - if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL - deleteLeft.push_back(&fileObj); - break; - - case SO_DELETE_RIGHT: - if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL - deleteRight[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(), - fileObj.getLastWriteTime<RIGHT_SIDE>(), - fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj; - break; - - case SO_OVERWRITE_RIGHT: - case SO_OVERWRITE_LEFT: - case SO_DO_NOTHING: - case SO_UNRESOLVED_CONFLICT: - break; + case SO_CREATE_NEW_LEFT: + if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL + createLeft[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(), + fileObj.getLastWriteTime<RIGHT_SIDE>(), + fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj; + break; + + case SO_CREATE_NEW_RIGHT: + if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL + createRight.push_back(&fileObj); + break; + + case SO_DELETE_LEFT: + if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL + deleteLeft.push_back(&fileObj); + break; + + case SO_DELETE_RIGHT: + if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL + deleteRight[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(), + fileObj.getLastWriteTime<RIGHT_SIDE>(), + fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj; + break; + + case SO_OVERWRITE_RIGHT: + case SO_OVERWRITE_LEFT: + case SO_DO_NOTHING: + case SO_UNRESOLVED_CONFLICT: + break; } } @@ -208,11 +208,11 @@ private: std::vector<FileMapping*> createRight; //pointer always bound! std::vector<FileMapping*> deleteLeft; // -// | -// \|/ + // | + // \|/ std::map<FindDBAssoc::AssocKey, Utility::FileID> assocDBLeftToRight; -// | -// \|/ + // | + // \|/ std::map<FindDBAssoc::AssocKey, FileMapping*> deleteRight; //pointer always bound! std::map<FindDBAssoc::AssocKey, FileMapping*> createLeft; // @@ -225,8 +225,8 @@ void FindRenameCandidates::getRenameCandidates( std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnRight) { for (std::vector<FileMapping*>::const_iterator crRightIter = createRight.begin(); - crRightIter != createRight.end(); - ++crRightIter) + crRightIter != createRight.end(); + ++crRightIter) { const FindDBAssoc::AssocKey assocDbKey((*crRightIter)->getFileID<LEFT_SIDE>(), (*crRightIter)->getLastWriteTime<LEFT_SIDE>(), @@ -239,8 +239,8 @@ void FindRenameCandidates::getRenameCandidates( { std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator delRightIter = deleteRight.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side - assocDbKey.lastWriteTimeRaw_, - assocDbKey.fileSize_)); + assocDbKey.lastWriteTimeRaw_, + assocDbKey.fileSize_)); if (delRightIter != deleteRight.end()) { @@ -250,8 +250,8 @@ void FindRenameCandidates::getRenameCandidates( } //------------------------------------------------------------------------------------------------ for (std::vector<FileMapping*>::const_iterator delLeftIter = deleteLeft.begin(); - delLeftIter != deleteLeft.end(); - ++delLeftIter) + delLeftIter != deleteLeft.end(); + ++delLeftIter) { const FindDBAssoc::AssocKey assocDbKey((*delLeftIter)->getFileID<LEFT_SIDE>(), (*delLeftIter)->getLastWriteTime<LEFT_SIDE>(), @@ -264,8 +264,8 @@ void FindRenameCandidates::getRenameCandidates( { std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator createLeftIter = createLeft.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side - assocDbKey.lastWriteTimeRaw_, - assocDbKey.fileSize_)); + assocDbKey.lastWriteTimeRaw_, + assocDbKey.fileSize_)); if (createLeftIter != createLeft.end()) { diff --git a/library/dir_lock.cpp b/library/dir_lock.cpp index 3d443b11..ba515a31 100644 --- a/library/dir_lock.cpp +++ b/library/dir_lock.cpp @@ -85,8 +85,11 @@ public: const char buffer[1] = {' '}; #ifdef FFS_WIN + //ATTENTION: setting file pointer IS required! => use CreateFile/FILE_GENERIC_WRITE + SetFilePointerEx! + //although CreateFile/FILE_APPEND_DATA without SetFilePointerEx works locally, it MAY NOT work on some network shares creating a 4 gig file!!! + const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_.c_str()).c_str(), - FILE_APPEND_DATA, + FILE_GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, @@ -98,8 +101,11 @@ public: Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, fileHandle); (void)dummy; //silence warning "unused variable" - const DWORD fpLow = ::SetFilePointer(fileHandle, 0, NULL, FILE_END); - if (fpLow == INVALID_SET_FILE_POINTER) + const LARGE_INTEGER moveDist = {}; + if (!::SetFilePointerEx(fileHandle, //__in HANDLE hFile, + moveDist, //__in LARGE_INTEGER liDistanceToMove, + NULL, //__out_opt PLARGE_INTEGER lpNewFilePointer, + FILE_END)) //__in DWORD dwMoveMethod return; DWORD bytesWritten = 0; @@ -158,8 +164,8 @@ wxULongLong getLockFileSize(const Zstring& filename) //throw (FileError, ErrorNo const DWORD lastError = ::GetLastError(); const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\"") + wxT("\n\n") + getLastErrorFormatted(lastError); - if ( lastError == ERROR_FILE_NOT_FOUND || - lastError == ERROR_PATH_NOT_FOUND) + if (lastError == ERROR_FILE_NOT_FOUND || + lastError == ERROR_PATH_NOT_FOUND) throw ErrorNotExisting(errorMessage); else throw FileError(errorMessage); @@ -253,9 +259,9 @@ struct LockInformation char formatDescr[sizeof(LOCK_FORMAT_DESCR)] = {}; stream.Read(formatDescr, sizeof(LOCK_FORMAT_DESCR)); //file format header const int lockFileVersion = util::readNumber<boost::int32_t>(stream); // - (void)lockFileVersion; + (void)lockFileVersion; - //some format checking here? + //some format checking here? lockId = readString(stream); procDescr.processId = static_cast<ProcessId>(util::readNumber<boost::uint64_t>(stream)); //possible loss of precision (32/64 bit process) covered by buildId @@ -299,8 +305,8 @@ enum ProcessStatus }; ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDescr) { - if ( procDescr.computerId != getComputerId() || - procDescr.computerId.empty()) //both names are empty + if (procDescr.computerId != getComputerId() || + procDescr.computerId.empty()) //both names are empty return PROC_STATUS_NO_IDEA; //lock owned by different computer #ifdef FFS_WIN @@ -310,7 +316,8 @@ ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDe 0); //__in DWORD th32ProcessID if (snapshot == INVALID_HANDLE_VALUE) return PROC_STATUS_NO_IDEA; - boost::shared_ptr<void> dummy(snapshot, ::CloseHandle); + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, snapshot); + (void)dummy; //silence warning "unused variable" PROCESSENTRY32 processEntry = {}; processEntry.dwSize = sizeof(processEntry); @@ -386,8 +393,8 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr lockSilentStart = currentTime; } - if ( lockOwnderDead || //no need to wait any longer... - currentTime - lockSilentStart > DETECT_EXITUS_INTERVAL) + if (lockOwnderDead || //no need to wait any longer... + currentTime - lockSilentStart > DETECT_EXITUS_INTERVAL) { DirLock dummy(deleteAbandonedLockName(lockfilename), callback); //throw (FileError) diff --git a/library/error_log.cpp b/library/error_log.cpp index 4f7c5847..1549c6b5 100644 --- a/library/error_log.cpp +++ b/library/error_log.cpp @@ -12,46 +12,74 @@ using ffs3::ErrorLogging; -void ErrorLogging::logInfo(const wxString& infoMessage) +void ErrorLogging::logMsg(const wxString& message, ffs3::MessageType type) { - const wxString prefix = wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ") + _("Info") + wxT(": "); - formattedMessages.push_back(assembleMessage(prefix, infoMessage)); -} + Entry newEntry; + newEntry.type = type; + newEntry.time = wxDateTime::GetTimeNow(); + newEntry.message = message; + messages.push_back(newEntry); -void ErrorLogging::logWarning(const wxString& warningMessage) -{ - const wxString prefix = wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ") + _("Warning") + wxT(": "); - formattedMessages.push_back(assembleMessage(prefix, warningMessage)); + ++statistics[type]; } -void ErrorLogging::logError(const wxString& errorMessage) +int ErrorLogging::typeCount(int types) const { - ++errorCount; + int count = 0; + + if (types & TYPE_INFO) + count += statistics[TYPE_INFO]; + if (types & TYPE_WARNING) + count += statistics[TYPE_WARNING]; + if (types & TYPE_ERROR) + count += statistics[TYPE_ERROR]; + if (types & TYPE_FATAL_ERROR) + count += statistics[TYPE_FATAL_ERROR]; - const wxString prefix = wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ") + _("Error") + wxT(": "); - formattedMessages.push_back(assembleMessage(prefix, errorMessage)); + return count; } -void ErrorLogging::logFatalError(const wxString& errorMessage) +std::vector<wxString> ErrorLogging::getFormattedMessages(int types) const { - ++errorCount; + std::vector<wxString> output; - const wxString prefix = wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ") + _("Fatal Error") + wxT(": "); - formattedMessages.push_back(assembleMessage(prefix, errorMessage)); + for (std::vector<Entry>::const_iterator i = messages.begin(); i != messages.end(); ++i) + if (i->type & types) + output.push_back(formatMessage(*i)); + + return output; } -wxString ErrorLogging::assembleMessage(const wxString& prefix, const wxString& message) +wxString ErrorLogging::formatMessage(const Entry& msg) { - const size_t prefixLength = prefix.size(); + wxString typeName; + switch (msg.type) + { + case TYPE_INFO: + typeName = _("Info"); + break; + case TYPE_WARNING: + typeName = _("Warning"); + break; + case TYPE_ERROR: + typeName = _("Error"); + break; + case TYPE_FATAL_ERROR: + typeName = _("Fatal Error"); + break; + } + + const wxString prefix = wxString(wxT("[")) + wxDateTime(msg.time).FormatTime() + wxT("] ") + typeName + wxT(": "); + wxString formattedText = prefix; - for (wxString::const_iterator i = message.begin(); i != message.end(); ++i) + for (wxString::const_iterator i = msg.message.begin(); i != msg.message.end(); ++i) if (*i == wxChar('\n')) { - formattedText += wxString(wxChar('\n')).Pad(prefixLength, wxChar(' '), true); + formattedText += wxString(wxChar('\n')).Pad(prefix.size(), wxChar(' '), true); while (*++i == wxChar('\n')) //remove duplicate newlines ; --i; diff --git a/library/error_log.h b/library/error_log.h index d5696f80..ff4d3aee 100644 --- a/library/error_log.h +++ b/library/error_log.h @@ -9,37 +9,42 @@ #include <wx/string.h> #include <vector> +#include <map> #include "../shared/zstring.h" namespace ffs3 { +enum MessageType +{ + TYPE_INFO = 1, + TYPE_WARNING = 2, + TYPE_ERROR = 4, + TYPE_FATAL_ERROR = 8, +}; + class ErrorLogging { public: - ErrorLogging() : errorCount(0) {} + void logMsg(const wxString& message, MessageType type); - void logInfo( const wxString& infoMessage); - void logWarning( const wxString& warningMessage); - void logError( const wxString& errorMessage); - void logFatalError(const wxString& errorMessage); + int typeCount(int types = TYPE_INFO | TYPE_WARNING | TYPE_ERROR | TYPE_FATAL_ERROR) const; - int errorsTotal() - { - return errorCount; - } + std::vector<wxString> getFormattedMessages(int types = TYPE_INFO | TYPE_WARNING | TYPE_ERROR | TYPE_FATAL_ERROR) const; - typedef std::vector<wxString> MessageEntry; - const MessageEntry& getFormattedMessages() const +private: + struct Entry { - return formattedMessages; - } + MessageType type; + time_t time; + wxString message; + }; -private: - wxString assembleMessage(const wxString& prefix, const wxString& message); + static wxString formatMessage(const Entry& msg); + + std::vector<Entry> messages; //list of non-resolved errors and warnings - MessageEntry formattedMessages; //list of non-resolved errors and warnings - int errorCount; + mutable std::map<MessageType, int> statistics; }; } diff --git a/library/filter.cpp b/library/filter.cpp index 789a5d81..70933b13 100644 --- a/library/filter.cpp +++ b/library/filter.cpp @@ -88,7 +88,7 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st static const Zstring asteriskSep = Zstring(Zchar('*')) + common::FILE_NAME_SEPARATOR; static const Zstring questionMarkSep = Zstring(Zchar('?')) + common::FILE_NAME_SEPARATOR; -//-------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------- //add some syntactic sugar: handle beginning of filtername if (filterFormatted.StartsWith(common::FILE_NAME_SEPARATOR)) { @@ -101,7 +101,7 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st addFilterEntry(Zstring(filterFormatted.c_str() + 1), fileFilter, directoryFilter); //prevent further recursion by prefix } -//-------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------- //even more syntactic sugar: handle end of filtername if (filterFormatted.EndsWith(common::FILE_NAME_SEPARATOR)) { @@ -149,35 +149,35 @@ bool matchesMask(const Zchar* string, const Zchar* mask) { switch (ch) { - case Zchar('?'): - if (*string == 0) - return false; - break; - - case Zchar('*'): - //advance to next non-*/? char - do - { - ++mask; - ch = *mask; - } - while (ch == Zchar('*') || ch == Zchar('?')); - //if match ends with '*': - if (ch == 0) - return true; - - ++mask; - while ((string = cStringFind(string, ch)) != NULL) - { - ++string; - if (matchesMask(string, mask)) + case Zchar('?'): + if (*string == 0) + return false; + break; + + case Zchar('*'): + //advance to next non-*/? char + do + { + ++mask; + ch = *mask; + } + while (ch == Zchar('*') || ch == Zchar('?')); + //if match ends with '*': + if (ch == 0) return true; - } - return false; - default: - if (*string != ch) + ++mask; + while ((string = cStringFind(string, ch)) != NULL) + { + ++string; + if (matchesMask(string, mask)) + return true; + } return false; + + default: + if (*string != ch) + return false; } } return *string == 0; @@ -194,15 +194,15 @@ bool matchesMaskBegin(const Zchar* string, const Zchar* mask) switch (ch) { - case Zchar('?'): - break; + case Zchar('?'): + break; - case Zchar('*'): - return true; + case Zchar('*'): + return true; - default: - if (*string != ch) - return false; + default: + if (*string != ch) + return false; } } return *string == 0; diff --git a/library/icon_buffer.cpp b/library/icon_buffer.cpp index e03ec8c4..e346e4be 100644 --- a/library/icon_buffer.cpp +++ b/library/icon_buffer.cpp @@ -38,7 +38,7 @@ IconBuffer::BasicString IconBuffer::getFileExtension(const BasicString& filename //test for extension for icons that physically have to be retrieved from disc bool IconBuffer::isPriceyExtension(const IconBuffer::BasicString& extension) { - static std::set<BasicString, LessFilename> exceptions; + static std::set<BasicString, LessFilename> exceptions; //not thread-safe, but called from worker thread only! if (exceptions.empty()) { exceptions.insert(Zstr("exe")); @@ -70,9 +70,9 @@ public: //icon holder has value semantics! IconHolder(const IconHolder& other) : handle_(other.handle_ == 0 ? 0 : #ifdef FFS_WIN - ::CopyIcon(other.handle_) + ::CopyIcon(other.handle_) #elif defined FFS_LINUX - gdk_pixbuf_copy(other.handle_) //create new Pix buf with reference count 1 or return 0 on error + gdk_pixbuf_copy(other.handle_) //create new Pix buf with reference count 1 or return 0 on error #endif ) {} @@ -99,20 +99,20 @@ public: wxIcon toWxIcon() const //copy HandleType, caller needs to take ownership! { + if (handle_ == 0) + return wxNullIcon; + IconHolder clone(*this); - if (clone.handle_ != 0) - { - wxIcon newIcon; //attention: wxIcon uses reference counting! + + wxIcon newIcon; //attention: wxIcon uses reference counting! #ifdef FFS_WIN - newIcon.SetHICON(clone.handle_); // - newIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE); //icon is actually scaled to this size (just in case referenced HICON differs) -#elif defined FFS_LINUX // - newIcon.SetPixbuf(clone.handle_); // transfer ownership!! -#endif // - clone.handle_ = 0; // - return newIcon; - } - return wxNullIcon; + newIcon.SetHICON(clone.handle_); // + newIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE); //icon is actually scaled to this size (just in case referenced HICON differs) +#elif defined FFS_LINUX // + newIcon.SetPixbuf(clone.handle_); // transfer ownership!! +#endif // + clone.handle_ = 0; // + return newIcon; } private: @@ -124,23 +124,22 @@ const wxIcon& IconBuffer::getDirectoryIcon() //one folder icon should be suffici { static wxIcon folderIcon; - static bool isInitalized = false; + static bool isInitalized = false; //not thread-safe, but called from GUI thread only! if (!isInitalized) { isInitalized = true; #ifdef FFS_WIN - SHFILEINFO fileInfo; - fileInfo.hIcon = 0; //initialize hIcon + SHFILEINFO fileInfo = {}; //initialize hIcon - //NOTE: CoInitializeEx()/CoUninitialize() implicitly called by wxWidgets on program startup! + //NOTE: CoInitializeEx()/CoUninitialize() needs to be called for THIS thread! if (::SHGetFileInfo(Zstr("dummy"), //Windows Seven doesn't like this parameter to be an empty string FILE_ATTRIBUTE_DIRECTORY, &fileInfo, sizeof(fileInfo), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES) && - fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! + fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! { folderIcon.SetHICON(fileInfo.hIcon); //transfer ownership! folderIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE); @@ -154,17 +153,61 @@ const wxIcon& IconBuffer::getDirectoryIcon() //one folder icon should be suffici } +const wxIcon& IconBuffer::getFileIcon() //in case one folder icon is sufficient... +{ + static wxIcon fileIcon; + + static bool isInitalized = false; //not thread-safe, but called from GUI thread only! + if (!isInitalized) + { + isInitalized = true; + +#ifdef FFS_WIN + SHFILEINFO fileInfo = {}; //initialize hIcon + + //NOTE: CoInitializeEx()/CoUninitialize() needs to be called for THIS thread! + if (::SHGetFileInfo(Zstr("dummy"), //Windows Seven doesn't like this parameter to be an empty string + FILE_ATTRIBUTE_NORMAL, + &fileInfo, + sizeof(fileInfo), + SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES) && + + fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! + { + fileIcon.SetHICON(fileInfo.hIcon); //transfer ownership! + fileIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE); + } + +#elif defined FFS_LINUX + try + { + Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default(); + if (iconTheme) + { + Glib::RefPtr<Gdk::Pixbuf> iconPixbuf = iconTheme->load_icon("misc", ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN); + if (!iconPixbuf) + iconPixbuf = iconTheme->load_icon("text-x-generic", ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN); + if (iconPixbuf) + fileIcon.SetPixbuf(iconPixbuf->gobj_copy()); // transfer ownership!! + } + } + catch (const Glib::Error&) {} +#endif + } + return fileIcon; +} + + IconBuffer::IconHolder IconBuffer::getAssociatedIcon(const BasicString& filename) { #ifdef FFS_WIN //despite what docu says about SHGetFileInfo() it can't handle all relative filenames, e.g. "\DirName" //but no problem, directory formatting takes care that filenames are always absolute! - SHFILEINFO fileInfo; - fileInfo.hIcon = 0; //initialize hIcon -> fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! + SHFILEINFO fileInfo = {}; //initialize hIcon -> fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! //bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080 - //NOTE: CoInitializeEx()/CoUninitialize() implicitly called by wxWidgets on program startup! + //NOTE: CoInitializeEx()/CoUninitialize() needs to be called for THIS thread! ::SHGetFileInfo(filename.c_str(), //ffs3::removeLongPathPrefix(fileName), //::SHGetFileInfo() can't handle \\?\-prefix! 0, &fileInfo, @@ -174,14 +217,7 @@ IconBuffer::IconHolder IconBuffer::getAssociatedIcon(const BasicString& filename return IconHolder(fileInfo.hIcon); //pass icon ownership (may be 0) #elif defined FFS_LINUX - static struct RunOnce - { - RunOnce() - { - Gtk::Main::init_gtkmm_internals(); - } - } dummy; - + //call Gtk::Main::init_gtkmm_internals() on application startup!! try { Glib::RefPtr<Gio::File> fileObj = Gio::File::create_for_path(filename.c_str()); //never fails @@ -229,8 +265,7 @@ IconBuffer::IconHolder IconBuffer::getAssociatedIcon(const BasicString& filename #ifdef FFS_WIN IconBuffer::IconHolder IconBuffer::getAssociatedIconByExt(const BasicString& extension) { - SHFILEINFO fileInfo; - fileInfo.hIcon = 0; //initialize hIcon -> fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! + SHFILEINFO fileInfo = {}; //initialize hIcon -> fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! //no read-access to disk! determine icon by extension ::SHGetFileInfo((Zstr("dummy.") + extension).c_str(), //Windows Seven doesn't like this parameter to be without short name @@ -244,6 +279,28 @@ IconBuffer::IconHolder IconBuffer::getAssociatedIconByExt(const BasicString& ext #endif +namespace +{ +//failure to initialize COM for each thread is a source of hard to reproduce bugs: https://sourceforge.net/tracker/?func=detail&aid=3160472&group_id=234430&atid=1093080 +struct ThreadInitializer +{ + ThreadInitializer() + { +#ifdef FFS_WIN + ::CoInitializeEx(NULL, COINIT_MULTITHREADED); +#endif + } + + ~ThreadInitializer() + { +#ifdef FFS_WIN + ::CoUninitialize(); +#endif + } +}; +} + + class IconBuffer::WorkerThread { public: @@ -257,7 +314,7 @@ public: private: void doWork(); -//---------------------- Shared Data ------------------------- + //---------------------- Shared Data ------------------------- typedef BasicString FileName; struct SharedData @@ -266,7 +323,7 @@ private: boost::mutex mutex; boost::condition_variable condition; //signal event: data for processing available } shared; -//------------------------------------------------------------ + //------------------------------------------------------------ IconBuffer& iconBuffer; @@ -296,7 +353,7 @@ void IconBuffer::WorkerThread::setWorkload(const std::vector<Zstring>& load) //( shared.workload.clear(); for (std::vector<Zstring>::const_iterator i = load.begin(); i != load.end(); ++i) - shared.workload.push_back(FileName(i->c_str())); //make DEEP COPY from Zstring + shared.workload.push_back(FileName(i->c_str(), i->size())); //make DEEP COPY from Zstring } shared.condition.notify_one(); @@ -306,6 +363,8 @@ void IconBuffer::WorkerThread::setWorkload(const std::vector<Zstring>& load) //( void IconBuffer::WorkerThread::operator()() //thread entry { + ThreadInitializer dummy1; + try { while (true) @@ -320,10 +379,18 @@ void IconBuffer::WorkerThread::operator()() //thread entry doWork(); //no need to lock the complete method! } } + catch (boost::thread_interrupted&) + { + throw; //this is the only reasonable exception! + } catch (const std::exception& e) //exceptions must be catched per thread { wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Icon buffer)"), wxString::FromAscii(e.what())); //simple wxMessageBox won't do for threads } + catch (...) //exceptions must be catched per thread + { + wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Icon buffer2)"), wxT("Unknown exception in icon thread!")); //simple wxMessageBox won't do for threads + } } diff --git a/library/icon_buffer.h b/library/icon_buffer.h index d273a970..b00a566d 100644 --- a/library/icon_buffer.h +++ b/library/icon_buffer.h @@ -21,6 +21,7 @@ class IconBuffer { public: static const wxIcon& getDirectoryIcon(); //one folder icon should be sufficient... + static const wxIcon& getFileIcon(); //in case one folder icon is sufficient... static IconBuffer& getInstance(); bool requestFileIcon(const Zstring& fileName, wxIcon* icon = NULL); //returns false if icon is not in buffer @@ -42,10 +43,10 @@ private: class IconHolder; class IconDbSequence; -//--------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------------- typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class -//avoid reference-counted objects for shared data: NOT THREADSAFE!!! (implicitly shared variable: ref-count) -//--------------------------------------------------------------------------------------------------- + //avoid reference-counted objects for shared data: NOT THREADSAFE!!! (implicitly shared variable: ref-count) + //--------------------------------------------------------------------------------------------------- //methods used by worker thread void insertIntoBuffer(const BasicString& entryName, const IconHolder& icon); @@ -58,11 +59,11 @@ private: static bool isPriceyExtension(const BasicString& extension); #endif -//---------------------- Shared Data ------------------------- + //---------------------- Shared Data ------------------------- boost::mutex lockIconDB; std::auto_ptr<IconDB> buffer; //use synchronisation when accessing this! std::auto_ptr<IconDbSequence> bufSequence; //save sequence of buffer entry to delete oldest elements -//------------------------------------------------------------ + //------------------------------------------------------------ class WorkerThread; std::auto_ptr<WorkerThread> worker; diff --git a/library/pch.h b/library/pch.h index a8d6ae30..fa384ce5 100644 --- a/library/pch.h +++ b/library/pch.h @@ -12,8 +12,8 @@ do NOT use in release build! #endif -//##################################################### -// basic wxWidgets headers + //##################################################### + // basic wxWidgets headers #ifndef WX_PRECOMP #define WX_PRECOMP #endif @@ -24,10 +24,10 @@ do NOT use in release build! #include <wx/wxprec.h> -//##################################################### -// #include other rarely changing headers here + //##################################################### + // #include other rarely changing headers here -//STL headers + //STL headers #include <string> #include <vector> #include <set> @@ -48,7 +48,7 @@ do NOT use in release build! #include <new> #include <stdexcept> -//other wxWidgets headers + //other wxWidgets headers #include <wx/log.h> #include <wx/grid.h> #include <wx/animate.h> @@ -104,11 +104,11 @@ do NOT use in release build! #include <wx/help.h> #include <wx/event.h> -//other + //other #include "../shared/tinyxml/tinyxml.h" #include <sys/stat.h> -//Boost + //Boost #include <boost/shared_ptr.hpp> #include <boost/scoped_array.hpp> diff --git a/library/process_xml.cpp b/library/process_xml.cpp index c4e80d17..79d233fc 100644 --- a/library/process_xml.cpp +++ b/library/process_xml.cpp @@ -271,7 +271,7 @@ void FfsXmlParser::readXmlLocalConfig(const TiXmlElement& folderPair, FolderPair readXmlElementLogging("Right", &folderPair, enhPair.rightDirectory); -//########################################################### + //########################################################### //alternate sync configuration const TiXmlElement* altSyncConfig = TiXmlHandleConst(&folderPair).FirstChild("AlternateSyncConfig").ToElement(); if (altSyncConfig) @@ -296,7 +296,7 @@ void FfsXmlParser::readXmlLocalConfig(const TiXmlElement& folderPair, FolderPair readXmlElementLogging("CustomDeletionFolder", miscSettings, altSyncCfg->customDeletionDirectory); } -//########################################################### + //########################################################### //alternate filter configuration const TiXmlElement* filterCfg = TiXmlHandleConst(&folderPair).FirstChild("LocalFilter").ToElement(); if (filterCfg) @@ -312,7 +312,7 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg) { TiXmlHandleConst hRoot(getRoot()); //custom const handle: TiXml API seems broken in this regard -//########################################################### + //########################################################### const TiXmlElement* cmpSettings = hRoot.FirstChild("MainConfig").FirstChild("Comparison").ToElement(); //read compare variant @@ -321,7 +321,7 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg) //include symbolic links at all? readXmlElementLogging("HandleSymlinks", cmpSettings, mainCfg.handleSymlinks); -//########################################################### + //########################################################### const TiXmlElement* syncCfg = hRoot.FirstChild("MainConfig").FirstChild("Synchronization").ToElement(); const TiXmlElement* syncDirections = TiXmlHandleConst(syncCfg).FirstChild("Directions").ToElement(); @@ -334,13 +334,13 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg) readXmlElementLogging("Different", syncDirections, mainCfg.syncConfiguration.different); readXmlElementLogging("Conflict", syncDirections, mainCfg.syncConfiguration.conflict); -//########################################################### + //########################################################### const TiXmlElement* miscSettings = hRoot.FirstChild("MainConfig").FirstChild("Miscellaneous").ToElement(); //misc readXmlElementLogging("DeletionPolicy", miscSettings, mainCfg.handleDeletion); readXmlElementLogging("CustomDeletionFolder", miscSettings, mainCfg.customDeletionDirectory); -//########################################################### + //########################################################### const TiXmlElement* filter = TiXmlHandleConst(miscSettings).FirstChild("Filter").ToElement(); //read filter settings @@ -351,7 +351,7 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg) mainCfg.globalFilter = FilterConfig(includeFilter, excludeFilter); -//########################################################### + //########################################################### const TiXmlElement* pairs = hRoot.FirstChild("MainConfig").FirstChild("FolderPairs").FirstChild("Pair").ToElement(); //read all folder pairs @@ -403,6 +403,7 @@ void FfsXmlParser::readXmlBatchConfig(xmlAccess::XmlBatchConfig& outputCfg) readXmlElementLogging("Silent", batchConfig, outputCfg.silent); readXmlElementLogging("LogfileDirectory", batchConfig, outputCfg.logFileDirectory); + readXmlElementLogging("LogfileCountMax", batchConfig, outputCfg.logFileCountMax); readXmlElementLogging("HandleError", batchConfig, outputCfg.handleError); } @@ -471,7 +472,7 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg if (folderPairMax != 0) //if reading fails, leave at default outputCfg.gui.addFolderPairCountMax = std::max(static_cast<size_t>(2), folderPairMax) - 1; //map folderPairMax to additionalFolderPairMax -//########################################################### + //########################################################### //read column attributes readXmlAttributeLogging("AutoAdjust", TiXmlHandleConst(mainWindow).FirstChild("LeftColumns").ToElement(), outputCfg.gui.autoAdjustColumnsLeft); readXmlAttributeLogging("ShowFileIcons", TiXmlHandleConst(mainWindow).FirstChild("LeftColumns").ToElement(), outputCfg.gui.showFileIconsLeft); @@ -545,6 +546,7 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg const TiXmlElement* cfgHistory = TiXmlHandleConst(gui).FirstChild("ConfigHistory").ToElement(); //load config history elements + readXmlAttributeLogging("LastUsed", cfgHistory, outputCfg.gui.lastUsedConfigFile); readXmlElementLogging("File", cfgHistory, outputCfg.gui.cfgFileHistory); //last update check @@ -560,12 +562,12 @@ void addXmlElement(const std::string& name, const CompareVariant variant, TiXmlE { switch (variant) { - case ffs3::CMP_BY_TIME_SIZE: - xmlAccess::addXmlElement(name, std::string("ByTimeAndSize"), parent); - break; - case ffs3::CMP_BY_CONTENT: - xmlAccess::addXmlElement(name, std::string("ByContent"), parent); - break; + case ffs3::CMP_BY_TIME_SIZE: + xmlAccess::addXmlElement(name, std::string("ByTimeAndSize"), parent); + break; + case ffs3::CMP_BY_CONTENT: + xmlAccess::addXmlElement(name, std::string("ByContent"), parent); + break; } } @@ -574,15 +576,15 @@ void addXmlElement(const std::string& name, const SyncDirection value, TiXmlElem { switch (value) { - case SYNC_DIR_LEFT: - xmlAccess::addXmlElement(name, std::string("left"), parent); - break; - case SYNC_DIR_RIGHT: - xmlAccess::addXmlElement(name, std::string("right"), parent); - break; - case SYNC_DIR_NONE: - xmlAccess::addXmlElement(name, std::string("none"), parent); - break; + case SYNC_DIR_LEFT: + xmlAccess::addXmlElement(name, std::string("left"), parent); + break; + case SYNC_DIR_RIGHT: + xmlAccess::addXmlElement(name, std::string("right"), parent); + break; + case SYNC_DIR_NONE: + xmlAccess::addXmlElement(name, std::string("none"), parent); + break; } } @@ -591,15 +593,15 @@ void addXmlElement(const std::string& name, const xmlAccess::OnError value, TiXm { switch (value) { - case xmlAccess::ON_ERROR_IGNORE: - xmlAccess::addXmlElement(name, std::string("Ignore"), parent); - break; - case xmlAccess::ON_ERROR_EXIT: - xmlAccess::addXmlElement(name, std::string("Exit"), parent); - break; - case xmlAccess::ON_ERROR_POPUP: - xmlAccess::addXmlElement(name, std::string("Popup"), parent); - break; + case xmlAccess::ON_ERROR_IGNORE: + xmlAccess::addXmlElement(name, std::string("Ignore"), parent); + break; + case xmlAccess::ON_ERROR_EXIT: + xmlAccess::addXmlElement(name, std::string("Exit"), parent); + break; + case xmlAccess::ON_ERROR_POPUP: + xmlAccess::addXmlElement(name, std::string("Popup"), parent); + break; } } @@ -608,15 +610,15 @@ void addXmlElement(const std::string& name, const ffs3::DeletionPolicy value, Ti { switch (value) { - case ffs3::DELETE_PERMANENTLY: - xmlAccess::addXmlElement(name, std::string("DeletePermanently"), parent); - break; - case ffs3::MOVE_TO_RECYCLE_BIN: - xmlAccess::addXmlElement(name, std::string("MoveToRecycleBin"), parent); - break; - case ffs3::MOVE_TO_CUSTOM_DIRECTORY: - xmlAccess::addXmlElement(name, std::string("MoveToCustomDirectory"), parent); - break; + case ffs3::DELETE_PERMANENTLY: + xmlAccess::addXmlElement(name, std::string("DeletePermanently"), parent); + break; + case ffs3::MOVE_TO_RECYCLE_BIN: + xmlAccess::addXmlElement(name, std::string("MoveToRecycleBin"), parent); + break; + case ffs3::MOVE_TO_CUSTOM_DIRECTORY: + xmlAccess::addXmlElement(name, std::string("MoveToCustomDirectory"), parent); + break; } } @@ -625,15 +627,15 @@ void addXmlElement(const std::string& name, const ffs3::SymLinkHandling value, T { switch (value) { - case ffs3::SYMLINK_IGNORE: - xmlAccess::addXmlElement(name, std::string("Ignore"), parent); - break; - case ffs3::SYMLINK_USE_DIRECTLY: - xmlAccess::addXmlElement(name, std::string("UseDirectly"), parent); - break; - case ffs3::SYMLINK_FOLLOW_LINK: - xmlAccess::addXmlElement(name, std::string("FollowLink"), parent); - break; + case ffs3::SYMLINK_IGNORE: + xmlAccess::addXmlElement(name, std::string("Ignore"), parent); + break; + case ffs3::SYMLINK_USE_DIRECTLY: + xmlAccess::addXmlElement(name, std::string("UseDirectly"), parent); + break; + case ffs3::SYMLINK_FOLLOW_LINK: + xmlAccess::addXmlElement(name, std::string("FollowLink"), parent); + break; } } @@ -692,7 +694,7 @@ void writeXmlLocalConfig(const FolderPairEnh& enhPair, TiXmlElement& parent) addXmlElement("CustomDeletionFolder", altSyncConfig->customDeletionDirectory, miscSettings); } -//########################################################### + //########################################################### //alternate filter configuration TiXmlElement* filterCfg = new TiXmlElement("LocalFilter"); newfolderPair->LinkEndChild(filterCfg); @@ -711,7 +713,7 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc) TiXmlElement* settings = new TiXmlElement("MainConfig"); root->LinkEndChild(settings); -//########################################################### + //########################################################### TiXmlElement* cmpSettings = new TiXmlElement("Comparison"); settings->LinkEndChild(cmpSettings); @@ -721,7 +723,7 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc) //include symbolic links at all? addXmlElement("HandleSymlinks", mainCfg.handleSymlinks, cmpSettings); -//########################################################### + //########################################################### TiXmlElement* syncSettings = new TiXmlElement("Synchronization"); settings->LinkEndChild(syncSettings); @@ -738,7 +740,7 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc) addXmlElement("Different", mainCfg.syncConfiguration.different, syncDirections); addXmlElement("Conflict", mainCfg.syncConfiguration.conflict, syncDirections); -//########################################################### + //########################################################### TiXmlElement* miscSettings = new TiXmlElement("Miscellaneous"); settings->LinkEndChild(miscSettings); @@ -753,7 +755,7 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc) addXmlElement("DeletionPolicy", mainCfg.handleDeletion, miscSettings); addXmlElement("CustomDeletionFolder", mainCfg.customDeletionDirectory, miscSettings); -//########################################################### + //########################################################### TiXmlElement* pairs = new TiXmlElement("FolderPairs"); settings->LinkEndChild(pairs); @@ -806,6 +808,7 @@ bool writeXmlBatchConfig(const xmlAccess::XmlBatchConfig& inputCfg, TiXmlDocumen addXmlElement("Silent", inputCfg.silent, batchConfig); addXmlElement("LogfileDirectory", inputCfg.logFileDirectory, batchConfig); + addXmlElement("LogfileCountMax", inputCfg.logFileCountMax, batchConfig); addXmlElement("HandleError", inputCfg.handleError, batchConfig); return true; @@ -962,9 +965,9 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD TiXmlElement* cfgHistory = new TiXmlElement("ConfigHistory"); gui->LinkEndChild(cfgHistory); + addXmlAttribute("LastUsed", inputCfg.gui.lastUsedConfigFile, cfgHistory); addXmlElement("File", inputCfg.gui.cfgFileHistory, cfgHistory); - //last update check addXmlElement("LastUpdateCheck", inputCfg.gui.lastUpdateCheck, gui); @@ -1034,18 +1037,18 @@ xmlAccess::MergeType xmlAccess::getMergeType(const std::vector<wxString>& filena { switch (xmlAccess::getXmlType(*i)) //throw() { - case XML_GUI_CONFIG: - guiCfgExists = true; - break; - - case XML_BATCH_CONFIG: - batchCfgExists = true; - break; - - case XML_GLOBAL_SETTINGS: - case XML_REAL_CONFIG: - case XML_OTHER: - return MERGE_OTHER; + case XML_GUI_CONFIG: + guiCfgExists = true; + break; + + case XML_BATCH_CONFIG: + batchCfgExists = true; + break; + + case XML_GLOBAL_SETTINGS: + case XML_REAL_CONFIG: + case XML_OTHER: + return MERGE_OTHER; } } @@ -1097,18 +1100,18 @@ void mergeConfigFilesImpl(const std::vector<wxString>& filenames, XmlCfg& config { switch (getXmlType(*i)) { - case XML_GUI_CONFIG: - mainCfgs.push_back(loadCfgImpl<XmlGuiConfig>(*i, savedException).mainCfg); //throw (xmlAccess::XmlError) - break; - - case XML_BATCH_CONFIG: - mainCfgs.push_back(loadCfgImpl<XmlBatchConfig>(*i, savedException).mainCfg); //throw (xmlAccess::XmlError) - break; - - case XML_GLOBAL_SETTINGS: - case XML_REAL_CONFIG: - case XML_OTHER: - break; + case XML_GUI_CONFIG: + mainCfgs.push_back(loadCfgImpl<XmlGuiConfig>(*i, savedException).mainCfg); //throw (xmlAccess::XmlError) + break; + + case XML_BATCH_CONFIG: + mainCfgs.push_back(loadCfgImpl<XmlBatchConfig>(*i, savedException).mainCfg); //throw (xmlAccess::XmlError) + break; + + case XML_GLOBAL_SETTINGS: + case XML_REAL_CONFIG: + case XML_OTHER: + break; } } @@ -1124,7 +1127,7 @@ void mergeConfigFilesImpl(const std::vector<wxString>& filenames, XmlCfg& config config.mainCfg = merge(mainCfgs); if (savedException.get()) //"re-throw" exception - throw *savedException; + throw* savedException; } } diff --git a/library/process_xml.h b/library/process_xml.h index 92d94d14..dcd80327 100644 --- a/library/process_xml.h +++ b/library/process_xml.h @@ -77,12 +77,16 @@ struct XmlGuiConfig struct XmlBatchConfig { - XmlBatchConfig() : silent(false), handleError(ON_ERROR_POPUP) {} + XmlBatchConfig() : + silent(false), + logFileCountMax(200), + handleError(ON_ERROR_POPUP) {} ffs3::MainConfiguration mainCfg; bool silent; wxString logFileDirectory; + size_t logFileCountMax; OnError handleError; //reaction on error situation during synchronization }; @@ -114,7 +118,7 @@ wxString getGlobalConfigFile(); struct XmlGlobalSettings { -//--------------------------------------------------------------------- + //--------------------------------------------------------------------- //Shared (GUI/BATCH) settings XmlGlobalSettings() : programLanguage(retrieveSystemLanguage()), @@ -132,7 +136,7 @@ struct XmlGlobalSettings OptionalDialogs optDialogs; -//--------------------------------------------------------------------- + //--------------------------------------------------------------------- struct _Gui { _Gui() : @@ -160,14 +164,14 @@ struct XmlGlobalSettings //default external apps will be translated "on the fly"!!! #ifdef FFS_WIN externelApplications.push_back(std::make_pair(wxT("Open with Explorer"), //mark for extraction: _("Open with Explorer") - wxT("explorer /select, \"%name\""))); + wxT("explorer /select, \"%name\""))); externelApplications.push_back(std::make_pair(wxT("Open with default application"), //mark for extraction: _("Open with default application") - wxT("cmd /c start \"\" \"%name\""))); + wxT("cmd /c start \"\" \"%name\""))); #elif defined FFS_LINUX externelApplications.push_back(std::make_pair(wxT("Browse directory"), //mark for extraction: _("Browse directory") - wxT("xdg-open \"%dir\""))); + wxT("xdg-open \"%dir\""))); externelApplications.push_back(std::make_pair(wxT("Open with default application"), //mark for extraction: _("Open with default application") - wxT("xdg-open \"%name\""))); + wxT("xdg-open \"%name\""))); #endif } @@ -186,6 +190,7 @@ struct XmlGlobalSettings ExternalApps externelApplications; std::vector<wxString> cfgFileHistory; + wxString lastUsedConfigFile; std::vector<wxString> folderHistoryLeft; unsigned int folderHistLeftMax; @@ -205,7 +210,7 @@ struct XmlGlobalSettings wxString guiPerspectiveLast; //used by wxAuiManager } gui; -//--------------------------------------------------------------------- + //--------------------------------------------------------------------- //struct _Batch }; diff --git a/library/resources.cpp b/library/resources.cpp index 5ef33826..d07e66a8 100644 --- a/library/resources.cpp +++ b/library/resources.cpp @@ -18,7 +18,7 @@ using namespace ffs3; -const GlobalResources& GlobalResources::getInstance() +const GlobalResources& GlobalResources::instance() { static GlobalResources instance; return instance; @@ -31,6 +31,8 @@ GlobalResources::GlobalResources() animationMoney = new wxAnimation(wxNullAnimation); animationSync = new wxAnimation(wxNullAnimation); programIcon = new wxIcon(wxNullIcon); + + load(); } @@ -65,7 +67,7 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation* animation) } -void GlobalResources::load() const +void GlobalResources::load() { wxFFileInputStream input(ffs3::getResourceDir() + wxT("Resources.dat")); if (input.IsOk()) //if not... we don't want to react too harsh here @@ -104,16 +106,16 @@ void GlobalResources::load() const //*programIcon = wxIcon(FreeFileSync_xpm); //use big logo bitmap for better quality - programIcon->CopyFromBitmap(getImageByName(wxT("FreeFileSync.png"))); + programIcon->CopyFromBitmap(getImage(wxT("FreeFileSync.png"))); #endif } -const wxBitmap& GlobalResources::getImageByName(const wxString& imageName) const +const wxBitmap& GlobalResources::getImage(const wxString& imageName) const { const std::map<wxString, wxBitmap*>::const_iterator bmp = imageName.Find(wxChar('.')) == wxNOT_FOUND ? //assume .png ending if nothing else specified - bitmapResource.find(imageName + wxT(".png")) : - bitmapResource.find(imageName); + bitmapResource.find(imageName + wxT(".png")) : + bitmapResource.find(imageName); if (bmp != bitmapResource.end()) return *bmp->second; diff --git a/library/resources.h b/library/resources.h index 776fe785..691d5a6b 100644 --- a/library/resources.h +++ b/library/resources.h @@ -16,23 +16,23 @@ class GlobalResources { public: - static const GlobalResources& getInstance(); + static const GlobalResources& instance(); - const wxBitmap& getImageByName(const wxString& imageName) const; + const wxBitmap& getImage(const wxString& imageName) const; //global image resource objects wxAnimation* animationMoney; wxAnimation* animationSync; wxIcon* programIcon; - void load() const; //loads bitmap resources on program startup: logical const! - private: + void load(); //loads bitmap resources on program startup + GlobalResources(); ~GlobalResources(); //resource mapping - mutable std::map<wxString, wxBitmap*> bitmapResource; + std::map<wxString, wxBitmap*> bitmapResource; }; #endif // RESOURCES_H_INCLUDED diff --git a/library/soft_filter.h b/library/soft_filter.h index ad81ea44..4e6732a3 100644 --- a/library/soft_filter.h +++ b/library/soft_filter.h @@ -28,7 +28,7 @@ public: timeWindow_(timeWindow), currentTime(wxGetUTCTime()) {} -// typedef boost::shared_ptr<const SoftFilter> FilterRef; //always bound by design! + // typedef boost::shared_ptr<const SoftFilter> FilterRef; //always bound by design! bool passFilter(const FileMapping& fileMap) const; bool passFilter(const DirMapping& dirMap) const; diff --git a/library/statistics.cpp b/library/statistics.cpp index 7a77740c..c0bb2b25 100644 --- a/library/statistics.cpp +++ b/library/statistics.cpp @@ -168,7 +168,7 @@ wxString Statistics::getRemainingTime() const --windowBegin; //one point before window begin in order to handle "measurement holes" const TimeRecordMap::value_type& frontRecord = *windowBegin; -//----------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------------------- const double timeDelta = backRecord.first - frontRecord.first; const double dataDelta = backRecord.second.data - frontRecord.second.data; @@ -194,7 +194,7 @@ wxString Statistics::getBytesPerSecond() const --windowBegin; //one point before window begin in order to handle "measurement holes" const TimeRecordMap::value_type& frontRecord = *windowBegin; -//----------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------------------- const double timeDelta = backRecord.first - frontRecord.first; const double dataDelta = backRecord.second.data - frontRecord.second.data; diff --git a/library/status_handler.h b/library/status_handler.h index d89c4f5b..2dde4fd9 100644 --- a/library/status_handler.h +++ b/library/status_handler.h @@ -41,7 +41,7 @@ public: StatusHandler() : abortRequested(false) {} virtual ~StatusHandler() {} - //identifiers of different processes + //identifiers of different phases enum Process { PROCESS_NONE = 10, @@ -101,5 +101,4 @@ bool StatusHandler::abortIsRequested() return abortRequested; } - #endif // STATUSHANDLER_H_INCLUDED |