diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/binary.cpp | 10 | ||||
-rw-r--r-- | library/custom_grid.cpp | 293 | ||||
-rw-r--r-- | library/custom_grid.h | 72 | ||||
-rw-r--r-- | library/db_file.cpp | 2 | ||||
-rw-r--r-- | library/dir_lock.cpp | 79 | ||||
-rw-r--r-- | library/pch.h | 14 |
6 files changed, 278 insertions, 192 deletions
diff --git a/library/binary.cpp b/library/binary.cpp index d4d35e92..cbcef238 100644 --- a/library/binary.cpp +++ b/library/binary.cpp @@ -106,16 +106,6 @@ bool ffs3::filesHaveSameContent(const Zstring& filename1, const Zstring& filenam } //------------------------------------------------------------------------------------------------ -//#warning -// static wxLongLong blorg = wxGetLocalTimeMillis(); -// if (wxGetLocalTimeMillis() - blorg > 5000) -// { -// blorg = wxGetLocalTimeMillis(); -// wxMessageBox(numberToZstring<size_t>(bufferSize).c_str()); -// } - - - if (length1 != length2 || ::memcmp(&memory1[0], &memory2[0], length1) != 0) return false; diff --git a/library/custom_grid.cpp b/library/custom_grid.cpp index b510717f..e7a724a0 100644 --- a/library/custom_grid.cpp +++ b/library/custom_grid.cpp @@ -599,9 +599,6 @@ void CustomGrid::initSettings(CustomGridLeft* gridLeft, m_gridRight = gridRight; m_gridMiddle = gridMiddle; - //set underlying grid data - setGridDataTable(gridDataView); - //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); @@ -626,7 +623,8 @@ void CustomGrid::initSettings(CustomGridLeft* gridLeft, void CustomGrid::release() //release connection to ffs3::GridView { - setGridDataTable(NULL); + assert(getGridDataTable()); + getGridDataTable()->setGridDataTable(NULL); //kind of "disable" griddatatable; don't delete it with SetTable(NULL)! May be used by wxGridCellStringRenderer } @@ -955,6 +953,13 @@ void CustomGrid::adjustGridHeights(wxEvent& event) } +void CustomGrid::updateGridSizes() +{ + if(getGridDataTable()) + getGridDataTable()->updateGridSizes(); +} + + void CustomGrid::setSortMarker(SortMarker marker) { m_marker = marker; @@ -1175,7 +1180,48 @@ CustomGridRim::CustomGridRim(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGrid(parent, id, pos, size, style, name), fileIconsAreEnabled(false) {} + CustomGrid(parent, id, pos, size, style, name), fileIconsAreEnabled(false), 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> @@ -1217,21 +1263,25 @@ void CustomGridRim::setTooltip(const wxMouseEvent& event) } } - wxToolTip* tt = GetGridWindow()->GetToolTip(); - if (!tt) - //wxWidgets bug: tooltip multiline property is defined by first tooltip text containing newlines or not (same is true for maximum width) - 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->GetTip() != toolTip) - tt->SetTip(toolTip); -} + wxToolTip* tt = GetGridWindow()->GetToolTip(); -void CustomGridRim::updateGridSizes() -{ - assert(getGridDataTable()); - getGridDataTable()->updateGridSizes(); + 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); + } + } } @@ -1353,8 +1403,8 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) newPositions.push_back(columnSettings[i].type); //set column positions - assert(getGridDataTable()); - getGridDataTable()->setupColumns(newPositions); + if (getGridDataTableRim()) + getGridDataTableRim()->setupColumns(newPositions); //set column width (set them after setupColumns!) for (size_t i = 0; i < newPositions.size(); ++i) @@ -1379,8 +1429,10 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) xmlAccess::ColumnTypes CustomGridRim::getTypeAtPos(size_t pos) const { - assert(getGridDataTable()); - return getGridDataTable()->getTypeAtPos(pos); + if (getGridDataTableRim()) + return getGridDataTableRim()->getTypeAtPos(pos); + else + return xmlAccess::DIRECTORY; } @@ -1408,13 +1460,6 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType) } -CustomGridTableRim* CustomGridRim::getGridDataTable() -{ - //let the non-const call the const version: see Meyers Effective C++ - return const_cast<CustomGridTableRim*>(static_cast<const CustomGridRim*>(this)->getGridDataTable()); -} - - void CustomGridRim::autoSizeColumns() //performance optimized column resizer (analog to wxGrid::AutoSizeColumns() { for (int col = 0; col < GetNumberCols(); ++col) @@ -1474,9 +1519,9 @@ void CustomGridRim::enableFileIcons(const bool value) fileIconsAreEnabled = value; if (value) - SetDefaultRenderer(new GridCellRenderer<true>(loadIconSuccess, getGridDataTable())); //SetDefaultRenderer takes ownership! + SetDefaultRenderer(new GridCellRenderer<true>(loadIconSuccess, getGridDataTableRim())); //SetDefaultRenderer takes ownership! else - SetDefaultRenderer(new GridCellRenderer<false>(loadIconSuccess, getGridDataTable())); + SetDefaultRenderer(new GridCellRenderer<false>(loadIconSuccess, getGridDataTableRim())); Refresh(); } @@ -1504,13 +1549,22 @@ CustomGridRim::VisibleRowRange CustomGridRim::getVisibleRows() } +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 { newLoad.clear(); if (fileIconsAreEnabled) //don't check too often! give worker thread some time to fetch data { - const CustomGridTableRim* gridDataTable = getGridDataTable(); + const CustomGridTableRim* gridDataTable = getGridDataTableRim(); + if (!gridDataTable) return; + const VisibleRowRange rowsOnScreen = getVisibleRows(); const int totalCols = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberCols(); const int totalRows = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberRows(); @@ -1596,54 +1650,46 @@ CustomGridLeft::CustomGridLeft(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name), - gridDataTable(NULL) + CustomGridRim(parent, id, pos, size, style, name) { GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridLeft::OnMouseMovement), NULL, this); //row-based tooltip } -void CustomGridLeft::OnMouseMovement(wxMouseEvent& event) -{ - CustomGridRim::setTooltip<LEFT_SIDE>(event); - event.Skip(); -} - - 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. - gridDataTable = new CustomGridTableLeft; - SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor - + SetTable(new CustomGridTableLeft, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor return true; } -void CustomGridLeft::setGridDataTable(const GridView* gridDataView) +void CustomGridLeft::initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView) { //set underlying grid data - assert(gridDataTable); - gridDataTable->setGridDataTable(gridDataView); + assert(getGridDataTable()); + getGridDataTable()->setGridDataTable(gridDataView); + + CustomGridRim::setOtherGrid(gridRight); + + CustomGridRim::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); } -const CustomGridTableRim* CustomGridLeft::getGridDataTable() const +void CustomGridLeft::OnMouseMovement(wxMouseEvent& event) { - return gridDataTable; + CustomGridRim::setTooltip<LEFT_SIDE>(event); + event.Skip(); } -//this method is called when grid view changes: useful for parallel updating of multiple grids -void CustomGridLeft::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) +CustomGridTable* CustomGridLeft::getGridDataTable() const { - int x = 0; - int y = 0; - GetViewStart(&x, &y); - - gridMiddle->Scroll(-1, y); //scroll in y-direction only - gridRight->Scroll(x, y); + return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! } @@ -1654,51 +1700,44 @@ CustomGridRight::CustomGridRight(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name), - gridDataTable(NULL) + CustomGridRim(parent, id, pos, size, style, name) { GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridRight::OnMouseMovement), NULL, this); //row-based tooltip } -void CustomGridRight::OnMouseMovement(wxMouseEvent& event) -{ - CustomGridRim::setTooltip<RIGHT_SIDE>(event); - event.Skip(); -} - - bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) { - gridDataTable = new CustomGridTableRight; - SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor - + SetTable(new CustomGridTableRight, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor return true; } -void CustomGridRight::setGridDataTable(const GridView* gridDataView) +void CustomGridRight::initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView) { //set underlying grid data - assert(gridDataTable); - gridDataTable->setGridDataTable(gridDataView); + assert(getGridDataTable()); + getGridDataTable()->setGridDataTable(gridDataView); + + CustomGridRim::setOtherGrid(gridLeft); + + CustomGridRim::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); } -const CustomGridTableRim* CustomGridRight::getGridDataTable() const +void CustomGridRight::OnMouseMovement(wxMouseEvent& event) { - return gridDataTable; + CustomGridRim::setTooltip<RIGHT_SIDE>(event); + event.Skip(); } -//this method is called when grid view changes: useful for parallel updating of multiple grids -void CustomGridRight::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) +CustomGridTable* CustomGridRight::getGridDataTable() const { - int x = 0; - int y = 0; - GetViewStart(&x, &y); - gridLeft->Scroll(x, y); - gridMiddle->Scroll(-1, y); + return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! } @@ -1706,7 +1745,7 @@ void CustomGridRight::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMidd class GridCellRendererMiddle : public wxGridCellStringRenderer { public: - GridCellRendererMiddle(const CustomGridMiddle* middleGrid) : m_gridMiddle(middleGrid) {}; + GridCellRendererMiddle(const CustomGridMiddle& middleGrid) : m_gridMiddle(middleGrid) {}; virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, @@ -1716,7 +1755,7 @@ public: bool isSelected); private: - const CustomGridMiddle* const m_gridMiddle; + const CustomGridMiddle& m_gridMiddle; }; @@ -1744,7 +1783,6 @@ CustomGridMiddle::CustomGridMiddle(wxWindow *parent, selectionPos(BLOCKPOS_CHECK_BOX), highlightedRow(-1), highlightedPos(BLOCKPOS_CHECK_BOX), - gridDataTable(NULL), toolTip(new CustomTooltip) { SetLayoutDirection(wxLayout_LeftToRight); // @@ -1765,38 +1803,55 @@ CustomGridMiddle::~CustomGridMiddle() {} //non-inline destructor for std::auto_p bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) { - gridDataTable = new CustomGridTableMiddle; - SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor + 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! + SetDefaultRenderer(new GridCellRendererMiddle(*this)); //SetDefaultRenderer takes ownership! return true; } -#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::setGridDataTable(const GridView* gridDataView) //called once on startup +void CustomGridMiddle::initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView) { //set underlying grid data - assert(gridDataTable); - gridDataTable->setGridDataTable(gridDataView); + 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; @@ -1836,14 +1891,17 @@ void CustomGridMiddle::OnLeaveWindow(wxMouseEvent& event) void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) { - const FileSystemObject* const fsObj = gridDataTable->getRawData(rowNumber); + if (!getGridDataTableMiddle()) + return; + + const FileSystemObject* const fsObj = getGridDataTableMiddle()->getRawData(rowNumber); if (fsObj == NULL) //if invalid row... { toolTip->hide(); return; } - if (gridDataTable->syncPreviewIsActive()) //synchronization preview + if (getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview { const SyncOperation syncOp = fsObj->getSyncOperation(); switch (syncOp) @@ -1963,6 +2021,9 @@ void CustomGridMiddle::OnLeftMouseUp(wxMouseEvent& event) int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) { + if (!getGridDataTableMiddle()) + return 0; + int row = -1; int x = -1; int y = -1; @@ -1978,9 +2039,9 @@ int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) if (row >= 0) { - const FileSystemObject* const fsObj = gridDataTable->getRawData(row); + const FileSystemObject* const fsObj = getGridDataTableMiddle()->getRawData(row); if ( fsObj != NULL && //if valid row... - gridDataTable->syncPreviewIsActive() && + getGridDataTableMiddle()->syncPreviewIsActive() && fsObj->getSyncOperation() != SO_EQUAL) //in sync-preview equal files shall be treated as in cmp result, i.e. as full checkbox { // cell: @@ -2012,8 +2073,8 @@ int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) void CustomGridMiddle::enableSyncPreview(bool value) { - assert(gridDataTable); - gridDataTable->enableSyncPreview(value); + assert(getGridDataTableMiddle()); + getGridDataTableMiddle()->enableSyncPreview(value); if (value) GetGridColLabelWindow()->SetToolTip(_("Synchronization Preview")); @@ -2022,13 +2083,6 @@ void CustomGridMiddle::enableSyncPreview(bool value) } -void CustomGridMiddle::updateGridSizes() -{ - assert(gridDataTable); - gridDataTable->updateGridSizes(); -} - - void GridCellRendererMiddle::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -2037,12 +2091,12 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, bool isSelected) { //retrieve grid data - const FileSystemObject* const fsObj = m_gridMiddle->gridDataTable->getRawData(row); + 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; + const bool rowIsHighlighted = row == m_gridMiddle.highlightedRow; wxRect rectShrinked(rect); @@ -2055,7 +2109,7 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, //HIGHLIGHTNING (checkbox): if ( rowIsHighlighted && - m_gridMiddle->highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) + m_gridMiddle.highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) { if (fsObj->isActive()) dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("checkboxTrueFocus")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); @@ -2074,14 +2128,14 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected); //print remaining block - if (m_gridMiddle->gridDataTable->syncPreviewIsActive()) //synchronization preview + 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) + m_gridMiddle.highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files + switch (m_gridMiddle.highlightedPos) { case CustomGridMiddle::BLOCKPOS_CHECK_BOX: break; @@ -2153,9 +2207,12 @@ void CustomGridMiddle::DrawColLabel(wxDC& dc, int col) { CustomGrid::DrawColLabel(dc, col); + if (!getGridDataTableMiddle()) + return; + const wxRect rect(GetColLeft(col), 0, GetColWidth(col), GetColLabelSize()); - if (gridDataTable->syncPreviewIsActive()) + if (getGridDataTableMiddle()->syncPreviewIsActive()) dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("syncViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); else dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("cmpViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); diff --git a/library/custom_grid.h b/library/custom_grid.h index 206841dd..193b403d 100644 --- a/library/custom_grid.h +++ b/library/custom_grid.h @@ -16,6 +16,7 @@ #include "../file_hierarchy.h" +class CustomGridTable; class CustomGridTableRim; class CustomGridTableLeft; class CustomGridTableRight; @@ -62,10 +63,10 @@ public: virtual ~CustomGrid() {} - void initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView - CustomGridMiddle* gridMiddle, - CustomGridRight* gridRight, - const ffs3::GridView* gridDataView); + virtual void initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView); void release(); //release connection to ffs3::GridView @@ -80,6 +81,9 @@ public: DESCENDING }; + //notify wxGrid that underlying table size has changed + void updateGridSizes(); + typedef std::pair<SortColumn, SortDirection> SortMarker; void setSortMarker(SortMarker marker); @@ -90,9 +94,9 @@ protected: virtual void DrawColLabel(wxDC& dc, int col); std::pair<int, int> mousePosToCell(wxPoint pos); //returns (row/column) pair -private: - virtual void setGridDataTable(const ffs3::GridView* gridDataView) = 0; + virtual CustomGridTable* getGridDataTable() const = 0; +private: //this method is called when grid view changes: useful for parallel updating of multiple grids void OnPaintGrid(wxEvent& event); @@ -147,9 +151,6 @@ public: long style, const wxString& name); - //notify wxGrid that underlying table size has changed - void updateGridSizes(); - //set visibility, position and width of columns static xmlAccess::ColumnAttributes getDefaultColumnAttributes(); xmlAccess::ColumnAttributes getColumnAttributes(); @@ -159,7 +160,6 @@ public: static wxString getTypeName(xmlAccess::ColumnTypes colType); void autoSizeColumns(); //performance optimized column resizer - void autoSizeColumns(int col, bool doRefresh = true); // void enableFileIcons(const bool value); @@ -167,9 +167,15 @@ protected: template <ffs3::SelectedSide side> void setTooltip(const wxMouseEvent& event); +void setOtherGrid(CustomGridRim* other); //call during initialization! + private: - CustomGridTableRim* getGridDataTable(); - virtual const CustomGridTableRim* getGridDataTable() const = 0; + CustomGridTableRim* getGridDataTableRim() const; + +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 @@ -188,6 +194,7 @@ private: bool fileIconsAreEnabled; xmlAccess::ColumnAttributes columnSettings; //set visibility, position and width of columns + CustomGridRim* otherGrid; //sibling grid on other side }; @@ -203,15 +210,14 @@ public: virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); + virtual void initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView); + private: void OnMouseMovement(wxMouseEvent& event); - virtual void setGridDataTable(const ffs3::GridView* gridDataView); - virtual const CustomGridTableRim* getGridDataTable() const; - - //this method is called when grid view changes: useful for parallel updating of multiple grids - virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight); - - CustomGridTableLeft* gridDataTable; + virtual CustomGridTable* getGridDataTable() const; }; @@ -227,15 +233,14 @@ public: virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); + virtual void initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView); + private: void OnMouseMovement(wxMouseEvent& event); - virtual void setGridDataTable(const ffs3::GridView* gridDataView); - virtual const CustomGridTableRim* getGridDataTable() const; - - //this method is called when grid view changes: useful for parallel updating of multiple grids - virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight); - - CustomGridTableRight* gridDataTable; + virtual CustomGridTable* getGridDataTable() const; }; @@ -255,18 +260,21 @@ public: virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); - void enableSyncPreview(bool value); + virtual void initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView); - //notify wxGrid that underlying table size has changed - void updateGridSizes(); + void enableSyncPreview(bool value); private: + virtual CustomGridTable* getGridDataTable() const; + CustomGridTableMiddle* getGridDataTableMiddle() const; + #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 - virtual void setGridDataTable(const ffs3::GridView* gridDataView); - //this method is called when grid view changes: useful for parallel updating of multiple grids virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight); @@ -297,8 +305,6 @@ private: int highlightedRow; BlockPosition highlightedPos; - CustomGridTableMiddle* gridDataTable; - std::auto_ptr<CustomTooltip> toolTip; }; diff --git a/library/db_file.cpp b/library/db_file.cpp index 195d7df6..a0f5099c 100644 --- a/library/db_file.cpp +++ b/library/db_file.cpp @@ -33,8 +33,6 @@ const int FILE_FORMAT_VER = 4; //------------------------------------------------------------------------------------------------------------------------------- -//yet another layer of indirection: Since 32/64 bit builds are binary incompatible, we want them to write into "distinct parts" of the db-file -//just like we were actually accessing different files class FileInputStreamDB : public FileInputStream { public: diff --git a/library/dir_lock.cpp b/library/dir_lock.cpp index 54ae8636..f4ed8e07 100644 --- a/library/dir_lock.cpp +++ b/library/dir_lock.cpp @@ -12,8 +12,11 @@ #include "../shared/system_constants.h" #include "../shared/guid.h" #include "../shared/file_io.h" +#include "../shared/assert_static.h" #include <utility> #include "../shared/serialize.h" +#include <boost/cstdint.hpp> +#include "../shared/build_info.h" #ifdef FFS_WIN #include <tlhelp32.h> @@ -205,20 +208,37 @@ Zstring deleteAbandonedLockName(const Zstring& lockfilename) namespace { inline -wxString readString(wxInputStream& stream) //read string from file stream +std::string readString(wxInputStream& stream) //read string from file stream { - const size_t strLength = util::readNumber<size_t>(stream); - boost::scoped_array<wxChar> buffer(new wxChar[strLength]); - stream.Read(buffer.get(), sizeof(wxChar) * strLength); - return wxString(buffer.get(), strLength); + const boost::uint32_t strLength = util::readNumber<boost::uint32_t>(stream); + std::string output; + if (strLength > 0) + { + output.resize(strLength); + stream.Read(&output[0], strLength); + } + return output; } inline -void writeString(wxOutputStream& stream, const wxString& str) //write string to filestream +void writeString(wxOutputStream& stream, const std::string& str) //write string to filestream +{ + const boost::uint32_t strLength = static_cast<boost::uint32_t>(str.length()); + util::writeNumber<boost::uint32_t>(stream, strLength); + stream.Write(str.c_str(), strLength); +} + + +std::string getComputerId() //returns empty string on error { - util::writeNumber<size_t>(stream, str.length()); - stream.Write(str.c_str(), sizeof(wxChar) * str.length()); + const wxString fhn = ::wxGetFullHostName(); + if (fhn.empty()) return std::string(); +#ifdef FFS_WIN + return "Windows " + std::string(fhn.ToUTF8()); +#elif defined FFS_LINUX + return "Linux " + std::string(fhn.ToUTF8()); +#endif } @@ -227,36 +247,42 @@ struct LockInformation LockInformation() { #ifdef FFS_WIN - processId = ::GetCurrentProcessId(); + procDescr.processId = ::GetCurrentProcessId(); #elif defined FFS_LINUX - processId = ::getpid(); + procDescr.processId = ::getpid(); #endif - computerId = ::wxGetFullHostName(); + procDescr.computerId = getComputerId(); } LockInformation(wxInputStream& stream) : //read lockId(util::UniqueId(stream)) { - processId = util::readNumber<ProcessId>(stream); - computerId = readString(stream); + procDescr.processId = static_cast<ProcessId>(util::readNumber<boost::uint64_t>(stream)); //possible loss of precision (32/64 bit process) covered by buildId + procDescr.computerId = readString(stream); } void toStream(wxOutputStream& stream) const //write { + assert_static(sizeof(ProcessId) <= sizeof(boost::uint64_t)); //ensure portability + lockId.toStream(stream); - util::writeNumber<ProcessId>(stream, processId); - writeString(stream, computerId); + util::writeNumber<boost::uint64_t>(stream, procDescr.processId); + writeString(stream, procDescr.computerId); } #ifdef FFS_WIN - typedef DWORD ProcessId; + typedef DWORD ProcessId; //same size on 32 and 64 bit windows! #elif defined FFS_LINUX typedef pid_t ProcessId; #endif - util::UniqueId lockId; - ProcessId processId; - wxString computerId; + util::UniqueId lockId; //16 byte portable construct + + struct ProcessDescription + { + ProcessId processId; + std::string computerId; + } procDescr; }; @@ -267,16 +293,17 @@ enum ProcessStatus PROC_STATUS_RUNNING, PROC_STATUS_NO_IDEA }; -ProcessStatus getProcessStatus(LockInformation::ProcessId procId, const wxString& computerId) +ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDescr) { - if (::wxGetFullHostName() != computerId || computerId.empty()) + if ( procDescr.computerId != getComputerId() || + procDescr.computerId.empty()) //both names are empty return PROC_STATUS_NO_IDEA; //lock owned by different computer #ifdef FFS_WIN //note: ::OpenProcess() is no option as it may successfully return for crashed processes! HANDLE snapshot = ::CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, //__in DWORD dwFlags, - procId); //__in DWORD th32ProcessID + 0); //__in DWORD th32ProcessID if (snapshot == INVALID_HANDLE_VALUE) return PROC_STATUS_NO_IDEA; boost::shared_ptr<void> dummy(snapshot, ::CloseHandle); @@ -290,7 +317,7 @@ ProcessStatus getProcessStatus(LockInformation::ProcessId procId, const wxString do { - if (processEntry.th32ProcessID == procId) + if (processEntry.th32ProcessID == procDescr.processId) return PROC_STATUS_RUNNING; //process still running } while(::Process32Next(snapshot, &processEntry)); @@ -298,10 +325,10 @@ ProcessStatus getProcessStatus(LockInformation::ProcessId procId, const wxString return PROC_STATUS_NOT_RUNNING; #elif defined FFS_LINUX - if (procId <= 0 || procId >= 65536) + if (procDescr.processId <= 0 || procDescr.processId >= 65536) return PROC_STATUS_NO_IDEA; //invalid process id - return ffs3::dirExists(Zstr("/proc/") + Zstring::fromNumber(procId)) ? PROC_STATUS_RUNNING : PROC_STATUS_NOT_RUNNING; + return ffs3::dirExists(Zstr("/proc/") + Zstring::fromNumber(procDescr.processId)) ? PROC_STATUS_RUNNING : PROC_STATUS_NOT_RUNNING; #endif } @@ -339,7 +366,7 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr try { const LockInformation lockInfo = retrieveLockInfo(lockfilename); //throw (FileError, ErrorNotExisting) - const bool lockOwnderDead = getProcessStatus(lockInfo.processId, lockInfo.computerId) == PROC_STATUS_NOT_RUNNING; //convenience optimization: if we know the owning process crashed, we needn't wait DETECT_EXITUS_INTERVAL sec + const bool lockOwnderDead = getProcessStatus(lockInfo.procDescr) == PROC_STATUS_NOT_RUNNING; //convenience optimization: if we know the owning process crashed, we needn't wait DETECT_EXITUS_INTERVAL sec wxULongLong fileSizeOld; wxLongLong lockSilentStart = wxGetLocalTimeMillis(); diff --git a/library/pch.h b/library/pch.h index 798319c7..f7ff59ab 100644 --- a/library/pch.h +++ b/library/pch.h @@ -29,16 +29,24 @@ do NOT use in release build! //STL headers #include <string> -#include <algorithm> #include <vector> -#include <queue> -#include <stack> #include <set> #include <map> +#include <queue> +#include <deque> +#include <stack> +#include <list> +#include <algorithm> +#include <functional> +#include <iterator> +#include <numeric> #include <memory> +#include <utility> #include <fstream> +#include <iostream> #include <sstream> #include <new> +#include <stdexcept> //other wxWidgets headers #include <wx/log.h> |