diff options
Diffstat (limited to 'lib')
51 files changed, 186 insertions, 2955 deletions
diff --git a/lib/IFileOperation/dll_main.cpp b/lib/IFileOperation/dll_main.cpp index 3805c99d..46c65311 100644 --- a/lib/IFileOperation/dll_main.cpp +++ b/lib/IFileOperation/dll_main.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** diff --git a/lib/IFileOperation/file_op.cpp b/lib/IFileOperation/file_op.cpp index fca802f0..8024ab91 100644 --- a/lib/IFileOperation/file_op.cpp +++ b/lib/IFileOperation/file_op.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "file_op.h" diff --git a/lib/IFileOperation/file_op.h b/lib/IFileOperation/file_op.h index c33993ad..530226d3 100644 --- a/lib/IFileOperation/file_op.h +++ b/lib/IFileOperation/file_op.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef RECYCLER_DLL_H diff --git a/lib/ShadowCopy/LockFile.cpp b/lib/ShadowCopy/LockFile.cpp index 7df3ec66..523b01bb 100644 --- a/lib/ShadowCopy/LockFile.cpp +++ b/lib/ShadowCopy/LockFile.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** diff --git a/lib/ShadowCopy/dll_main.cpp b/lib/ShadowCopy/dll_main.cpp index 3805c99d..46c65311 100644 --- a/lib/ShadowCopy/dll_main.cpp +++ b/lib/ShadowCopy/dll_main.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** diff --git a/lib/ShadowCopy/shadow.cpp b/lib/ShadowCopy/shadow.cpp index 5047a698..fc95381d 100644 --- a/lib/ShadowCopy/shadow.cpp +++ b/lib/ShadowCopy/shadow.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "shadow.h" @@ -46,6 +46,35 @@ struct shadow::ShadowData namespace { +std::wstring formatVssError(HRESULT hr) //at least the one's from IVssBackupComponents::AddToSnapshotSet; return empty if no format found +{ + switch (hr) + { + case VSS_E_BAD_STATE: + return L"VSS_E_BAD_STATE"; + case VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED: + return L"VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED"; + case VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED: + return L"VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED"; + case VSS_E_OBJECT_NOT_FOUND: + return L"VSS_E_OBJECT_NOT_FOUND"; + case VSS_E_PROVIDER_NOT_REGISTERED: + return L"VSS_E_PROVIDER_NOT_REGISTERED"; + case VSS_E_PROVIDER_VETO: + return L"VSS_E_PROVIDER_VETO"; + case VSS_E_VOLUME_NOT_SUPPORTED: + return L"VSS_E_VOLUME_NOT_SUPPORTED"; + case VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER: + return L"VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER"; + case VSS_E_UNEXPECTED_PROVIDER_ERROR: + return L"VSS_E_UNEXPECTED_PROVIDER_ERROR"; + default: + return std::wstring(); + } +} + + + inline void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize) { @@ -92,7 +121,7 @@ shadow::ShadowData createShadowCopy(const wchar_t* volumeName) //throw ComError VSS_ID snapshotSetId = {}; ZEN_CHECK_COM(backupComp->StartSnapshotSet(&snapshotSetId)); - ScopeGuard guardSnapShot = makeGuard([&]() { backupComp->AbortBackup(); }); + ScopeGuard guardSnapShot = makeGuard([&] { backupComp->AbortBackup(); }); //Quote: "This method must be called if a backup operation terminates after the creation of a //shadow copy set with "StartSnapshotSet" and before "DoSnapshotSet" returns." @@ -103,7 +132,11 @@ shadow::ShadowData createShadowCopy(const wchar_t* volumeName) //throw ComError { if (hr == VSS_E_VOLUME_NOT_SUPPORTED) throw ComError(L"Volume Shadow Copy Service is not supported on this volume!"); - throw ComError(L"Error calling \"backupComp->AddToSnapshotSet\".", hr); + const std::wstring vssError = formatVssError(hr); + if (!vssError.empty()) + throw ComError(L"Error calling \"backupComp->AddToSnapshotSet\": " + vssError); + else + throw ComError(L"Error calling \"backupComp->AddToSnapshotSet\".", hr); } } diff --git a/lib/ShadowCopy/shadow.h b/lib/ShadowCopy/shadow.h index 68b7141f..ea113dae 100644 --- a/lib/ShadowCopy/shadow.h +++ b/lib/ShadowCopy/shadow.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef SHADOWCOPY_H diff --git a/lib/Thumbnail/dll_main.cpp b/lib/Thumbnail/dll_main.cpp index 3805c99d..46c65311 100644 --- a/lib/Thumbnail/dll_main.cpp +++ b/lib/Thumbnail/dll_main.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** diff --git a/lib/Thumbnail/thumbnail.cpp b/lib/Thumbnail/thumbnail.cpp index c3d22cbd..050251de 100644 --- a/lib/Thumbnail/thumbnail.cpp +++ b/lib/Thumbnail/thumbnail.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "thumbnail.h" diff --git a/lib/Thumbnail/thumbnail.h b/lib/Thumbnail/thumbnail.h index 3feec275..7e11812c 100644 --- a/lib/Thumbnail/thumbnail.h +++ b/lib/Thumbnail/thumbnail.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef TASKBAR_SEVEN_DLL_H diff --git a/lib/binary.cpp b/lib/binary.cpp index 4fdf8899..1da93ee6 100644 --- a/lib/binary.cpp +++ b/lib/binary.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "binary.h" diff --git a/lib/binary.h b/lib/binary.h index 111af249..1fcfdf57 100644 --- a/lib/binary.h +++ b/lib/binary.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef BINARY_H_INCLUDED diff --git a/lib/custom_grid.cpp b/lib/custom_grid.cpp deleted file mode 100644 index 92f3b718..00000000 --- a/lib/custom_grid.cpp +++ /dev/null @@ -1,2422 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** - -#include "custom_grid.h" -#include "resources.h" -#include <wx/dc.h> -#include <wx+/format_unit.h> -#include <wx+/string_conv.h> -#include "resources.h" -#include <typeinfo> -#include "../ui/grid_view.h" -#include "../synchronization.h" -#include <wx/dcclient.h> -#include <wx/icon.h> -#include <wx/tooltip.h> -#include <wx/settings.h> - -#ifdef FFS_WIN -#include <wx/timer.h> -#include "status_handler.h" -#include <cmath> - -#elif defined FFS_LINUX -#include <gtk/gtk.h> -#endif - -using namespace zen; - - -const size_t MIN_ROW_COUNT = 15; - -//class containing pure grid data: basically the same as wxGridStringTable, but adds cell formatting - -/* -class hierarchy: - CustomGridTable - /|\ - ________________|________________ - | | - CustomGridTableRim | - /|\ | - __________|__________ | - | | | -CustomGridTableLeft CustomGridTableRight CustomGridTableMiddle -*/ - -class CustomGridTable : public wxGridTableBase -{ -public: - CustomGridTable(int initialRows = 0, int initialCols = 0) : //note: initialRows/initialCols MUST match with GetNumberRows()/GetNumberCols() at initialization!!! - wxGridTableBase(), - gridDataView(NULL), - lastNrRows(initialRows), - lastNrCols(initialCols) {} - - - virtual ~CustomGridTable() {} - - - void setGridDataTable(const GridView* view) - { - this->gridDataView = view; - } - - - //########################################################################### - //grid standard input output methods, redirected directly to gridData to improve performance - - virtual int GetNumberRows() - { - if (gridDataView) - return static_cast<int>(std::max(gridDataView->rowsOnView(), MIN_ROW_COUNT)); - else - return 0; //grid is initialized with zero number of rows - } - - - virtual bool IsEmptyCell(int row, int col) - { - return false; //avoid overlapping cells - - //return (GetValue(row, col) == wxEmptyString); - } - - - virtual void SetValue(int row, int col, const wxString& value) - { - assert (false); //should not be used, since values are retrieved directly from gridDataView - } - - //update dimensions of grid: no need for InsertRows(), AppendRows(), DeleteRows() anymore!!! - void updateGridSizes() - { - const int currentNrRows = GetNumberRows(); - - if (lastNrRows < currentNrRows) - { - if (GetView()) - { - wxGridTableMessage msg(this, - wxGRIDTABLE_NOTIFY_ROWS_APPENDED, - currentNrRows - lastNrRows); - - GetView()->ProcessTableMessage( msg ); - } - } - else if (lastNrRows > currentNrRows) - { - if (GetView()) - { - wxGridTableMessage msg(this, - wxGRIDTABLE_NOTIFY_ROWS_DELETED, - 0, - lastNrRows - currentNrRows); - - GetView()->ProcessTableMessage( msg ); - } - } - lastNrRows = currentNrRows; - - const int currentNrCols = GetNumberCols(); - - if (lastNrCols < currentNrCols) - { - if (GetView()) - { - wxGridTableMessage msg(this, - wxGRIDTABLE_NOTIFY_COLS_APPENDED, - currentNrCols - lastNrCols); - - GetView()->ProcessTableMessage( msg ); - } - } - else if (lastNrCols > currentNrCols) - { - if (GetView()) - { - wxGridTableMessage msg(this, - wxGRIDTABLE_NOTIFY_COLS_DELETED, - 0, - lastNrCols - currentNrCols); - - GetView()->ProcessTableMessage( msg ); - } - } - lastNrCols = currentNrCols; - } - //########################################################################### - - - virtual wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) - { - const std::pair<wxColour, wxColour> color = getRowColor(row); - - //add color to some rows - wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind); - if (result) - { - if (result->GetTextColour() == color.first && - result->GetBackgroundColour() == color.second) - { - return result; - } - else //grid attribute might be referenced by other elements, so clone it! - { - wxGridCellAttr* attr = result->Clone(); //attr has ref-count 1 - result->DecRef(); - result = attr; - } - } - else - result = new wxGridCellAttr; //created with ref-count 1 - - result->SetTextColour (color.first); - result->SetBackgroundColour(color.second); - - return result; - } - - - const FileSystemObject* getRawData(size_t row) const - { - if (gridDataView) - return gridDataView->getObject(row); //returns NULL if request is not valid or not data found - - return NULL; - } - -protected: - static const wxColour COLOR_BLUE; - static const wxColour COLOR_GREY; - static const wxColour COLOR_ORANGE; - static const wxColour COLOR_CMP_RED; - static const wxColour COLOR_CMP_BLUE; - static const wxColour COLOR_CMP_GREEN; - static const wxColour COLOR_SYNC_BLUE; - static const wxColour COLOR_SYNC_BLUE_LIGHT; - static const wxColour COLOR_SYNC_GREEN; - static const wxColour COLOR_SYNC_GREEN_LIGHT; - static const wxColour COLOR_YELLOW; - static const wxColour COLOR_YELLOW_LIGHT; - - const GridView* gridDataView; //(very fast) access to underlying grid data :) - -private: - virtual const std::pair<wxColour, wxColour> getRowColor(int row) = 0; //rows that are filtered out are shown in different color: <foreground, background> - - int lastNrRows; - int lastNrCols; -}; - -//see http://www.latiumsoftware.com/en/articles/00015.php#12 for "safe" colors -const wxColour CustomGridTable::COLOR_ORANGE( 238, 201, 0); -const wxColour CustomGridTable::COLOR_BLUE( 80, 110, 255); -const wxColour CustomGridTable::COLOR_GREY( 212, 208, 200); -const wxColour CustomGridTable::COLOR_CMP_RED( 249, 163, 165); -const wxColour CustomGridTable::COLOR_CMP_BLUE( 144, 232, 246); -const wxColour CustomGridTable::COLOR_CMP_GREEN( 147, 253, 159); -const wxColour CustomGridTable::COLOR_SYNC_BLUE( 201, 203, 247); -const wxColour CustomGridTable::COLOR_SYNC_BLUE_LIGHT(201, 225, 247); -const wxColour CustomGridTable::COLOR_SYNC_GREEN(197, 248, 190); -const wxColour CustomGridTable::COLOR_SYNC_GREEN_LIGHT(226, 248, 190); -const wxColour CustomGridTable::COLOR_YELLOW( 247, 252, 62); -const wxColour CustomGridTable::COLOR_YELLOW_LIGHT(253, 252, 169); - - -class CustomGridTableRim : public CustomGridTable -{ -public: - virtual ~CustomGridTableRim() {} - - virtual int GetNumberCols() - { - return static_cast<int>(columnPositions.size()); - } - - virtual wxString GetColLabelValue( int col ) - { - return CustomGridRim::getTypeName(getTypeAtPos(col)); - } - - - void setupColumns(const std::vector<xmlAccess::ColumnTypes>& positions) - { - columnPositions = positions; - updateGridSizes(); //add or remove columns - } - - - xmlAccess::ColumnTypes getTypeAtPos(size_t pos) const - { - if (pos < columnPositions.size()) - return columnPositions[pos]; - else - return xmlAccess::DIRECTORY; - } - - //get filename in order to retrieve the icon from it - virtual Zstring getIconFile(size_t row) const = 0; //return "folder" if row points to a folder - -protected: - template <SelectedSide side> - wxString GetValueSub(int row, int col) - { - const FileSystemObject* fsObj = getRawData(row); - if (fsObj) - { - struct GetTextValue : public FSObjectVisitor - { - GetTextValue(xmlAccess::ColumnTypes colType, const FileSystemObject& fso) : colType_(colType), fsObj_(fso) {} - virtual void visit(const FileMapping& fileObj) - { - switch (colType_) - { - case xmlAccess::FULL_PATH: - value = toWx(beforeLast(fileObj.getFullName<side>(), FILE_NAME_SEPARATOR)); - break; - case xmlAccess::FILENAME: //filename - value = toWx(fileObj.getShortName<side>()); - break; - case xmlAccess::REL_PATH: //relative path - value = toWx(beforeLast(fileObj.getObjRelativeName(), FILE_NAME_SEPARATOR)); //returns empty string if ch not found - break; - case xmlAccess::DIRECTORY: - value = toWx(fileObj.getBaseDirPf<side>()); - break; - case xmlAccess::SIZE: //file size - if (!fsObj_.isEmpty<side>()) - value = zen::toStringSep(fileObj.getFileSize<side>()); - break; - case xmlAccess::DATE: //date - if (!fsObj_.isEmpty<side>()) - value = zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()); - break; - case xmlAccess::EXTENSION: //file extension - value = toWx(fileObj.getExtension<side>()); - break; - } - } - - virtual void visit(const SymLinkMapping& linkObj) - { - switch (colType_) - { - case xmlAccess::FULL_PATH: - value = toWx(beforeLast(linkObj.getFullName<side>(), FILE_NAME_SEPARATOR)); - break; - case xmlAccess::FILENAME: //filename - value = toWx(linkObj.getShortName<side>()); - break; - case xmlAccess::REL_PATH: //relative path - value = toWx(beforeLast(linkObj.getObjRelativeName(), FILE_NAME_SEPARATOR)); //returns empty string if ch not found - break; - case xmlAccess::DIRECTORY: - value = toWx(linkObj.getBaseDirPf<side>()); - break; - case xmlAccess::SIZE: //file size - if (!fsObj_.isEmpty<side>()) - value = _("<Symlink>"); - break; - case xmlAccess::DATE: //date - if (!fsObj_.isEmpty<side>()) - value = zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>()); - break; - case xmlAccess::EXTENSION: //file extension - value = wxEmptyString; - break; - } - } - - virtual void visit(const DirMapping& dirObj) - { - switch (colType_) - { - case xmlAccess::FULL_PATH: - value = toWx(dirObj.getFullName<side>()); - break; - case xmlAccess::FILENAME: - value = toWx(dirObj.getShortName<side>()); - break; - case xmlAccess::REL_PATH: - value = toWx(beforeLast(dirObj.getObjRelativeName(), FILE_NAME_SEPARATOR)); //returns empty string if ch not found - break; - case xmlAccess::DIRECTORY: - value = toWx(dirObj.getBaseDirPf<side>()); - break; - case xmlAccess::SIZE: //file size - if (!fsObj_.isEmpty<side>()) - value = _("<Directory>"); - break; - case xmlAccess::DATE: //date - if (!fsObj_.isEmpty<side>()) - value = wxEmptyString; - break; - case xmlAccess::EXTENSION: //file extension - value = wxEmptyString; - break; - } - } - xmlAccess::ColumnTypes colType_; - wxString value; - - const FileSystemObject& fsObj_; - } getVal(getTypeAtPos(col), *fsObj); - fsObj->accept(getVal); - return getVal.value; - } - //if data is not found: - return wxEmptyString; - } - - template <SelectedSide side> - Zstring getIconFileImpl(size_t row) const //return "folder" if row points to a folder - { - const FileSystemObject* fsObj = getRawData(row); - if (fsObj && !fsObj->isEmpty<side>()) - { - struct GetIcon : public FSObjectVisitor - { - virtual void visit(const FileMapping& fileObj) - { - //Optimization: if filename exists on both sides, always use left side's file - //if (!fileObj.isEmpty<LEFT_SIDE>() && !fileObj.isEmpty<RIGHT_SIDE>()) - // iconName = fileObj.getFullName<LEFT_SIDE>(); - //else -> now with thumbnails this isn't viable anymore - iconName = fileObj.getFullName<side>(); - } - virtual void visit(const SymLinkMapping& linkObj) - { - iconName = linkObj.getLinkType<side>() == LinkDescriptor::TYPE_DIR ? - Zstr("folder") : - linkObj.getFullName<side>(); - } - virtual void visit(const DirMapping& dirObj) - { - iconName = Zstr("folder"); - } - - Zstring iconName; - } getIcon; - fsObj->accept(getIcon); - return getIcon.iconName; - } - - return Zstring(); - } - - -private: - virtual const std::pair<wxColour, wxColour> getRowColor(int row) //rows that are filtered out are shown in different color: <foreground, background> - { - std::pair<wxColour, wxColour> result(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), - wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - - const FileSystemObject* fsObj = getRawData(row); - if (fsObj) - { - //mark filtered rows - if (!fsObj->isActive()) - { - result.first = *wxBLACK; - result.second = COLOR_BLUE; - } - else - { - //mark directories and symlinks - struct GetRowColor : public FSObjectVisitor - { - GetRowColor(wxColour& foreground, wxColour& background) : foreground_(foreground), background_(background) {} - - virtual void visit(const FileMapping& fileObj) {} - virtual void visit(const SymLinkMapping& linkObj) - { - foreground_ = *wxBLACK; - background_ = COLOR_ORANGE; - } - virtual void visit(const DirMapping& dirObj) - { - foreground_ = *wxBLACK; - background_ = COLOR_GREY; - } - - private: - wxColour& foreground_; - wxColour& background_; - } getCol(result.first, result.second); - fsObj->accept(getCol); - } - } - - return result; - } - - std::vector<xmlAccess::ColumnTypes> columnPositions; -}; - - -class CustomGridTableLeft : public CustomGridTableRim -{ -public: - - virtual wxString GetValue(int row, int col) - { - return CustomGridTableRim::GetValueSub<LEFT_SIDE>(row, col); - } - - virtual Zstring getIconFile(size_t row) const //return "folder" if row points to a folder - { - return getIconFileImpl<LEFT_SIDE>(row); - } -}; - - -class CustomGridTableRight : public CustomGridTableRim -{ -public: - virtual wxString GetValue(int row, int col) - { - return CustomGridTableRim::GetValueSub<RIGHT_SIDE>(row, col); - } - - virtual Zstring getIconFile(size_t row) const //return "folder" if row points to a folder - { - return getIconFileImpl<RIGHT_SIDE>(row); - } -}; - - -class CustomGridTableMiddle : public CustomGridTable -{ -public: - //middle grid is created (first wxWidgets internal call to GetNumberCols()) with one column - CustomGridTableMiddle() : - CustomGridTable(0, GetNumberCols()), //attention: static binding to virtual GetNumberCols() in a Constructor! - syncPreviewActive(false) {} - - virtual int GetNumberCols() - { - return 1; - } - - virtual wxString GetColLabelValue( int col ) - { - return wxEmptyString; - } - - virtual wxString GetValue(int row, int col) //method used for exporting .csv file only! - { - const FileSystemObject* fsObj = getRawData(row); - if (fsObj) - { - if (syncPreviewActive) //synchronization preview - return getSymbol(fsObj->getSyncOperation()); - else - return getSymbol(fsObj->getCategory()); - } - return wxEmptyString; - } - - void enableSyncPreview(bool value) - { - syncPreviewActive = value; - } - - bool syncPreviewIsActive() const - { - return syncPreviewActive; - } - -private: - virtual const std::pair<wxColour, wxColour> getRowColor(int row) //rows that are filtered out are shown in different color: <foreground, background> - { - std::pair<wxColour, wxColour> result(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), - wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - - const FileSystemObject* fsObj = getRawData(row); - if (fsObj) - { - //mark filtered rows - if (!fsObj->isActive()) - { - result.first = *wxBLACK;; - result.second = COLOR_BLUE; - } - else - { - if (syncPreviewActive) //synchronization preview - { - switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_DO_NOTHING: - case SO_EQUAL: - break;//usually white - case SO_CREATE_NEW_LEFT: - case SO_OVERWRITE_LEFT: - case SO_DELETE_LEFT: - case SO_MOVE_LEFT_SOURCE: - case SO_MOVE_LEFT_TARGET: - case SO_COPY_METADATA_TO_LEFT: - result.first = *wxBLACK; - result.second = COLOR_SYNC_BLUE; - break; - // result.second = COLOR_SYNC_BLUE_LIGHT; - break; - case SO_CREATE_NEW_RIGHT: - case SO_OVERWRITE_RIGHT: - case SO_DELETE_RIGHT: - case SO_MOVE_RIGHT_SOURCE: - case SO_MOVE_RIGHT_TARGET: - case SO_COPY_METADATA_TO_RIGHT: - result.first = *wxBLACK; - result.second = COLOR_SYNC_GREEN; - break; - // result.second = COLOR_SYNC_GREEN_LIGHT; - case SO_UNRESOLVED_CONFLICT: - result.first = *wxBLACK; - result.second = COLOR_YELLOW; - break; - } - } - else //comparison results view - { - switch (fsObj->getCategory()) - { - case FILE_LEFT_SIDE_ONLY: - case FILE_LEFT_NEWER: - result.first = *wxBLACK; - result.second = COLOR_SYNC_BLUE; //COLOR_CMP_BLUE; - break; - - case FILE_RIGHT_SIDE_ONLY: - case FILE_RIGHT_NEWER: - result.first = *wxBLACK; - result.second = COLOR_SYNC_GREEN; //COLOR_CMP_GREEN; - break; - case FILE_DIFFERENT: - result.first = *wxBLACK; - result.second = COLOR_CMP_RED; - break; - case FILE_EQUAL: - break;//usually white - case FILE_CONFLICT: - result.first = *wxBLACK; - result.second = COLOR_YELLOW; - break; - case FILE_DIFFERENT_METADATA: - result.first = *wxBLACK; - result.second = COLOR_YELLOW_LIGHT; - break; - } - } - } - } - - return result; - } - - bool syncPreviewActive; //determines wheter grid shall show compare result or sync preview -}; - -//######################################################################################################## - - -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), - m_gridMiddle(NULL), - m_gridRight(NULL), - isLeading(false), - m_marker(-1, ASCENDING) -{ - //wxColour darkBlue(40, 35, 140); -> user default colors instead! - //SetSelectionBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)); - //SetSelectionForeground(*wxWHITE); -} - - -void CustomGrid::initSettings(CustomGridLeft* gridLeft, - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const GridView* gridDataView) -{ - assert(this == gridLeft || this == gridRight || this == gridMiddle); - - //these grids will scroll together - m_gridLeft = gridLeft; - m_gridRight = gridRight; - m_gridMiddle = gridMiddle; - - //enhance grid functionality; identify leading grid by keyboard input or scroll action - Connect(wxEVT_KEY_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_TOP, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_BOTTOM, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_PAGEUP, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_PAGEDOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - Connect(wxEVT_SET_FOCUS, wxEventHandler(CustomGrid::onGridAccess), NULL, this); //used by grid text-search - GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - GetGridWindow()->Connect(wxEVT_RIGHT_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); - - GetGridWindow()->Connect(wxEVT_ENTER_WINDOW, wxEventHandler(CustomGrid::adjustGridHeights), NULL, this); - - //parallel grid scrolling: do NOT use DoPrepareDC() to align grids! GDI resource leak! Use regular paint event instead: - GetGridWindow()->Connect(wxEVT_PAINT, wxEventHandler(CustomGrid::OnPaintGrid), NULL, this); -} - - -void CustomGrid::release() //release connection to zen::GridView -{ - assert(getGridDataTable()); - getGridDataTable()->setGridDataTable(NULL); //kind of "disable" griddatatable; don't delete it with SetTable(NULL)! May be used by wxGridCellStringRenderer -} - - -bool CustomGrid::isLeadGrid() const -{ - return isLeading; -} - - -void CustomGrid::setIconManager(const std::shared_ptr<IconBuffer>& iconBuffer) -{ - if (iconBuffer.get()) - SetDefaultRowSize(iconBuffer->getSize() + 1, true); //+ 1 for line between rows - else - SetDefaultRowSize(IconBuffer(IconBuffer::SIZE_SMALL).getSize() + 1, true); //currently iconBuffer is always bound, but we may use it as a "no icon" status at some time... - - enableFileIcons(iconBuffer); - Refresh(); -} - - -void CustomGrid::RefreshCell(int row, int col) -{ - wxRect rectScrolled(CellToRect(row, col)); - //use: wxRect rect = CellToRect( row, col ); ? - CalcScrolledPosition(rectScrolled.x, rectScrolled.y, &rectScrolled.x, &rectScrolled.y); - - GetGridWindow()->RefreshRect(rectScrolled); //note: CellToRect() and YToRow work on m_gridWindow NOT on the whole grid! -} - - -void CustomGrid::OnPaintGrid(wxEvent& event) -{ - if (isLeadGrid()) //avoid back coupling - alignOtherGrids(m_gridLeft, m_gridMiddle, m_gridRight); //scroll other grids - event.Skip(); -} - - -void moveCursorWhileSelecting(int anchor, int oldPos, int newPos, wxGrid* grid) -{ - //note: all positions are valid in this context! - - grid->SetGridCursor( newPos, grid->GetGridCursorCol()); - grid->MakeCellVisible(newPos, grid->GetGridCursorCol()); - - if (oldPos < newPos) - { - for (int i = oldPos; i < std::min(anchor, newPos); ++i) - grid->DeselectRow(i); //remove selection - - for (int i = std::max(oldPos, anchor); i <= newPos; ++i) - grid->SelectRow(i, true); //add to selection - } - else - { - for (int i = std::max(newPos, anchor) + 1; i <= oldPos; ++i) - grid->DeselectRow(i); //remove selection - - for (int i = newPos; i <= std::min(oldPos, anchor); ++i) - grid->SelectRow(i, true); //add to selection - } -} - - -void execGridCommands(wxEvent& event, wxGrid* grid) -{ - static int anchorRow = 0; - if (grid->GetNumberRows() == 0 || - grid->GetNumberCols() == 0) - return; - - const wxKeyEvent* keyEvent = dynamic_cast<const wxKeyEvent*> (&event); - if (keyEvent) - { - //ensure cursorOldPos is always a valid row! - const int cursorOldPos = std::max(std::min(grid->GetGridCursorRow(), grid->GetNumberRows() - 1), 0); - const int cursorOldColumn = std::max(std::min(grid->GetGridCursorCol(), grid->GetNumberCols() - 1), 0); - - const bool shiftPressed = keyEvent->ShiftDown(); - const bool ctrlPressed = keyEvent->ControlDown(); - const int keyCode = keyEvent->GetKeyCode(); - - //SHIFT + X - 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 - 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) - { - 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 - 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(); - event.Skip(); //let event delegate! -} - - -inline -bool gridsShouldBeCleared(const wxEvent& event) -{ - const wxMouseEvent* mouseEvent = dynamic_cast<const wxMouseEvent*>(&event); - if (mouseEvent) - { - if (mouseEvent->ControlDown() || mouseEvent->ShiftDown()) - return false; - - if (mouseEvent->ButtonDown(wxMOUSE_BTN_LEFT)) - return true; - } - else - { - const wxKeyEvent* keyEvent = dynamic_cast<const wxKeyEvent*>(&event); - if (keyEvent) - { - if (keyEvent->ControlDown() || keyEvent->AltDown() || keyEvent->ShiftDown()) - return false; - - switch (keyEvent->GetKeyCode()) - { - //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; -} - - -void CustomGrid::onGridAccess(wxEvent& event) -{ - if (!isLeading) - { - //notify other grids of new user focus - m_gridLeft ->isLeading = m_gridLeft == this; - m_gridMiddle->isLeading = m_gridMiddle == this; - m_gridRight ->isLeading = m_gridRight == this; - - wxGrid::SetFocus(); - } - - //clear grids - if (gridsShouldBeCleared(event)) - { - m_gridLeft ->ClearSelection(); - m_gridMiddle->ClearSelection(); - m_gridRight ->ClearSelection(); - } - - //update row labels NOW (needed when scrolling if buttons keep being pressed) - m_gridLeft ->GetGridRowLabelWindow()->Update(); - m_gridRight->GetGridRowLabelWindow()->Update(); - - //support for custom short-cuts (overwriting wxWidgets functionality!) - execGridCommands(event, this); //event.Skip is handled here! -} - - -//workaround: ensure that all grids are properly aligned: add some extra window space to grids that have no horizontal scrollbar -void CustomGrid::adjustGridHeights(wxEvent& event) -{ - //m_gridLeft, m_gridRight, m_gridMiddle not NULL because called after initSettings() - - int y1 = 0; - int y2 = 0; - int y3 = 0; - int dummy = 0; - - m_gridLeft ->GetViewStart(&dummy, &y1); - m_gridRight ->GetViewStart(&dummy, &y2); - m_gridMiddle->GetViewStart(&dummy, &y3); - - if (y1 != y2 || y2 != y3) - { - int yMax = std::max(y1, std::max(y2, y3)); - - if (m_gridLeft->isLeadGrid()) //do not handle case (y1 == yMax) here!!! Avoid back coupling! - m_gridLeft->SetMargins(0, 0); - else if (y1 < yMax) - m_gridLeft->SetMargins(0, 30); - - if (m_gridRight->isLeadGrid()) - m_gridRight->SetMargins(0, 0); - else if (y2 < yMax) - m_gridRight->SetMargins(0, 30); - - if (m_gridMiddle->isLeadGrid()) - m_gridMiddle->SetMargins(0, 0); - else if (y3 < yMax) - m_gridMiddle->SetMargins(0, 30); - - m_gridLeft ->ForceRefresh(); - m_gridRight ->ForceRefresh(); - m_gridMiddle->ForceRefresh(); - } -} - - -void CustomGrid::updateGridSizes() -{ - if (getGridDataTable()) - getGridDataTable()->updateGridSizes(); -} - - -void CustomGridRim::updateGridSizes() -{ - CustomGrid::updateGridSizes(); - - //set row label size - if (GetRowLabelSize() > 0) - { - //SetRowLabelSize(wxGRID_AUTOSIZE); -> we can do better - wxClientDC dc(GetGridRowLabelWindow()); - dc.SetFont(GetLabelFont()); - - wxArrayString lines; - lines.push_back(GetRowLabelValue(GetNumberRows())); - - long width = 0; - long dummy = 0; - GetTextBoxSize(dc, lines, &width, &dummy); - - width += 8; - - SetRowLabelSize(width); - } -} - - -void CustomGrid::setSortMarker(SortMarker marker) -{ - m_marker = marker; -} - - -void CustomGrid::DrawColLabel(wxDC& dc, int col) -{ - wxGrid::DrawColLabel(dc, col); - - if (col == m_marker.first) - { - if (m_marker.second == ASCENDING) - dc.DrawBitmap(GlobalResources::getImage(wxT("smallUp")), GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border - else - dc.DrawBitmap(GlobalResources::getImage(wxT("smallDown")), GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border - } -} - - -std::pair<int, int> CustomGrid::mousePosToCell(wxPoint pos) -{ - int x = -1; - int y = -1; - CalcUnscrolledPosition(pos.x, pos.y, &x, &y); - - std::pair<int, int> output(-1, -1); - if (x >= 0 && y >= 0) - { - output.first = YToRow(y); - output.second = XToCol(x); - } - return output; -} - - -std::set<size_t> CustomGrid::getAllSelectedRows() const -{ - std::set<size_t> output; - - const wxArrayInt selectedRows = this->GetSelectedRows(); - if (!selectedRows.IsEmpty()) - { - for (size_t i = 0; i < selectedRows.GetCount(); ++i) - output.insert(selectedRows[i]); - } - - if (!this->GetSelectedCols().IsEmpty()) //if a column is selected this is means all rows are marked for deletion - { - for (int k = 0; k < const_cast<CustomGrid*>(this)->GetNumberRows(); ++k) //messy wxGrid implementation... - output.insert(k); - } - - const wxGridCellCoordsArray singlySelected = this->GetSelectedCells(); - if (!singlySelected.IsEmpty()) - { - for (size_t k = 0; k < singlySelected.GetCount(); ++k) - output.insert(singlySelected[k].GetRow()); - } - - const wxGridCellCoordsArray tmpArrayTop = this->GetSelectionBlockTopLeft(); - if (!tmpArrayTop.IsEmpty()) - { - wxGridCellCoordsArray tmpArrayBottom = this->GetSelectionBlockBottomRight(); - - size_t arrayCount = tmpArrayTop.GetCount(); - - if (arrayCount == tmpArrayBottom.GetCount()) - { - for (size_t i = 0; i < arrayCount; ++i) - { - const int rowTop = tmpArrayTop[i].GetRow(); - const int rowBottom = tmpArrayBottom[i].GetRow(); - - for (int k = rowTop; k <= rowBottom; ++k) - output.insert(k); - } - } - } - - //some exception: also add current cursor row to selection if there are no others... hopefully improving usability - if (output.empty() && this->isLeadGrid()) - output.insert(const_cast<CustomGrid*>(this)->GetCursorRow()); //messy wxGrid implementation... - - return output; -} - - -//############################################################################################ -//CustomGrid specializations - -class GridCellRenderer : public wxGridCellStringRenderer -{ -public: - GridCellRenderer(CustomGridRim::FailedIconLoad& failedLoads, - const CustomGridTableRim* gridDataTable, - const std::shared_ptr<zen::IconBuffer>& iconBuffer) : - failedLoads_(failedLoads), - m_gridDataTable(gridDataTable), - iconBuffer_(iconBuffer) {} - - - virtual void Draw(wxGrid& grid, - wxGridCellAttr& attr, - wxDC& dc, - const wxRect& rect, //unscrolled rect - int row, int col, - bool isSelected) - { - //############## show windows explorer file icons ###################### - - if (iconBuffer_.get() && - m_gridDataTable->getTypeAtPos(col) == xmlAccess::FILENAME) - { - const int iconSize = iconBuffer_->getSize(); - if (rect.GetWidth() >= iconSize) - { - // Partitioning: - // ____________________________ - // | 2 pix border | icon | rest | - // ---------------------------- - { - //clear area where icon will be placed (including border) - wxRect rectShrinked(rect); - rectShrinked.SetWidth(LEFT_BORDER + iconSize); //add 2 pixel border - wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected); - } - - { - //draw rest - wxRect rest(rect); //unscrolled - rest.x += LEFT_BORDER + iconSize; - rest.width -= LEFT_BORDER + iconSize; - wxGridCellStringRenderer::Draw(grid, attr, dc, rest, row, col, isSelected); - } - - wxRect rectIcon(rect); - rectIcon.SetWidth(iconSize); //set to icon area only - rectIcon.x += LEFT_BORDER; // - - //try to draw icon - //retrieve grid data - const Zstring fileName = m_gridDataTable->getIconFile(row); - if (!fileName.empty()) - { - wxIcon icon; - - //first check if it is a directory icon: - if (fileName == Zstr("folder")) - icon = iconBuffer_->genericDirIcon(); - else //retrieve file icon - { - if (!iconBuffer_->requestFileIcon(fileName, &icon)) //returns false if icon is not in buffer - { - icon = iconBuffer_->genericFileIcon(); //better than nothing - - failedLoads_.insert(row); //save status of failed icon load -> used for async. icon loading - //falsify only! we want to avoid writing incorrect success values when only partially updating the DC, e.g. when scrolling, - //see repaint behavior of ::ScrollWindow() function! - } - } - - if (icon.IsOk()) - { - int posX = rectIcon.GetX(); - int posY = rectIcon.GetY(); - //center icon if it is too small - if (rectIcon.GetWidth() > icon.GetWidth()) - posX += (rectIcon.GetWidth() - icon.GetWidth()) / 2; - if (rectIcon.GetHeight() > icon.GetHeight()) - posY += (rectIcon.GetHeight() - icon.GetHeight()) / 2; - - dc.DrawIcon(icon, posX, posY); - } - } - return; - } - } - - //default - wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); - } - - - virtual wxSize GetBestSize(wxGrid& grid, //adapt reported width if file icons are shown - wxGridCellAttr& attr, - wxDC& dc, - int row, int col) - { - if (iconBuffer_.get() && //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_->getSize()); - return rv; - } - - //default - return wxGridCellStringRenderer::GetBestSize(grid, attr, dc, row, col); - } - - -private: - CustomGridRim::FailedIconLoad& failedLoads_; - const CustomGridTableRim* const m_gridDataTable; - std::shared_ptr<zen::IconBuffer> iconBuffer_; - - static const int LEFT_BORDER = 2; -}; - -//---------------------------------------------------------------------------------------- - -CustomGridRim::CustomGridRim(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) : - CustomGrid(parent, id, pos, size, style, name), otherGrid(NULL) -{ - Connect(wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler(CustomGridRim::OnResizeColumn), NULL, this); //row-based tooltip -} - - -void CustomGridRim::setOtherGrid(CustomGridRim* other) //call during initialization! -{ - otherGrid = other; -} - - -void CustomGridRim::OnResizeColumn(wxGridSizeEvent& event) -{ - //Resize columns on both sides in parallel - const int thisCol = event.GetRowOrCol(); - - if (!otherGrid || thisCol < 0 || thisCol >= GetNumberCols()) return; - - const xmlAccess::ColumnTypes thisColType = getTypeAtPos(thisCol); - - for (int i = 0; i < otherGrid->GetNumberCols(); ++i) - if (otherGrid->getTypeAtPos(i) == thisColType) - { - otherGrid->SetColSize(i, GetColSize(thisCol)); - otherGrid->ForceRefresh(); - break; - } -} - - -//this method is called when grid view changes: useful for parallel updating of multiple grids -void CustomGridRim::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) -{ - if (!otherGrid) return; - - int x = 0; - int y = 0; - GetViewStart(&x, &y); - gridMiddle->Scroll(-1, y); - otherGrid->Scroll(x, y); -} - - -template <SelectedSide side> -void CustomGridRim::setTooltip(const wxMouseEvent& event) -{ - const int hoveredRow = mousePosToCell(event.GetPosition()).first; - - wxString toolTip; - if (hoveredRow >= 0 && getGridDataTable() != NULL) - { - const FileSystemObject* const fsObj = getGridDataTable()->getRawData(hoveredRow); - if (fsObj && !fsObj->isEmpty<side>()) - { - struct AssembleTooltip : public FSObjectVisitor - { - AssembleTooltip(wxString& tipMsg) : tipMsg_(tipMsg) {} - - virtual void visit(const FileMapping& fileObj) - { - tipMsg_ = copyStringTo<wxString>(std::wstring() + fileObj.getRelativeName<side>() + L"\n" + - _("Size") + L": " + zen::filesizeToShortString(to<Int64>(fileObj.getFileSize<side>())) + L"\n" + - _("Date") + L": " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>())); - } - - virtual void visit(const SymLinkMapping& linkObj) - { - tipMsg_ = copyStringTo<wxString>(std::wstring() + linkObj.getRelativeName<side>() + L"\n" + - _("Date") + L": " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>())); - } - - virtual void visit(const DirMapping& dirObj) - { - tipMsg_ = toWx(dirObj.getRelativeName<side>()); - } - - wxString& tipMsg_; - } assembler(toolTip); - fsObj->accept(assembler); - } - } - - - wxToolTip* tt = GetGridWindow()->GetToolTip(); - - const wxString currentTip = tt ? tt->GetTip() : wxString(); - if (toolTip != currentTip) - { - if (toolTip.IsEmpty()) - GetGridWindow()->SetToolTip(NULL); //wxGTK doesn't allow wxToolTip with empty text! - else - { - //wxWidgets bug: tooltip multiline property is defined by first tooltip text containing newlines or not (same is true for maximum width) - if (!tt) - GetGridWindow()->SetToolTip(new wxToolTip(wxT("a b\n\ - a b"))); //ugly, but is working (on Windows) - tt = GetGridWindow()->GetToolTip(); //should be bound by now - if (tt) - tt->SetTip(toolTip); - } - } -} - - -xmlAccess::ColumnAttributes CustomGridRim::getDefaultColumnAttributes() -{ - xmlAccess::ColumnAttributes defaultColumnSettings; - - xmlAccess::ColumnAttrib newEntry; - newEntry.type = xmlAccess::FULL_PATH; - newEntry.visible = false; - newEntry.position = 0; - newEntry.width = 150; - defaultColumnSettings.push_back(newEntry); - - newEntry.type = xmlAccess::DIRECTORY; - newEntry.position = 1; - newEntry.width = 140; - defaultColumnSettings.push_back(newEntry); - - newEntry.type = xmlAccess::REL_PATH; - newEntry.visible = true; - newEntry.position = 2; - newEntry.width = 118; - defaultColumnSettings.push_back(newEntry); - - newEntry.type = xmlAccess::FILENAME; - newEntry.position = 3; - newEntry.width = 138; - defaultColumnSettings.push_back(newEntry); - - newEntry.type = xmlAccess::SIZE; - newEntry.position = 4; - newEntry.width = 80; - defaultColumnSettings.push_back(newEntry); - - newEntry.type = xmlAccess::DATE; - newEntry.position = 5; - newEntry.width = 113; - defaultColumnSettings.push_back(newEntry); - - newEntry.type = xmlAccess::EXTENSION; - newEntry.visible = false; - newEntry.position = 6; - newEntry.width = 60; - defaultColumnSettings.push_back(newEntry); - - return defaultColumnSettings; -} - - -xmlAccess::ColumnAttributes CustomGridRim::getColumnAttributes() -{ - std::sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility); - - xmlAccess::ColumnAttributes output; - xmlAccess::ColumnAttrib newEntry; - for (size_t i = 0; i < columnSettings.size(); ++i) - { - newEntry = columnSettings[i]; - if (newEntry.visible) - newEntry.width = GetColSize(static_cast<int>(i)); //hidden columns are sorted to the end of vector! - output.push_back(newEntry); - } - - return output; -} - - -void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) -{ - //remove special alignment for column "size" - if (GetLayoutDirection() != wxLayout_RightToLeft) //don't change for RTL languages - for (int i = 0; i < GetNumberCols(); ++i) - if (getTypeAtPos(i) == xmlAccess::SIZE) - { - wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i); - cellAttributes->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTRE); - SetColAttr(i, cellAttributes); - break; - } - //---------------------------------------------------------------------------------- - - columnSettings.clear(); - if (attr.size() == 0) - { - //default settings: - columnSettings = getDefaultColumnAttributes(); - } - else - { - for (size_t i = 0; i < xmlAccess::COLUMN_TYPE_COUNT; ++i) - { - xmlAccess::ColumnAttrib newEntry; - - if (i < attr.size()) - newEntry = attr[i]; - else //fix corrupted data: - { - newEntry.type = static_cast<xmlAccess::ColumnTypes>(xmlAccess::COLUMN_TYPE_COUNT); //sort additional rows to the end - newEntry.visible = false; - newEntry.position = i; - newEntry.width = 100; - } - columnSettings.push_back(newEntry); - } - - std::sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByType); - for (size_t i = 0; i < xmlAccess::COLUMN_TYPE_COUNT; ++i) //just be sure that each type exists only once - columnSettings[i].type = static_cast<xmlAccess::ColumnTypes>(i); - - std::sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionOnly); - for (size_t i = 0; i < xmlAccess::COLUMN_TYPE_COUNT; ++i) //just be sure that positions are numbered correctly - columnSettings[i].position = i; - } - - std::sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility); - std::vector<xmlAccess::ColumnTypes> newPositions; - for (size_t i = 0; i < columnSettings.size() && columnSettings[i].visible; ++i) //hidden columns are sorted to the end of vector! - newPositions.push_back(columnSettings[i].type); - - //set column positions - if (getGridDataTableRim()) - getGridDataTableRim()->setupColumns(newPositions); - - //set column width (set them after setupColumns!) - 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) - if (getTypeAtPos(i) == xmlAccess::SIZE) - { - wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i); - cellAttributes->SetAlignment(wxALIGN_RIGHT, wxALIGN_CENTRE); - SetColAttr(i, cellAttributes); //make filesize right justified on grids - break; - } - - ClearSelection(); - ForceRefresh(); -} - - -xmlAccess::ColumnTypes CustomGridRim::getTypeAtPos(size_t pos) const -{ - if (getGridDataTableRim()) - return getGridDataTableRim()->getTypeAtPos(pos); - else - return xmlAccess::DIRECTORY; -} - - -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"); - } - - return wxEmptyString; //dummy -} - - -void CustomGridRim::autoSizeColumns() //performance optimized column resizer (analog to wxGrid::AutoSizeColumns() -{ - for (int col = 0; col < GetNumberCols(); ++col) - { - if (col < 0) - return; - - int rowMax = -1; - size_t lenMax = 0; - for (int row = 0; row < GetNumberRows(); ++row) - if (GetCellValue(row, col).size() > lenMax) - { - lenMax = GetCellValue(row, col).size(); - rowMax = row; - } - - wxCoord extentMax = 0; - - //calculate width of (most likely) widest cell - wxClientDC dc(GetGridWindow()); - if (rowMax > -1) - { - wxGridCellAttr* attr = GetCellAttr(rowMax, col); - if (attr) - { - wxGridCellRenderer* renderer = attr->GetRenderer(this, rowMax, col); - if (renderer) - { - const wxSize size = renderer->GetBestSize(*this, *attr, dc, rowMax, col); - extentMax = std::max(extentMax, size.x); - renderer->DecRef(); - } - attr->DecRef(); - } - } - - //consider column label - dc.SetFont(GetLabelFont()); - wxCoord w = 0; - wxCoord h = 0; - dc.GetMultiLineTextExtent(GetColLabelValue(col), &w, &h ); - if (GetColLabelTextOrientation() == wxVERTICAL) - w = h; - extentMax = std::max(extentMax, w); - - extentMax += 15; //leave some space around text - - SetColSize(col, extentMax); - - } - Refresh(); -} - - -void CustomGridRim::enableFileIcons(const std::shared_ptr<IconBuffer>& iconBuffer) -{ - iconBuffer_ = iconBuffer; - SetDefaultRenderer(new GridCellRenderer(failedLoads, getGridDataTableRim(), iconBuffer)); //SetDefaultRenderer takes ownership! -} - - -std::pair<CustomGridRim::RowBegin, CustomGridRim::RowEnd> CustomGridRim::getVisibleRows() -{ - int dummy = -1; - int height = -1; - GetGridWindow()->GetClientSize(&dummy, &height); - - if (height >= 0) - { - const int rowTop = mousePosToCell(wxPoint(0, 0)).first; - int rowEnd = mousePosToCell(wxPoint(0, height)).first; - if (rowEnd == -1) //when scrolling to the very end, there are a few border pixels that do not belong to any row - rowEnd = GetNumberRows(); - else - ++rowEnd; - - if (0 <= rowTop && rowTop <= rowEnd) - return std::make_pair(rowTop, rowEnd); //"top" means here top of the screen => smaller value - } - return std::make_pair(0, 0); -} - - -inline -CustomGridTableRim* CustomGridRim::getGridDataTableRim() const -{ - return dynamic_cast<CustomGridTableRim*>(getGridDataTable()); //I'm tempted to use a static cast here... -} - - -void CustomGridRim::getIconsToBeLoaded(std::vector<Zstring>& newLoad) //loads all (not yet) drawn icons -{ - //don't check too often! give worker thread some time to fetch data - - newLoad.clear(); - - if (iconBuffer_.get()) - { - const CustomGridTableRim* gridDataTable = getGridDataTableRim(); - if (!gridDataTable) return; - - const int totalCols = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberCols(); - const int totalRows = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberRows(); - - //determine column - const int colFilename = [&]() -> int - { - for (int k = 0; k < totalCols; ++k) - if (gridDataTable->getTypeAtPos(k) == xmlAccess::FILENAME) - return k; - return -1; - }(); - if (colFilename < 0) - return; - - const auto rowsOnScreen = getVisibleRows(); - - //loop over all visible rows - const int firstRow = static_cast<int>(rowsOnScreen.first); - const int rowNo = std::min(static_cast<int>(rowsOnScreen.second), totalRows) - firstRow; - - for (int i = 0; i < rowNo; ++i) - { - //alternate when adding rows: first, last, first + 1, last - 1 ... -> Icon buffer will then load reversely, i.e. from inside out - const int currentRow = firstRow + (i % 2 == 0 ? - i / 2 : - rowNo - 1 - (i - 1) / 2); - - if (failedLoads.find(currentRow) != failedLoads.end()) //find failed attempts to load icon - { - const Zstring fileName = gridDataTable->getIconFile(currentRow); - if (!fileName.empty()) - { - //test if they are already loaded in buffer: - if (iconBuffer_->requestFileIcon(fileName)) - { - //exists in buffer: refresh Row - RefreshCell(currentRow, colFilename); //do a *full* refresh for *every* failed load to update partial DC updates while scrolling - failedLoads.erase(currentRow); // - } - else //not yet in buffer: mark for async. loading - { - newLoad.push_back(fileName); - } - } - } - } - } -} - -//---------------------------------------------------------------------------------------- - - -//update file icons periodically: use SINGLE instance to coordinate left and right grid at once -IconUpdater::IconUpdater(CustomGridLeft* leftGrid, CustomGridRight* rightGrid) : - m_leftGrid(leftGrid), - m_rightGrid(rightGrid), - m_timer(new wxTimer) //connect timer event for async. icon loading -{ - m_timer->Connect(wxEVT_TIMER, wxEventHandler(IconUpdater::loadIconsAsynchronously), NULL, this); - m_timer->Start(50); //timer interval in ms -} - - -IconUpdater::~IconUpdater() {} - - -void IconUpdater::loadIconsAsynchronously(wxEvent& event) //loads all (not yet) drawn icons -{ - std::vector<Zstring> iconsLeft; - m_leftGrid->getIconsToBeLoaded(iconsLeft); - - std::vector<Zstring> newLoad; - m_rightGrid->getIconsToBeLoaded(newLoad); - - //merge vectors - newLoad.insert(newLoad.end(), iconsLeft.begin(), iconsLeft.end()); - - if (m_leftGrid->iconBuffer_.get()) - m_leftGrid->iconBuffer_->setWorkload(newLoad); - - //event.Skip(); -} - -//---------------------------------------------------------------------------------------- - - -CustomGridLeft::CustomGridLeft(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name) -{ - GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridLeft::OnMouseMovement), NULL, this); //row-based tooltip -} - - -bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) -{ - //use custom wxGridTableBase class for management of large sets of formatted data. - //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default. - SetTable(new CustomGridTableLeft, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor - return true; -} - - -void CustomGridLeft::initSettings(CustomGridLeft* gridLeft, //create connection with zen::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const zen::GridView* gridDataView) -{ - //set underlying grid data - assert(getGridDataTable()); - getGridDataTable()->setGridDataTable(gridDataView); - - CustomGridRim::setOtherGrid(gridRight); - - CustomGridRim::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); -} - - -void CustomGridLeft::OnMouseMovement(wxMouseEvent& event) -{ - CustomGridRim::setTooltip<LEFT_SIDE>(event); - event.Skip(); -} - - -CustomGridTable* CustomGridLeft::getGridDataTable() const -{ - return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! -} - - -//---------------------------------------------------------------------------------------- -CustomGridRight::CustomGridRight(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name) -{ - GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridRight::OnMouseMovement), NULL, this); //row-based tooltip -} - - -bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) -{ - SetTable(new CustomGridTableRight, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor - return true; -} - - -void CustomGridRight::initSettings(CustomGridLeft* gridLeft, //create connection with zen::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const zen::GridView* gridDataView) -{ - //set underlying grid data - assert(getGridDataTable()); - getGridDataTable()->setGridDataTable(gridDataView); - - CustomGridRim::setOtherGrid(gridLeft); - - CustomGridRim::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); -} - - -void CustomGridRight::OnMouseMovement(wxMouseEvent& event) -{ - CustomGridRim::setTooltip<RIGHT_SIDE>(event); - event.Skip(); -} - - -CustomGridTable* CustomGridRight::getGridDataTable() const -{ - return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! -} - - -//---------------------------------------------------------------------------------------- -class GridCellRendererMiddle : public wxGridCellStringRenderer -{ -public: - GridCellRendererMiddle(const CustomGridMiddle& middleGrid) : m_gridMiddle(middleGrid) {}; - - virtual void Draw(wxGrid& grid, - wxGridCellAttr& attr, - wxDC& dc, - const wxRect& rect, - int row, int col, - bool isSelected); - -private: - const CustomGridMiddle& m_gridMiddle; -}; - - -//define new event types -const wxEventType FFS_CHECK_ROWS_EVENT = wxNewEventType(); //attention! do NOT place in header to keep (generated) id unique! -const wxEventType FFS_SYNC_DIRECTION_EVENT = wxNewEventType(); - -const int CHECK_BOX_IMAGE = 11; //width of checkbox image -const int CHECK_BOX_WIDTH = CHECK_BOX_IMAGE + 3; //width of first block - -// cell: -// ---------------------------------- -// | checkbox | left | middle | right| -// ---------------------------------- - - -CustomGridMiddle::CustomGridMiddle(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) : - CustomGrid(parent, id, pos, size, style, name), - selectionRowBegin(-1), - selectionPos(BLOCKPOS_CHECK_BOX), - highlightedRow(-1), - highlightedPos(BLOCKPOS_CHECK_BOX) -{ - SetLayoutDirection(wxLayout_LeftToRight); // - GetGridWindow ()->SetLayoutDirection(wxLayout_LeftToRight); //avoid mirroring this dialog in RTL languages like Hebrew or Arabic - GetGridColLabelWindow()->SetLayoutDirection(wxLayout_LeftToRight); // - - //connect events for dynamic selection of sync direction - GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridMiddle::OnMouseMovement), NULL, this); - GetGridWindow()->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(CustomGridMiddle::OnLeaveWindow), NULL, this); - GetGridWindow()->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseUp), NULL, this); - GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseDown), NULL, this); -} - - -CustomGridMiddle::~CustomGridMiddle() {} - - -bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) -{ - SetTable(new CustomGridTableMiddle, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor - - //display checkboxes (representing bool values) if row is enabled for synchronization - SetDefaultRenderer(new GridCellRendererMiddle(*this)); //SetDefaultRenderer takes ownership! - - return true; -} - - -void CustomGridMiddle::initSettings(CustomGridLeft* gridLeft, //create connection with zen::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const zen::GridView* gridDataView) -{ - //set underlying grid data - assert(getGridDataTable()); - getGridDataTable()->setGridDataTable(gridDataView); - -#ifdef FFS_LINUX //get rid of scrollbars; Linux: change policy for GtkScrolledWindow - GtkWidget* gridWidget = wxWindow::m_widget; - GtkScrolledWindow* scrolledWindow = GTK_SCROLLED_WINDOW(gridWidget); - gtk_scrolled_window_set_policy(scrolledWindow, GTK_POLICY_NEVER, GTK_POLICY_NEVER); -#endif - - CustomGrid::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); -} - - -CustomGridTable* CustomGridMiddle::getGridDataTable() const -{ - return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! -} - - -inline -CustomGridTableMiddle* CustomGridMiddle::getGridDataTableMiddle() const -{ - return static_cast<CustomGridTableMiddle*>(getGridDataTable()); -} - - -#ifdef FFS_WIN //get rid of scrollbars; Windows: overwrite virtual method -void CustomGridMiddle::SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh) -{ - wxWindow::SetScrollbar(orientation, 0, 0, 0, refresh); -} -#endif - - -void CustomGridMiddle::OnMouseMovement(wxMouseEvent& event) -{ - const int rowOld = highlightedRow; - const BlockPosition posOld = highlightedPos; - - - if (selectionRowBegin == -1) //change highlightning only if currently not dragging mouse - { - highlightedRow = mousePosToRow(event.GetPosition(), &highlightedPos); - - if (rowOld != highlightedRow) - { - RefreshCell(highlightedRow, 0); - RefreshCell(rowOld, 0); - } - else if (posOld != highlightedPos) - RefreshCell(highlightedRow, 0); - - //handle tooltip - showToolTip(highlightedRow, GetGridWindow()->ClientToScreen(event.GetPosition())); - } - - event.Skip(); -} - - -void CustomGridMiddle::OnLeaveWindow(wxMouseEvent& event) -{ - highlightedRow = -1; - highlightedPos = BLOCKPOS_CHECK_BOX; - Refresh(); - - //handle tooltip - toolTip.hide(); -} - - -void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) -{ - if (!getGridDataTableMiddle()) - return; - - const FileSystemObject* const fsObj = getGridDataTableMiddle()->getRawData(rowNumber); - if (fsObj == NULL) //if invalid row... - { - toolTip.hide(); - return; - } - - if (getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview - { - const wchar_t* imageName = [&]() -> const wchar_t* - { - const SyncOperation syncOp = fsObj->getSyncOperation(); - switch (syncOp) - { - case SO_CREATE_NEW_LEFT: - return L"createLeft"; - case SO_CREATE_NEW_RIGHT: - return L"createRight"; - case SO_DELETE_LEFT: - return L"deleteLeft"; - case SO_DELETE_RIGHT: - return L"deleteRight"; - case SO_MOVE_LEFT_SOURCE: - return L"moveLeftSource"; - case SO_MOVE_LEFT_TARGET: - return L"moveLeftTarget"; - case SO_MOVE_RIGHT_SOURCE: - return L"moveRightSource"; - case SO_MOVE_RIGHT_TARGET: - return L"moveRightTarget"; - case SO_OVERWRITE_LEFT: - return L"updateLeft"; - case SO_COPY_METADATA_TO_LEFT: - return L"moveLeft"; - case SO_OVERWRITE_RIGHT: - return L"updateRight"; - case SO_COPY_METADATA_TO_RIGHT: - return L"moveRight"; - case SO_DO_NOTHING: - return L"none"; - case SO_EQUAL: - return L"equal"; - case SO_UNRESOLVED_CONFLICT: - return L"conflict"; - }; - assert(false); - return L""; - }(); - - toolTip.show(getSyncOpDescription(*fsObj), pos, &GlobalResources::getImage(imageName)); - } - else - { - const wchar_t* imageName = [&]() -> const wchar_t* - { - const CompareFilesResult cmpRes = fsObj->getCategory(); - switch (cmpRes) - { - case FILE_LEFT_SIDE_ONLY: - return L"leftOnly"; - case FILE_RIGHT_SIDE_ONLY: - return L"rightOnly"; - case FILE_LEFT_NEWER: - return L"leftNewer"; - case FILE_RIGHT_NEWER: - return L"rightNewer"; - case FILE_DIFFERENT: - return L"different"; - case FILE_EQUAL: - return L"equal"; - case FILE_DIFFERENT_METADATA: - return L"conflict"; - case FILE_CONFLICT: - return L"conflict"; - } - assert(false); - return L""; - }(); - - toolTip.show(getCategoryDescription(*fsObj), pos, &GlobalResources::getImage(imageName)); - } -} - - -void CustomGridMiddle::OnLeftMouseDown(wxMouseEvent& event) -{ - selectionRowBegin = mousePosToRow(event.GetPosition(), &selectionPos); - event.Skip(); -} - - -void CustomGridMiddle::OnLeftMouseUp(wxMouseEvent& event) -{ - //int selRowEnd = mousePosToCell(event.GetPosition()).first; - //-> use visibly marked rows instead! with wxWidgets 2.8.12 there is no other way than IsInSelection() - int selRowEnd = -1; - if (0 <= selectionRowBegin && selectionRowBegin < GetNumberRows()) - { - for (int i = selectionRowBegin; i < GetNumberRows() && IsInSelection(i, 0); ++i) - selRowEnd = i; - - if (selRowEnd == selectionRowBegin) - for (int i = selectionRowBegin; i >= 0 && IsInSelection(i, 0); --i) - selRowEnd = i; - } - - if (0 <= selectionRowBegin && 0 <= selRowEnd) - { - switch (selectionPos) - { - case BLOCKPOS_CHECK_BOX: - { - //create a custom event - FFSCheckRowsEvent evt(selectionRowBegin, selRowEnd); - AddPendingEvent(evt); - } - break; - case BLOCKPOS_LEFT: - { - //create a custom event - FFSSyncDirectionEvent evt(selectionRowBegin, selRowEnd, SYNC_DIR_LEFT); - AddPendingEvent(evt); - } - break; - case BLOCKPOS_MIDDLE: - { - //create a custom event - FFSSyncDirectionEvent evt(selectionRowBegin, selRowEnd, SYNC_DIR_NONE); - AddPendingEvent(evt); - } - break; - case BLOCKPOS_RIGHT: - { - //create a custom event - FFSSyncDirectionEvent evt(selectionRowBegin, selRowEnd, SYNC_DIR_RIGHT); - AddPendingEvent(evt); - } - break; - } - } - selectionRowBegin = -1; - selectionPos = BLOCKPOS_CHECK_BOX; - - ClearSelection(); - event.Skip(); -} - - -int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) -{ - if (!getGridDataTableMiddle()) - return 0; - - int row = -1; - int x = -1; - int y = -1; - CalcUnscrolledPosition( pos.x, pos.y, &x, &y ); - if (x >= 0 && y >= 0) - { - row = YToRow(y); - - //determine blockposition within cell (optional) - if (block) - { - *block = BLOCKPOS_CHECK_BOX; //default - - if (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 - { - // cell: - // ---------------------------------- - // | checkbox | left | middle | right| - // ---------------------------------- - - const wxRect rect = CellToRect(row, 0); - if (rect.GetWidth() > CHECK_BOX_WIDTH) - { - const double blockWidth = (rect.GetWidth() - CHECK_BOX_WIDTH) / 3.0; - if (rect.GetX() + CHECK_BOX_WIDTH <= x && x < rect.GetX() + rect.GetWidth()) - { - if (x - (rect.GetX() + CHECK_BOX_WIDTH) < blockWidth) - *block = BLOCKPOS_LEFT; - else if (x - (rect.GetX() + CHECK_BOX_WIDTH) < 2 * blockWidth) - *block = BLOCKPOS_MIDDLE; - else - *block = BLOCKPOS_RIGHT; - } - } - } - } - } - } - return row; -} - - -void CustomGridMiddle::enableSyncPreview(bool value) -{ - assert(getGridDataTableMiddle()); - getGridDataTableMiddle()->enableSyncPreview(value); - - if (value) - GetGridColLabelWindow()->SetToolTip(_("Synchronization Preview")); - else - GetGridColLabelWindow()->SetToolTip(_("Comparison Result")); -} - - -void GridCellRendererMiddle::Draw(wxGrid& grid, - wxGridCellAttr& attr, - wxDC& dc, - const wxRect& rect, - int row, int col, - bool isSelected) -{ - //retrieve grid data - const FileSystemObject* const fsObj = m_gridMiddle.getGridDataTableMiddle() ? m_gridMiddle.getGridDataTableMiddle()->getRawData(row) : NULL; - if (fsObj != NULL) //if valid row... - { - if (rect.GetWidth() > CHECK_BOX_WIDTH) - { - const bool rowIsHighlighted = row == m_gridMiddle.highlightedRow; - - wxRect rectShrinked(rect); - - //clean first block of rect that will receive image of checkbox - rectShrinked.SetWidth(CHECK_BOX_WIDTH); - wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected); - - //print checkbox into first block - rectShrinked.SetX(rect.GetX() + 1); - - //HIGHLIGHTNING (checkbox): - if (rowIsHighlighted && - m_gridMiddle.highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) - { - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(fsObj->isActive() ? - wxT("checkboxTrueFocus") : - wxT("checkboxFalseFocus")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - } - else //default - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(fsObj->isActive() ? - wxT("checkboxTrue") : - 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); - rectShrinked.SetX(rect.GetX() + CHECK_BOX_WIDTH); - wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected); - - //print remaining block - if (m_gridMiddle.getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview - { - //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 - - switch (m_gridMiddle.highlightedPos) - { - case CustomGridMiddle::BLOCKPOS_CHECK_BOX: - break; - case CustomGridMiddle::BLOCKPOS_LEFT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_LEFT, true)), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - break; - case CustomGridMiddle::BLOCKPOS_MIDDLE: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_NONE, true)), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case CustomGridMiddle::BLOCKPOS_RIGHT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_RIGHT, true)), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - break; - } - else //default - { - const wxBitmap& syncOpIcon = getSyncOpImage(fsObj->getSyncOperation()); - dc.DrawLabel(wxEmptyString, syncOpIcon, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - } - } - else //comparison results view - { - switch (fsObj->getCategory()) - { - case FILE_LEFT_SIDE_ONLY: - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("leftOnlySmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_RIGHT_SIDE_ONLY: - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("rightOnlySmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_LEFT_NEWER: - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("leftNewerSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_RIGHT_NEWER: - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("rightNewerSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_DIFFERENT: - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("differentSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_EQUAL: - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("equalSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - case FILE_CONFLICT: - case FILE_DIFFERENT_METADATA: - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("conflictSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - break; - } - } - - return; - } - } - - //fallback - wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); -} - - -//this method is called when grid view changes: useful for parallel updating of multiple grids -void CustomGridMiddle::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) -{ - int x = 0; - int y = 0; - GetViewStart(&x, &y); - gridLeft->Scroll(-1, y); - gridRight->Scroll(-1, y); -} - - -void CustomGridMiddle::DrawColLabel(wxDC& dc, int col) -{ - CustomGrid::DrawColLabel(dc, col); - - if (!getGridDataTableMiddle()) - return; - - const wxRect rect(GetColLeft(col), 0, GetColWidth(col), GetColLabelSize()); - - if (getGridDataTableMiddle()->syncPreviewIsActive()) - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("syncViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); - else - dc.DrawLabel(wxEmptyString, GlobalResources::getImage(wxT("cmpViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); -} - - -const wxBitmap& zen::getSyncOpImage(SyncOperation syncOp) -{ - switch (syncOp) //evaluate comparison result and sync direction - { - case SO_CREATE_NEW_LEFT: - return GlobalResources::getImage(L"createLeftSmall"); - case SO_CREATE_NEW_RIGHT: - return GlobalResources::getImage(L"createRightSmall"); - case SO_DELETE_LEFT: - return GlobalResources::getImage(L"deleteLeftSmall"); - case SO_DELETE_RIGHT: - return GlobalResources::getImage(L"deleteRightSmall"); - case SO_MOVE_LEFT_SOURCE: - return GlobalResources::getImage(L"moveLeftSourceSmall"); - case SO_MOVE_LEFT_TARGET: - return GlobalResources::getImage(L"moveLeftTargetSmall"); - case SO_MOVE_RIGHT_SOURCE: - return GlobalResources::getImage(L"moveRightSourceSmall"); - case SO_MOVE_RIGHT_TARGET: - return GlobalResources::getImage(L"moveRightTargetSmall"); - case SO_OVERWRITE_RIGHT: - return GlobalResources::getImage(L"updateRightSmall"); - case SO_COPY_METADATA_TO_RIGHT: - return GlobalResources::getImage(L"moveRightSmall"); - case SO_OVERWRITE_LEFT: - return GlobalResources::getImage(L"updateLeftSmall"); - case SO_COPY_METADATA_TO_LEFT: - return GlobalResources::getImage(L"moveLeftSmall"); - case SO_DO_NOTHING: - return GlobalResources::getImage(L"noneSmall"); - case SO_EQUAL: - return GlobalResources::getImage(L"equalSmall"); - case SO_UNRESOLVED_CONFLICT: - return GlobalResources::getImage(L"conflictSmall"); - } - - return wxNullBitmap; //dummy -} - diff --git a/lib/custom_grid.h b/lib/custom_grid.h deleted file mode 100644 index 47aad3e6..00000000 --- a/lib/custom_grid.h +++ /dev/null @@ -1,370 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** - -#ifndef CUSTOMGRID_H_INCLUDED -#define CUSTOMGRID_H_INCLUDED - -#include <vector> -#include <wx/grid.h> -#include <wx+/tooltip.h> -#include "process_xml.h" -#include <memory> -#include <set> -#include "../file_hierarchy.h" -#include "icon_buffer.h" - - -class CustomGridTable; -class CustomGridTableRim; -class CustomGridTableLeft; -class CustomGridTableRight; -class CustomGridTableMiddle; -class GridCellRendererMiddle; -class wxTimer; -class CustomGridRim; -class CustomGridLeft; -class CustomGridMiddle; -class CustomGridRight; - - -namespace zen -{ -class GridView; - -const wxBitmap& getSyncOpImage(SyncOperation syncOp); -} -//################################################################################## - -/* -class hierarchy: - CustomGrid - /|\ - ____________|____________ - | | - CustomGridRim | - /|\ | - ________|_______ | - | | | -CustomGridLeft CustomGridRight CustomGridMiddle -*/ - -class CustomGrid : public wxGrid -{ -public: - CustomGrid(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxWANTS_CHARS, - const wxString& name = wxGridNameStr); - - virtual ~CustomGrid() {} - - virtual void initSettings(CustomGridLeft* gridLeft, //create connection with zen::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const zen::GridView* gridDataView); - - void release(); //release connection to zen::GridView - - std::set<size_t> getAllSelectedRows() const; - - //set sort direction indicator on UI - typedef int SortColumn; - - //notify wxGrid that underlying table size has changed - virtual void updateGridSizes(); - - enum SortDirection - { - ASCENDING, - DESCENDING - }; - typedef std::pair<SortColumn, SortDirection> SortMarker; - void setSortMarker(SortMarker marker); - - bool isLeadGrid() const; - - void setIconManager(const std::shared_ptr<zen::IconBuffer>& iconBuffer); - -protected: - void RefreshCell(int row, int col); - virtual void DrawColLabel(wxDC& dc, int col); - std::pair<int, int> mousePosToCell(wxPoint pos); //returns (row/column) pair - - 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 adjustGridHeights(wxEvent& event); - virtual void enableFileIcons(const std::shared_ptr<zen::IconBuffer>& iconBuffer) = 0; - - CustomGrid* m_gridLeft; - CustomGrid* m_gridMiddle; - CustomGrid* m_gridRight; - - bool isLeading; //identify grid that has user focus - - SortMarker m_marker; -}; - - -class GridCellRenderer; - - -//----------------------------------------------------------- -class IconUpdater : private wxEvtHandler //update file icons periodically: use SINGLE instance to coordinate left and right grid at once -{ -public: - IconUpdater(CustomGridLeft* leftGrid, CustomGridRight* rightGrid); - ~IconUpdater(); - -private: - void loadIconsAsynchronously(wxEvent& event); //loads all (not yet) drawn icons - - CustomGridRim* m_leftGrid; - CustomGridRim* m_rightGrid; - - std::unique_ptr<wxTimer> m_timer; //user timer event to periodically update icons: better than idle event because also active when scrolling! :) -}; - - -//############## SPECIALIZATIONS ################### -class CustomGridRim : public CustomGrid -{ - friend class IconUpdater; - friend class GridCellRenderer; - -public: - CustomGridRim(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name); - - //set visibility, position and width of columns - static xmlAccess::ColumnAttributes getDefaultColumnAttributes(); - xmlAccess::ColumnAttributes getColumnAttributes(); - void setColumnAttributes(const xmlAccess::ColumnAttributes& attr); - - xmlAccess::ColumnTypes getTypeAtPos(size_t pos) const; - static wxString getTypeName(xmlAccess::ColumnTypes colType); - - void autoSizeColumns(); //performance optimized column resizer - - virtual void updateGridSizes(); - -protected: - template <zen::SelectedSide side> - void setTooltip(const wxMouseEvent& event); - - void setOtherGrid(CustomGridRim* other); //call during initialization! - -private: - CustomGridTableRim* getGridDataTableRim() const; - virtual void enableFileIcons(const std::shared_ptr<zen::IconBuffer>& iconBuffer); - - void OnResizeColumn(wxGridSizeEvent& event); - - //this method is called when grid view changes: useful for parallel updating of multiple grids - virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight); - - //asynchronous icon loading - void getIconsToBeLoaded(std::vector<Zstring>& newLoad); //loads all (not yet) drawn icons - - typedef size_t RowBegin; - typedef size_t RowEnd; - std::pair<RowBegin, RowEnd> getVisibleRows(); //return [first, last) number pair - - typedef size_t RowNumber; - typedef std::set<RowNumber> FailedIconLoad; - FailedIconLoad failedLoads; //save status of last icon load when drawing on GUI - - std::shared_ptr<zen::IconBuffer> iconBuffer_; - - xmlAccess::ColumnAttributes columnSettings; //set visibility, position and width of columns - CustomGridRim* otherGrid; //sibling grid on other side -}; - - -class CustomGridLeft : public CustomGridRim -{ -public: - CustomGridLeft(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxWANTS_CHARS, - const wxString& name = wxGridNameStr); - - virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); - - virtual void initSettings(CustomGridLeft* gridLeft, //create connection with zen::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const zen::GridView* gridDataView); - -private: - void OnMouseMovement(wxMouseEvent& event); - virtual CustomGridTable* getGridDataTable() const; -}; - - -class CustomGridRight : public CustomGridRim -{ -public: - CustomGridRight(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxWANTS_CHARS, - const wxString& name = wxGridNameStr); - - virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); - - virtual void initSettings(CustomGridLeft* gridLeft, //create connection with zen::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const zen::GridView* gridDataView); - -private: - void OnMouseMovement(wxMouseEvent& event); - virtual CustomGridTable* getGridDataTable() const; -}; - - -class CustomGridMiddle : public CustomGrid -{ - friend class GridCellRendererMiddle; - -public: - CustomGridMiddle(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxWANTS_CHARS, - const wxString& name = wxGridNameStr); - - ~CustomGridMiddle(); - - virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); - - virtual void initSettings(CustomGridLeft* gridLeft, //create connection with zen::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const zen::GridView* gridDataView); - - void enableSyncPreview(bool value); - -private: - virtual CustomGridTable* getGridDataTable() const; - CustomGridTableMiddle* getGridDataTableMiddle() const; - - virtual void enableFileIcons(const std::shared_ptr<zen::IconBuffer>& iconBuffer) {}; -#ifdef FFS_WIN //get rid of scrollbars; Windows: overwrite virtual method - virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh = true); -#endif - - //this method is called when grid view changes: useful for parallel updating of multiple grids - virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight); - - virtual void DrawColLabel(wxDC& dc, int col); - - void OnMouseMovement(wxMouseEvent& event); - void OnLeaveWindow(wxMouseEvent& event); - void OnLeftMouseDown(wxMouseEvent& event); - void OnLeftMouseUp(wxMouseEvent& event); - - void showToolTip(int rowNumber, wxPoint pos); - - //small helper methods - enum BlockPosition //each cell can be divided into four blocks concerning mouse selections - { - BLOCKPOS_CHECK_BOX, - BLOCKPOS_LEFT, - BLOCKPOS_MIDDLE, - BLOCKPOS_RIGHT - }; - int mousePosToRow(const wxPoint pos, BlockPosition* block = NULL); - - //variables for selecting sync direction - int selectionRowBegin; - BlockPosition selectionPos; - - //variables for highlightning on mouse-over - int highlightedRow; - BlockPosition highlightedPos; - - zen::Tooltip toolTip; -}; - -//custom events for middle grid: - -//-------------------------------------------------------------------------------------------- -//(UN-)CHECKING ROWS FROM SYNCHRONIZATION - -extern const wxEventType FFS_CHECK_ROWS_EVENT; //define new event type - -class FFSCheckRowsEvent : public wxCommandEvent -{ -public: - FFSCheckRowsEvent(const int from, const int to) : - wxCommandEvent(FFS_CHECK_ROWS_EVENT), - rowFrom(from), - rowTo(to) {} - - virtual wxEvent* Clone() const - { - return new FFSCheckRowsEvent(rowFrom, rowTo); - } - - const int rowFrom; - const int rowTo; -}; - -typedef void (wxEvtHandler::*FFSCheckRowsEventFunction)(FFSCheckRowsEvent&); - -#define FFSCheckRowsEventHandler(func) \ - (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(FFSCheckRowsEventFunction, &func) - -//-------------------------------------------------------------------------------------------- -//SELECTING SYNC DIRECTION - -extern const wxEventType FFS_SYNC_DIRECTION_EVENT; //define new event type - -class FFSSyncDirectionEvent : public wxCommandEvent -{ -public: - FFSSyncDirectionEvent(const int from, const int to, const zen::SyncDirection dir) : - wxCommandEvent(FFS_SYNC_DIRECTION_EVENT), - rowFrom(from), - rowTo(to), - direction(dir) {} - - virtual wxEvent* Clone() const - { - return new FFSSyncDirectionEvent(rowFrom, rowTo, direction); - } - - const int rowFrom; - const int rowTo; - const zen::SyncDirection direction; -}; - -typedef void (wxEvtHandler::*FFSSyncDirectionEventFunction)(FFSSyncDirectionEvent&); - -#define FFSSyncDirectionEventHandler(func) \ - (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(FFSSyncDirectionEventFunction, &func) - - -#endif // CUSTOMGRID_H_INCLUDED diff --git a/lib/db_file.cpp b/lib/db_file.cpp index 51333687..2d02d634 100644 --- a/lib/db_file.cpp +++ b/lib/db_file.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "db_file.h" @@ -48,7 +48,7 @@ Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false) //Linux and Windows builds are binary incompatible: different file id?, problem with case sensitivity? //however 32 and 64 bit db files *are* designed to be binary compatible! //Give db files different names. - //make sure they end with ".ffs_db". These files will not be included into comparison + //make sure they end with ".ffs_db". These files will not be included into comparison #ifdef FFS_WIN Zstring dbname = Zstring(Zstr("sync")) + (tempfile ? Zstr(".tmp") : Zstr("")) + SYNC_DB_FILE_ENDING; #elif defined FFS_LINUX diff --git a/lib/db_file.h b/lib/db_file.h index 0413c404..e5ae7b50 100644 --- a/lib/db_file.h +++ b/lib/db_file.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef DBFILE_H_INCLUDED diff --git a/lib/dir_exist_async.h b/lib/dir_exist_async.h index f59e9490..f3826eb3 100644 --- a/lib/dir_exist_async.h +++ b/lib/dir_exist_async.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef DIR_EXIST_HEADER_08173281673432158067342132467183267 diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp index 9ca76310..88fb19b3 100644 --- a/lib/dir_lock.cpp +++ b/lib/dir_lock.cpp @@ -1,3 +1,8 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * +// ************************************************************************** #include "dir_lock.h" #include <utility> #include <wx/utils.h> diff --git a/lib/dir_lock.h b/lib/dir_lock.h index c9a16c62..9938d554 100644 --- a/lib/dir_lock.h +++ b/lib/dir_lock.h @@ -1,3 +1,8 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * +// ************************************************************************** #ifndef DIR_LOCK_H_INCLUDED #define DIR_LOCK_H_INCLUDED diff --git a/lib/error_log.cpp b/lib/error_log.cpp index 67584dea..a71e72e1 100644 --- a/lib/error_log.cpp +++ b/lib/error_log.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "error_log.h" diff --git a/lib/error_log.h b/lib/error_log.h index a0b7ab90..62aac70f 100644 --- a/lib/error_log.h +++ b/lib/error_log.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef ERRORLOGGING_H_INCLUDED diff --git a/lib/ffs_paths.h b/lib/ffs_paths.h index 0ad02b15..ac032e6b 100644 --- a/lib/ffs_paths.h +++ b/lib/ffs_paths.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef STANDARDPATHS_H_INCLUDED diff --git a/lib/hard_filter.cpp b/lib/hard_filter.cpp index ee744337..fcef6a9f 100644 --- a/lib/hard_filter.cpp +++ b/lib/hard_filter.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "hard_filter.h" diff --git a/lib/hard_filter.h b/lib/hard_filter.h index e128a9df..476f5ac1 100644 --- a/lib/hard_filter.h +++ b/lib/hard_filter.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef FFS_FILTER_H_INCLUDED diff --git a/lib/help_provider.h b/lib/help_provider.h index 094084b2..213c05e3 100644 --- a/lib/help_provider.h +++ b/lib/help_provider.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef HELPPROVIDER_H_INCLUDED diff --git a/lib/icon_buffer.cpp b/lib/icon_buffer.cpp index 4e05e642..647228e3 100644 --- a/lib/icon_buffer.cpp +++ b/lib/icon_buffer.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "icon_buffer.h" @@ -522,7 +522,7 @@ void WorkerThread::operator()() //thread entry ZEN_ON_BLOCK_EXIT(::CoUninitialize()); //2. Initialize system image list - typedef BOOL (WINAPI *FileIconInitFun)(BOOL fRestoreCache); + typedef BOOL (WINAPI* FileIconInitFun)(BOOL fRestoreCache); const SysDllFun<FileIconInitFun> fileIconInit(L"Shell32.dll", reinterpret_cast<LPCSTR>(660)); assert(fileIconInit); if (fileIconInit) diff --git a/lib/icon_buffer.h b/lib/icon_buffer.h index a13ad3cd..3f77a520 100644 --- a/lib/icon_buffer.h +++ b/lib/icon_buffer.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef ICONBUFFER_H_INCLUDED diff --git a/lib/localization.cpp b/lib/localization.cpp index 8084eb42..e8867129 100644 --- a/lib/localization.cpp +++ b/lib/localization.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "localization.h" @@ -32,7 +32,7 @@ namespace class FFSLocale : public TranslationHandler { public: - FFSLocale(const wxString& filename, wxLanguage languageId); //throw (lngfile::ParsingError, PluralForm::ParsingError) + FFSLocale(const wxString& filename, wxLanguage languageId); //throw lngfile::ParsingError, PluralForm::ParsingError wxLanguage langId() const { return langId_; } @@ -71,7 +71,7 @@ private: -FFSLocale::FFSLocale(const wxString& filename, wxLanguage languageId) : langId_(languageId) //throw (lngfile::ParsingError, PluralForm::ParsingError) +FFSLocale::FFSLocale(const wxString& filename, wxLanguage languageId) : langId_(languageId) //throw lngfile::ParsingError, PluralForm::ParsingError { std::string inputStream; try @@ -111,7 +111,7 @@ FFSLocale::FFSLocale(const wxString& filename, wxLanguage languageId) : langId_( transMappingPl.insert(std::make_pair(std::make_pair(singular, plural), plFormsWide)); } - pluralParser.reset(new PluralForm(header.pluralDefinition.c_str())); //throw PluralForm::ParsingError + pluralParser.reset(new PluralForm(copyStringTo<Wstring>(header.pluralDefinition))); //throw PluralForm::ParsingError } } @@ -205,7 +205,7 @@ ExistingTranslations::ExistingTranslations() locMapping.push_back(newEntry); } } - catch (lngfile::ParsingError&) {} + catch (lngfile::ParsingError&) {} //better not show an error message here; scenario: batch jobs } catch (...) {} @@ -388,7 +388,7 @@ void zen::setLanguage(int language) { try { - zen::setTranslator(new FFSLocale(languageFile, static_cast<wxLanguage>(language))); //throw (lngfile::ParsingError, PluralForm::ParsingError) + zen::setTranslator(new FFSLocale(languageFile, static_cast<wxLanguage>(language))); //throw lngfile::ParsingError, PluralForm::ParsingError } catch (lngfile::ParsingError& e) { diff --git a/lib/localization.h b/lib/localization.h index 438ad445..7c30ab74 100644 --- a/lib/localization.h +++ b/lib/localization.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef MISC_H_INCLUDED diff --git a/lib/norm_filter.h b/lib/norm_filter.h index d95fbe35..a47fd910 100644 --- a/lib/norm_filter.h +++ b/lib/norm_filter.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef NORM_FILTER_H_INCLUDED diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp index a98623cf..774cbeb7 100644 --- a/lib/parallel_scan.cpp +++ b/lib/parallel_scan.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "parallel_scan.h" diff --git a/lib/parallel_scan.h b/lib/parallel_scan.h index 99424b2a..836892ad 100644 --- a/lib/parallel_scan.h +++ b/lib/parallel_scan.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef PARALLEL_SCAN_H_INCLUDED @@ -59,7 +59,7 @@ public: TRAV_ERROR_RETRY, TRAV_ERROR_IGNORE }; - virtual HandleError reportError (const std::wstring& errorText) = 0; //may throw! + virtual HandleError reportError (const std::wstring& errorText) = 0; //may throw! virtual void reportStatus(const std::wstring& statusMsg, int itemTotal) = 0; // }; diff --git a/lib/parse_lng.h b/lib/parse_lng.h index 811a3181..e876c5a9 100644 --- a/lib/parse_lng.h +++ b/lib/parse_lng.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef PARSE_LNG_HEADER_INCLUDED diff --git a/lib/parse_plural.h b/lib/parse_plural.h index c4466320..297aaafc 100644 --- a/lib/parse_plural.h +++ b/lib/parse_plural.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef PARSE_PLURAL_H_INCLUDED diff --git a/lib/process_xml.cpp b/lib/process_xml.cpp index ef324246..4ee215b9 100644 --- a/lib/process_xml.cpp +++ b/lib/process_xml.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "process_xml.h" @@ -71,7 +71,6 @@ void setXmlType(XmlDoc& doc, XmlType type) //throw() } //################################################################################################################ - wxString xmlAccess::getGlobalConfigFile() { return toWx(zen::getConfigDir()) + wxT("GlobalSettings.xml"); @@ -539,15 +538,29 @@ bool readText(const std::string& input, UnitTime& value) template <> inline -void writeText(const ColumnTypes& value, std::string& output) +void writeText(const ColumnTypeRim& value, std::string& output) { output = toString<std::string>(value); } template <> inline -bool readText(const std::string& input, ColumnTypes& value) +bool readText(const std::string& input, ColumnTypeRim& value) { - value = static_cast<ColumnTypes>(toNumber<int>(input)); + value = static_cast<ColumnTypeRim>(toNumber<int>(input)); + return true; +} + + +template <> inline +void writeText(const ColumnTypeNavi& value, std::string& output) +{ + output = toString<std::string>(value); +} + +template <> inline +bool readText(const std::string& input, ColumnTypeNavi& value) +{ + value = static_cast<ColumnTypeNavi>(toNumber<int>(input)); return true; } @@ -631,23 +644,42 @@ bool readText(const std::string& input, DirectionConfig::Variant& value) template <> inline -bool readValue(const XmlElement& input, ColumnAttrib& value) +bool readValue(const XmlElement& input, ColumnAttributeRim& value) +{ + XmlIn in(input); + bool rv1 = in.attribute("Type", value.type_); + bool rv2 = in.attribute("Visible", value.visible_); + bool rv3 = in.attribute("Width", value.width_); + return rv1 && rv2 && rv3; +} + +template <> inline +void writeValue(const ColumnAttributeRim& value, XmlElement& output) +{ + XmlOut out(output); + out.attribute("Type", value.type_); + out.attribute("Visible", value.visible_); + out.attribute("Width", value.width_); +} + + +template <> inline +bool readValue(const XmlElement& input, ColumnAttributeNavi& value) { XmlIn in(input); - bool rv1 = in.attribute("Type", value.type); - bool rv2 = in.attribute("Visible", value.visible); - bool rv3 = in.attribute("Width", value.width); - value.position = 0; + bool rv1 = in.attribute("Type", value.type_); + bool rv2 = in.attribute("Visible", value.visible_); + bool rv3 = in.attribute("Width", value.width_); return rv1 && rv2 && rv3; } template <> inline -void writeValue(const ColumnAttrib& value, XmlElement& output) +void writeValue(const ColumnAttributeNavi& value, XmlElement& output) { XmlOut out(output); - out.attribute("Type", value.type); - out.attribute("Visible", value.visible); - out.attribute("Width", value.width); + out.attribute("Type", value.type_); + out.attribute("Visible", value.visible_); + out.attribute("Width", value.width_); } } @@ -791,16 +823,7 @@ void readConfig(const XmlIn& in, xmlAccess::XmlBatchConfig& config) //read GUI specific config data XmlIn inBatchCfg = in["BatchConfig"]; - //----------------------------------------------------------------------------- - if (inBatchCfg["Silent"]) - { - inBatchCfg["Silent"](config.showProgress); - config.showProgress = !config.showProgress; - } - else - //----------------------------------------------------------------------------- - - inBatchCfg["ShowProgress" ](config.showProgress); + inBatchCfg["ShowProgress" ](config.showProgress); inBatchCfg["LogfileDirectory"](config.logFileDirectory); inBatchCfg["LogfileCountMax" ](config.logFileCountMax); inBatchCfg["HandleError" ](config.handleError); @@ -845,12 +868,6 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) inWnd.attribute("PosY", config.gui.dlgPos.y); inWnd.attribute("Maximized", config.gui.isMaximized); - // inWnd["Width" ](config.gui.dlgSize.x); - // inWnd["Height" ](config.gui.dlgSize.y); - // inWnd["PosX" ](config.gui.dlgPos.x); - // inWnd["PosY" ](config.gui.dlgPos.y); - // inWnd["Maximized"](config.gui.isMaximized); - inWnd["MaxFolderPairsVisible"](config.gui.maxFolderPairsVisible); inWnd["ManualDeletionOnBothSides"](config.gui.deleteOnBothSides); @@ -861,22 +878,21 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) //########################################################### //read column attributes - XmlIn inColLeft = inWnd["LeftColumns"]; - inColLeft.attribute("AutoAdjust", config.gui.autoAdjustColumnsLeft); + XmlIn inColNavi = inWnd["CompressedView"]; + inColNavi(config.gui.columnAttribNavi); - inColLeft(config.gui.columnAttribLeft); - for (size_t i = 0; i < config.gui.columnAttribLeft.size(); ++i) - config.gui.columnAttribLeft[i].position = i; + inColNavi.attribute("ShowPercentage", config.gui.showPercentBar); + inColNavi.attribute("SortByColumn", config.gui.naviLastSortColumn); + inColNavi.attribute("SortAscending", config.gui.naviLastSortAscending); - //########################################################### - XmlIn inColRight = inWnd["RightColumns"]; - inColRight.attribute("AutoAdjust", config.gui.autoAdjustColumnsRight); + XmlIn inColLeft = inWnd["ColumnsLeft"]; + inColLeft(config.gui.columnAttribLeft); + XmlIn inColRight = inWnd["ColumnsRight"]; inColRight(config.gui.columnAttribRight); - for (size_t i = 0; i < config.gui.columnAttribRight.size(); ++i) - config.gui.columnAttribRight[i].position = i; + //########################################################### - inWnd["Perspective" ](config.gui.guiPerspectiveLast); + inWnd["Layout"](config.gui.guiPerspectiveLast); inGui["FolderHistoryLeft" ](config.gui.folderHistoryLeft); inGui["FolderHistoryRight"](config.gui.folderHistoryRight); @@ -1126,18 +1142,22 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out) outWnd["IconSize"](config.gui.iconSize); //########################################################### - //write column attributes - XmlOut outColLeft = outWnd["LeftColumns"]; - outColLeft.attribute("AutoAdjust", config.gui.autoAdjustColumnsLeft); + XmlOut outColNavi = outWnd["CompressedView"]; + outColNavi(config.gui.columnAttribNavi); + + outColNavi.attribute("ShowPercentage", config.gui.showPercentBar); + outColNavi.attribute("SortByColumn", config.gui.naviLastSortColumn); + outColNavi.attribute("SortAscending", config.gui.naviLastSortAscending); + + XmlOut outColLeft = outWnd["ColumnsLeft"]; outColLeft(config.gui.columnAttribLeft); - //########################################################### - XmlOut outColRight = outWnd["RightColumns"]; - outColRight.attribute("AutoAdjust", config.gui.autoAdjustColumnsRight); + XmlOut outColRight = outWnd["ColumnsRight"]; outColRight(config.gui.columnAttribRight); + //########################################################### - outWnd["Perspective" ](config.gui.guiPerspectiveLast); + outWnd["Layout"](config.gui.guiPerspectiveLast); outGui["FolderHistoryLeft" ](config.gui.folderHistoryLeft); outGui["FolderHistoryRight"](config.gui.folderHistoryRight); diff --git a/lib/process_xml.h b/lib/process_xml.h index d8ca7e54..5abbfdc9 100644 --- a/lib/process_xml.h +++ b/lib/process_xml.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef PROCESSXML_H_INCLUDED @@ -11,6 +11,7 @@ #include "../structures.h" #include "xml_base.h" #include "localization.h" +#include "../ui/column_attr.h" namespace xmlAccess { @@ -38,28 +39,6 @@ enum OnGuiError ON_GUIERROR_IGNORE }; -enum ColumnTypes -{ - DIRECTORY, //this needs to begin with 0 and be continuous (some code relies on it) - FULL_PATH, - REL_PATH, - FILENAME, - SIZE, - DATE, - EXTENSION -}; -const size_t COLUMN_TYPE_COUNT = 7; - -struct ColumnAttrib -{ - ColumnTypes type; - bool visible; - size_t position; - int width; -}; -typedef std::vector<ColumnAttrib> ColumnAttributes; - - typedef wxString Description; typedef wxString Commandline; typedef std::vector<std::pair<Description, Commandline> > ExternalApps; @@ -167,8 +146,12 @@ struct XmlGlobalSettings dlgSize(wxDefaultCoord, wxDefaultCoord), isMaximized(false), maxFolderPairsVisible(6), - autoAdjustColumnsLeft(false), - autoAdjustColumnsRight(false), + columnAttribNavi (zen::getDefaultColumnAttributesNavi()), + columnAttribLeft (zen::getDefaultColumnAttributesLeft()), + columnAttribRight(zen::getDefaultColumnAttributesRight()), + naviLastSortColumn(zen::defaultValueLastSortColumn), + naviLastSortAscending(zen::defaultValueLastSortAscending), + showPercentBar(zen::defaultValueShowPercentage), folderHistMax(15), onCompletionHistoryMax(8), deleteOnBothSides(false), @@ -201,11 +184,14 @@ struct XmlGlobalSettings int maxFolderPairsVisible; - ColumnAttributes columnAttribLeft; - ColumnAttributes columnAttribRight; + std::vector<zen::ColumnAttributeNavi> columnAttribNavi; //compressed view/navigation + std::vector<zen::ColumnAttributeRim> columnAttribLeft; + std::vector<zen::ColumnAttributeRim> columnAttribRight; + + zen::ColumnTypeNavi naviLastSortColumn; //remember sort on navigation panel + bool naviLastSortAscending; // - bool autoAdjustColumnsLeft; - bool autoAdjustColumnsRight; + bool showPercentBar; //in navigation panel ExternalApps externelApplications; @@ -234,31 +220,6 @@ struct XmlGlobalSettings //struct Batch }; - -inline -bool sortByType(const ColumnAttrib& a, const ColumnAttrib& b) -{ - return a.type < b.type; -} - - -inline -bool sortByPositionOnly(const ColumnAttrib& a, const ColumnAttrib& b) -{ - return a.position < b.position; -} - - -inline -bool sortByPositionAndVisibility(const ColumnAttrib& a, const ColumnAttrib& b) -{ - if (a.visible == false) //hidden elements shall appear at end of vector - return false; - if (b.visible == false) - return true; - return a.position < b.position; -} - void readConfig(const wxString& filename, XmlGuiConfig& config); //throw xmlAccess::FfsXmlError void readConfig(const wxString& filename, XmlBatchConfig& config); //throw xmlAccess::FfsXmlError void readConfig( XmlGlobalSettings& config); //throw xmlAccess::FfsXmlError diff --git a/lib/recycler.cpp b/lib/recycler.cpp index abe63a3e..11ed77f7 100644 --- a/lib/recycler.cpp +++ b/lib/recycler.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "recycler.h" diff --git a/lib/recycler.h b/lib/recycler.h index 4607199c..37b9250e 100644 --- a/lib/recycler.h +++ b/lib/recycler.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef RECYCLER_H_INCLUDED diff --git a/lib/resolve_path.cpp b/lib/resolve_path.cpp index df65b98b..178e70e2 100644 --- a/lib/resolve_path.cpp +++ b/lib/resolve_path.cpp @@ -312,7 +312,7 @@ Zstring volumenNameToPath(const Zstring& volumeName) //return empty string on er if (EqualFilename()(volumeName, Zstring(&volName[0]))) { //GetVolumePathNamesForVolumeName is not available for Windows 2000! - typedef BOOL (WINAPI *GetVolumePathNamesForVolumeNameWFunc)(LPCWSTR lpszVolumeName, + typedef BOOL (WINAPI* GetVolumePathNamesForVolumeNameWFunc)(LPCWSTR lpszVolumeName, LPWCH lpszVolumePathNames, DWORD cchBufferLength, PDWORD lpcchReturnLength); diff --git a/lib/resolve_path.h b/lib/resolve_path.h index 7005d0ea..2fd5008e 100644 --- a/lib/resolve_path.h +++ b/lib/resolve_path.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef RESOLVE_PATH_H_INCLUDED diff --git a/lib/resources.cpp b/lib/resources.cpp index 01a046b1..e47065e6 100644 --- a/lib/resources.cpp +++ b/lib/resources.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "resources.h" @@ -65,8 +65,8 @@ GlobalResources::GlobalResources() //generic image loading if (name.EndsWith(wxT(".png"))) bitmaps.insert(std::make_pair(name, wxImage(resourceFile, wxBITMAP_TYPE_PNG))); - else if (name == wxT("money.gif")) - loadAnimFromZip(resourceFile, animationMoney); + //else if (name == wxT("money.gif")) + // loadAnimFromZip(resourceFile, animationMoney); else if (name == wxT("working.gif")) loadAnimFromZip(resourceFile, animationSync); } diff --git a/lib/resources.h b/lib/resources.h index d8b08b72..56b23a5f 100644 --- a/lib/resources.h +++ b/lib/resources.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef RESOURCES_H_INCLUDED @@ -21,7 +21,7 @@ public: static const wxBitmap& getImage(const wxString& name) { return instance().getImageInt(name); } //global image resource objects - wxAnimation animationMoney; + //wxAnimation animationMoney; wxAnimation animationSync; wxIcon programIcon; diff --git a/lib/shadow.cpp b/lib/shadow.cpp index 9bc17aff..d00aa2f3 100644 --- a/lib/shadow.cpp +++ b/lib/shadow.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "shadow.h" @@ -21,7 +21,7 @@ namespace bool runningWOW64() //test if process is running under WOW64 (reference http://msdn.microsoft.com/en-us/library/ms684139(VS.85).aspx) { //dynamically load windows API function - typedef BOOL (WINAPI *IsWow64ProcessFun)(HANDLE hProcess, PBOOL Wow64Process); + typedef BOOL (WINAPI* IsWow64ProcessFun)(HANDLE hProcess, PBOOL Wow64Process); const SysDllFun<IsWow64ProcessFun> isWow64Process(L"kernel32.dll", "IsWow64Process"); if (isWow64Process) diff --git a/lib/shadow.h b/lib/shadow.h index bfb1e84a..2d933840 100644 --- a/lib/shadow.h +++ b/lib/shadow.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef SHADOW_H_INCLUDED diff --git a/lib/soft_filter.h b/lib/soft_filter.h index 6763d6b7..1ad55ea9 100644 --- a/lib/soft_filter.h +++ b/lib/soft_filter.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef SOFT_FILTER_H_INCLUDED diff --git a/lib/statistics.cpp b/lib/statistics.cpp index 6cc3c0cd..9914d455 100644 --- a/lib/statistics.cpp +++ b/lib/statistics.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "statistics.h" diff --git a/lib/statistics.h b/lib/statistics.h index 62a30b99..bddf129d 100644 --- a/lib/statistics.h +++ b/lib/statistics.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef STATISTICS_H_INCLUDED diff --git a/lib/status_handler.cpp b/lib/status_handler.cpp index 55f82c64..5e75b60e 100644 --- a/lib/status_handler.cpp +++ b/lib/status_handler.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "status_handler.h" diff --git a/lib/status_handler.h b/lib/status_handler.h index acab956a..a37d2257 100644 --- a/lib/status_handler.h +++ b/lib/status_handler.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef STATUSHANDLER_H_INCLUDED @@ -56,6 +56,7 @@ struct ProcessCallback //opportunity to abort must be implemented in a frequently executed method like requestUiRefresh() virtual void requestUiRefresh() = 0; //throw ? + virtual void forceUiRefresh () = 0; //throw ? - call before starting long running task which doesn't update regularly //called periodically after data was processed: expected(!) to request GUI update virtual void reportStatus(const std::wstring& text) = 0; //status info only, should not be logged! @@ -90,8 +91,6 @@ class StatusHandler : public ProcessCallback, public AbortCallback public: StatusHandler() : abortRequested(false) {} - virtual void forceUiRefresh() = 0; - virtual void requestUiRefresh() { if (updateUiIsAllowed()) //test if specific time span between ui updates is over diff --git a/lib/xml_base.cpp b/lib/xml_base.cpp index 26176776..e6b1e840 100644 --- a/lib/xml_base.cpp +++ b/lib/xml_base.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "xml_base.h" diff --git a/lib/xml_base.h b/lib/xml_base.h index dc534dc5..b81b406d 100644 --- a/lib/xml_base.h +++ b/lib/xml_base.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef XMLBASE_H_INCLUDED |