339 lines
11 KiB
C++
339 lines
11 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifndef PROPERTYSHEET_H
|
|
#define PROPERTYSHEET_H
|
|
|
|
#include <map>
|
|
|
|
#include <App/DocumentObject.h>
|
|
#include <App/PropertyLinks.h>
|
|
|
|
#include "Cell.h"
|
|
|
|
|
|
namespace Spreadsheet
|
|
{
|
|
|
|
class Sheet;
|
|
class PropertySheet;
|
|
class SheetObserver;
|
|
|
|
class SpreadsheetExport PropertySheet: public App::PropertyExpressionContainer,
|
|
private App::AtomicPropertyChangeInterface<PropertySheet>
|
|
{
|
|
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
|
|
|
public:
|
|
explicit PropertySheet(Sheet* _owner = nullptr);
|
|
|
|
~PropertySheet() override;
|
|
|
|
std::map<App::ObjectIdentifier, const App::Expression*> getExpressions() const override;
|
|
void setExpressions(std::map<App::ObjectIdentifier, App::ExpressionPtr>&& exprs) override;
|
|
void onRelabeledDocument(const App::Document& doc) override;
|
|
|
|
void updateElementReference(App::DocumentObject* feature,
|
|
bool reverse = false,
|
|
bool notify = false) override;
|
|
bool referenceChanged() const override;
|
|
bool adjustLink(const std::set<App::DocumentObject*>& inList) override;
|
|
Property*
|
|
CopyOnImportExternal(const std::map<std::string, std::string>& nameMap) const override;
|
|
Property* CopyOnLabelChange(App::DocumentObject* obj,
|
|
const std::string& ref,
|
|
const char* newLabel) const override;
|
|
Property* CopyOnLinkReplace(const App::DocumentObject* parent,
|
|
App::DocumentObject* oldObj,
|
|
App::DocumentObject* newObj) const override;
|
|
void breakLink(App::DocumentObject* obj, bool clear) override;
|
|
|
|
void afterRestore() override;
|
|
void onContainerRestored() override;
|
|
|
|
Property* Copy() const override;
|
|
|
|
void Paste(const Property& from) override;
|
|
|
|
void Save(Base::Writer& writer) const override;
|
|
|
|
void Restore(Base::XMLReader& reader) override;
|
|
|
|
void getLinksTo(std::vector<App::ObjectIdentifier>& identifiers,
|
|
App::DocumentObject* obj,
|
|
const char* subname = nullptr,
|
|
bool all = false) const override;
|
|
|
|
void copyCells(Base::Writer& writer, const std::vector<App::Range>& ranges) const;
|
|
|
|
void pasteCells(Base::XMLReader& reader, App::Range dstRange);
|
|
|
|
Cell* createCell(App::CellAddress address);
|
|
|
|
void setValue()
|
|
{}
|
|
|
|
void setContent(App::CellAddress address, const char* value);
|
|
|
|
void setAlignment(App::CellAddress address, int _alignment);
|
|
|
|
void setStyle(App::CellAddress address, const std::set<std::string>& _style);
|
|
|
|
void setForeground(App::CellAddress address, const App::Color& color);
|
|
|
|
void setBackground(App::CellAddress address, const App::Color& color);
|
|
|
|
void setDisplayUnit(App::CellAddress address, const std::string& unit);
|
|
|
|
void setAlias(App::CellAddress address, const std::string& alias);
|
|
|
|
void setComputedUnit(App::CellAddress address, const Base::Unit& unit);
|
|
|
|
void setSpans(App::CellAddress address, int rows, int columns);
|
|
|
|
void clear(App::CellAddress address, bool toClearAlias = true);
|
|
|
|
void clear();
|
|
|
|
Cell* getValue(App::CellAddress key);
|
|
|
|
const Cell* getValue(App::CellAddress key) const;
|
|
|
|
Cell* getValueFromAlias(const std::string& alias);
|
|
|
|
const Cell* getValueFromAlias(const std::string& alias) const;
|
|
|
|
bool isValidAlias(const std::string& candidate);
|
|
|
|
std::vector<App::CellAddress> getUsedCells() const;
|
|
|
|
std::tuple<App::CellAddress, App::CellAddress> getUsedRange() const;
|
|
|
|
std::vector<App::CellAddress> getNonEmptyCells() const;
|
|
|
|
std::tuple<App::CellAddress, App::CellAddress> getNonEmptyRange() const;
|
|
|
|
Sheet* sheet() const
|
|
{
|
|
return owner;
|
|
}
|
|
|
|
const std::set<App::CellAddress>& getDirty()
|
|
{
|
|
return dirty;
|
|
}
|
|
|
|
void setDirty(App::CellAddress address);
|
|
|
|
void setDirty();
|
|
|
|
void clearDirty(App::CellAddress key)
|
|
{
|
|
dirty.erase(key);
|
|
}
|
|
|
|
void clearDirty()
|
|
{
|
|
dirty.clear();
|
|
purgeTouched();
|
|
}
|
|
|
|
bool isDirty() const
|
|
{
|
|
return dirty.size() > 0;
|
|
}
|
|
|
|
void
|
|
pasteCells(const std::map<App::CellAddress, std::string>& cells, int rowOffset, int colOffset);
|
|
|
|
void insertRows(int row, int count);
|
|
|
|
std::vector<App::CellAddress> getRows(int row, int count) const;
|
|
|
|
void removeRows(int row, int count);
|
|
|
|
void insertColumns(int col, int count);
|
|
|
|
std::vector<App::CellAddress> getColumns(int column, int count) const;
|
|
|
|
void removeColumns(int col, int count);
|
|
|
|
unsigned int getMemSize() const override;
|
|
|
|
bool mergeCells(App::CellAddress from, App::CellAddress to);
|
|
|
|
void splitCell(App::CellAddress address);
|
|
|
|
void getSpans(App::CellAddress address, int& rows, int& cols) const;
|
|
|
|
bool hasSpan() const;
|
|
|
|
App::CellAddress getAnchor(App::CellAddress address) const;
|
|
|
|
bool isMergedCell(App::CellAddress address) const;
|
|
|
|
bool isHidden(App::CellAddress address) const;
|
|
|
|
const std::set<App::CellAddress>& getDeps(const std::string& name) const;
|
|
|
|
const std::set<std::string>& getDeps(App::CellAddress pos) const;
|
|
|
|
void recomputeDependencies(App::CellAddress key);
|
|
|
|
PyObject* getPyObject() override;
|
|
void setPyObject(PyObject*) override;
|
|
|
|
PyObject* getPyValue(PyObject* key);
|
|
|
|
void invalidateDependants(const App::DocumentObject* docObj);
|
|
|
|
void
|
|
renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier>& paths);
|
|
|
|
void deletedDocumentObject(const App::DocumentObject* docObj);
|
|
|
|
void documentSet();
|
|
|
|
App::CellAddress getCellAddress(const char* addr, bool silent = false) const;
|
|
App::Range getRange(const char* range, bool silent = false) const;
|
|
|
|
std::string getRow(int offset = 0) const;
|
|
|
|
std::string getColumn(int offset = 0) const;
|
|
|
|
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
|
|
const boost::any getPathValue(const App::ObjectIdentifier& path) const override;
|
|
|
|
unsigned getBindingBorder(App::CellAddress address) const;
|
|
|
|
bool isBindingPath(const App::ObjectIdentifier& path,
|
|
App::CellAddress* from = nullptr,
|
|
App::CellAddress* to = nullptr,
|
|
bool* href = nullptr) const;
|
|
|
|
enum BindingType
|
|
{
|
|
BindingNone,
|
|
BindingNormal,
|
|
BindingHiddenRef,
|
|
};
|
|
BindingType getBinding(const App::Range& range,
|
|
App::ExpressionPtr* pStart = nullptr,
|
|
App::ExpressionPtr* pEnd = nullptr,
|
|
App::ObjectIdentifier* pTarget = nullptr) const;
|
|
|
|
protected:
|
|
void hasSetValue() override;
|
|
void hasSetChildValue(App::Property& prop) override;
|
|
void onBreakLink(App::DocumentObject* obj) override;
|
|
void onAddDep(App::DocumentObject* obj) override;
|
|
void onRemoveDep(App::DocumentObject* obj) override;
|
|
|
|
private:
|
|
PropertySheet(const PropertySheet& other);
|
|
PropertySheet& operator=(const PropertySheet&);
|
|
|
|
/* friends */
|
|
|
|
friend class AtomicPropertyChange;
|
|
|
|
friend class SheetObserver;
|
|
|
|
friend class Cell;
|
|
|
|
friend class Sheet;
|
|
|
|
Cell* cellAt(App::CellAddress address);
|
|
|
|
Cell* nonNullCellAt(App::CellAddress address);
|
|
|
|
const Cell* cellAt(App::CellAddress address) const;
|
|
|
|
bool colSortFunc(const App::CellAddress& a, const App::CellAddress& b);
|
|
|
|
bool rowSortFunc(const App::CellAddress& a, const App::CellAddress& b);
|
|
|
|
/*! Set of cells that have been marked dirty */
|
|
std::set<App::CellAddress> dirty;
|
|
|
|
/*! Cell data in this property */
|
|
std::map<App::CellAddress, Cell*> data;
|
|
|
|
/*! Merged cells; cell -> anchor cell */
|
|
std::map<App::CellAddress, App::CellAddress> mergedCells;
|
|
|
|
/*! Owner of this property */
|
|
Sheet* owner;
|
|
|
|
void clearAlias(App::CellAddress address);
|
|
|
|
void moveAlias(App::CellAddress currPos, App::CellAddress newPos);
|
|
|
|
void moveCell(App::CellAddress currPos,
|
|
App::CellAddress newPos,
|
|
std::map<App::ObjectIdentifier, App::ObjectIdentifier>& renames);
|
|
|
|
/*
|
|
* Cell dependency tracking
|
|
*/
|
|
|
|
void addDependencies(App::CellAddress key);
|
|
|
|
void removeDependencies(App::CellAddress key);
|
|
|
|
void slotChangedObject(const App::DocumentObject& obj, const App::Property& prop);
|
|
void recomputeDependants(const App::DocumentObject* obj, const char* propName);
|
|
|
|
/*! Cell dependencies, i.e when a change occurs to property given in key,
|
|
the set of addresses needs to be recomputed.
|
|
*/
|
|
std::map<std::string, std::set<App::CellAddress>> propertyNameToCellMap;
|
|
|
|
/*! Properties this cell depends on */
|
|
std::map<App::CellAddress, std::set<std::string>> cellToPropertyNameMap;
|
|
|
|
/*! Cell dependencies, i.e when a change occurs to documentObject given in key,
|
|
the set of addresses needs to be recomputed.
|
|
*/
|
|
std::map<std::string, std::set<App::CellAddress>> documentObjectToCellMap;
|
|
|
|
/*! DocumentObject this cell depends on */
|
|
std::map<App::CellAddress, std::set<std::string>> cellToDocumentObjectMap;
|
|
|
|
/*! Mapping of cell position to alias property */
|
|
std::map<App::CellAddress, std::string> aliasProp;
|
|
|
|
/*! Mapping of alias property to cell position */
|
|
std::map<std::string, App::CellAddress> revAliasProp;
|
|
|
|
/*! The associated python object */
|
|
Py::SmartPtr PythonObject;
|
|
|
|
std::map<const App::DocumentObject*, boost::signals2::scoped_connection> depConnections;
|
|
|
|
int updateCount = 0;
|
|
bool restoring = false;
|
|
};
|
|
|
|
} // namespace Spreadsheet
|
|
#endif // PROPERTYSHEET_H
|