Sketcher: TaskSketcherElements - Very Basic Layer Management
============================================================ This class needs quite some rework, as it is mixing model-view model and item model. Eventually, the whole needs to be moved to a QTreeWidget for layers' implementation. This commit: 1. Moves back implementation only class item to the cpp file. 2. Adds a contextual submenu to change the selection from one layer to another in the naive fixed 3 layer implementation. 3. Adds checkboxes to hide geometry. It is the minimal modification to enable a user work with the 3 layer implementation.
This commit is contained in:
committed by
abdullahtahiriyo
parent
a32a49d2de
commit
74f136bbac
@@ -73,6 +73,79 @@ void ElementView::FUNC(){ \
|
||||
Gui::Application::Instance->commandManager().runCommandByName(CMDSTR);}
|
||||
|
||||
|
||||
namespace SketcherGui {
|
||||
// helper class to store additional information about the listWidget entry.
|
||||
class ElementItem : public QListWidgetItem
|
||||
{
|
||||
public:
|
||||
|
||||
enum class GeometryState {
|
||||
Normal,
|
||||
Construction,
|
||||
InternalAlignment,
|
||||
External
|
||||
};
|
||||
|
||||
enum class Layer {
|
||||
Default = 0,
|
||||
Discontinuous = 1,
|
||||
Hidden = 2,
|
||||
};
|
||||
|
||||
ElementItem(int elementnr, int startingVertex, int midVertex, int endVertex,
|
||||
Base::Type geometryType, GeometryState state, const QString & lab, const Part::Geometry * geo) :
|
||||
ElementNbr(elementnr)
|
||||
, StartingVertex(startingVertex)
|
||||
, MidVertex(midVertex)
|
||||
, EndVertex(endVertex)
|
||||
, GeometryType(std::move(geometryType))
|
||||
, State(state)
|
||||
, isLineSelected(false)
|
||||
, isStartingPointSelected(false)
|
||||
, isEndPointSelected(false)
|
||||
, isMidPointSelected(false)
|
||||
, clickedOn(SubElementType::none)
|
||||
, hovered(SubElementType::none)
|
||||
, rightClicked(false)
|
||||
, label(lab)
|
||||
, geo(geo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~ElementItem() override {
|
||||
}
|
||||
|
||||
bool isVisible() {
|
||||
auto layer = getSafeGeomLayerId(geo);
|
||||
|
||||
return layer != static_cast<unsigned int>(Layer::Hidden);
|
||||
}
|
||||
|
||||
int ElementNbr;
|
||||
int StartingVertex;
|
||||
int MidVertex;
|
||||
int EndVertex;
|
||||
|
||||
Base::Type GeometryType;
|
||||
GeometryState State;
|
||||
|
||||
bool isLineSelected;
|
||||
bool isStartingPointSelected;
|
||||
bool isEndPointSelected;
|
||||
bool isMidPointSelected;
|
||||
|
||||
|
||||
SubElementType clickedOn;
|
||||
SubElementType hovered;
|
||||
bool rightClicked;
|
||||
|
||||
QString label;
|
||||
|
||||
const Part::Geometry * geo;
|
||||
};
|
||||
} // SketcherGui
|
||||
|
||||
class ElementWidgetIcons {
|
||||
|
||||
private:
|
||||
@@ -260,12 +333,53 @@ ElementView::ElementView(QWidget *parent) : QListWidget(parent)
|
||||
elementItemDelegate, &ElementItemDelegate::itemHovered,
|
||||
this, &ElementView::onIndexHovered
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
elementItemDelegate, &ElementItemDelegate::itemChecked,
|
||||
this, &ElementView::onIndexChecked
|
||||
);
|
||||
}
|
||||
|
||||
ElementView::~ElementView()
|
||||
{
|
||||
}
|
||||
|
||||
void ElementView::changeLayer(int layer)
|
||||
{
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
if (!doc)
|
||||
return;
|
||||
|
||||
doc->openTransaction("Geometry Layer Change");
|
||||
std::vector<Gui::SelectionObject> sel = Gui::Selection().getSelectionEx(doc->getName());
|
||||
for (std::vector<Gui::SelectionObject>::iterator ft = sel.begin(); ft != sel.end(); ++ft) {
|
||||
auto sketchobject = dynamic_cast<Sketcher::SketchObject *>(ft->getObject());
|
||||
|
||||
auto geoids = getGeoIdsOfEdgesFromNames(sketchobject, ft->getSubNames());
|
||||
|
||||
|
||||
auto geometry = sketchobject->Geometry.getValues();
|
||||
auto newgeometry(geometry);
|
||||
|
||||
bool anychanged = false;
|
||||
for(auto geoid : geoids) {
|
||||
auto currentlayer = getSafeGeomLayerId(geometry[geoid]);
|
||||
if( currentlayer != layer) {
|
||||
auto geo = geometry[geoid]->clone();
|
||||
setSafeGeomLayerId(geo, layer);
|
||||
newgeometry[geoid] = geo;
|
||||
anychanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(anychanged) {
|
||||
sketchobject->Geometry.setValues(std::move(newgeometry));
|
||||
sketchobject->solve();
|
||||
}
|
||||
}
|
||||
doc->commitTransaction();
|
||||
}
|
||||
|
||||
void ElementView::contextMenuEvent (QContextMenuEvent* event)
|
||||
{
|
||||
QMenu menu;
|
||||
@@ -303,6 +417,21 @@ void ElementView::contextMenuEvent (QContextMenuEvent* event)
|
||||
CONTEXT_ITEM("Sketcher_SelectHorizontalAxis","Select Horizontal Axis","Sketcher_SelectHorizontalAxis",doSelectHAxis,false)
|
||||
CONTEXT_ITEM("Sketcher_SelectVerticalAxis","Select Vertical Axis","Sketcher_SelectVerticalAxis",doSelectVAxis,false)
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
auto submenu = menu.addMenu(tr("Layer"));
|
||||
|
||||
auto addLayerAction = [submenu, this, items](auto && name, int layernumber){
|
||||
auto action = submenu->addAction(tr(std::forward<decltype(name)>(name)), [this, layernumber](){changeLayer(layernumber);});
|
||||
action->setEnabled(!items.isEmpty());
|
||||
return action;
|
||||
};
|
||||
|
||||
addLayerAction("Layer 0", 0);
|
||||
addLayerAction("Layer 1", 1);
|
||||
addLayerAction("Hidden", 2);
|
||||
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
QAction* remove = menu.addAction(tr("Delete"), this, &ElementView::deleteSelectedItems,
|
||||
@@ -362,6 +491,15 @@ void ElementView::onIndexHovered(QModelIndex index) {
|
||||
Q_EMIT onItemHovered(itemFromIndex(index));
|
||||
}
|
||||
|
||||
void ElementView::onIndexChecked(QModelIndex, Qt::CheckState state) {
|
||||
if(state == Qt::Checked) {
|
||||
changeLayer(static_cast<int>(ElementItem::Layer::Default));
|
||||
}
|
||||
else {
|
||||
changeLayer(static_cast<int>(ElementItem::Layer::Hidden));
|
||||
}
|
||||
}
|
||||
|
||||
ElementItem* ElementView::itemFromIndex(const QModelIndex& index) {
|
||||
return static_cast<ElementItem*>(QListWidget::itemFromIndex(index));
|
||||
}
|
||||
@@ -383,9 +521,25 @@ void ElementItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
|
||||
|
||||
if (item) {
|
||||
|
||||
QStyleOptionButton checkboxstyle;
|
||||
checkboxstyle.rect = option.rect;
|
||||
|
||||
checkboxstyle.state |= QStyle::State_Enabled;
|
||||
|
||||
if(item->isVisible())
|
||||
checkboxstyle.state |= QStyle::State_On;
|
||||
else
|
||||
checkboxstyle.state |= QStyle::State_Off;
|
||||
|
||||
QRect checkboxrect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkboxstyle);
|
||||
|
||||
customIconsMargin = leftMargin + checkboxrect.width();
|
||||
|
||||
QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkboxstyle, painter);
|
||||
|
||||
int height = option.rect.height();
|
||||
int width = height; //icons are square.
|
||||
int x0 = option.rect.x() + leftMargin;
|
||||
int x0 = option.rect.x() + customIconsMargin;
|
||||
int iconsize = height - 2 * border;
|
||||
int btny = option.rect.y() + border;
|
||||
|
||||
@@ -396,7 +550,9 @@ void ElementItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
|
||||
painter->fillRect(rect, option.palette.base());
|
||||
};
|
||||
|
||||
painter->fillRect(option.rect, option.palette.highlight()); // paint the item as selected
|
||||
QRect selection = QRect(customIconsMargin, option.rect.y(), option.rect.width()-customIconsMargin, option.rect.height());
|
||||
|
||||
painter->fillRect(selection, option.palette.highlight()); // paint the item as selected
|
||||
|
||||
// Repaint individual icons
|
||||
if (!item->isLineSelected)
|
||||
@@ -431,19 +587,17 @@ void ElementItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
|
||||
|
||||
bool ElementItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
|
||||
{
|
||||
using SubElementType = ElementItem::SubElementType;
|
||||
|
||||
auto getSubElementType = [&](ElementItem* item, int xPos, int width) {
|
||||
|
||||
bool label = (xPos > option.rect.x() + leftMargin + width * 4 + border);
|
||||
bool label = (xPos > option.rect.x() + customIconsMargin + width * 4 + border);
|
||||
|
||||
if((xPos < option.rect.x() + leftMargin + width + border) || ( item->GeometryType != Part::GeomPoint::getClassTypeId() && label))
|
||||
if((xPos < option.rect.x() + customIconsMargin + width + border) || ( item->GeometryType != Part::GeomPoint::getClassTypeId() && label))
|
||||
return SubElementType::edge;
|
||||
if(xPos < option.rect.x() + leftMargin + width * 2 + border || ( item->GeometryType == Part::GeomPoint::getClassTypeId() && label))
|
||||
if(xPos < option.rect.x() + customIconsMargin + width * 2 + border || ( item->GeometryType == Part::GeomPoint::getClassTypeId() && label))
|
||||
return SubElementType::start;
|
||||
if(xPos < option.rect.x() + leftMargin + width * 3 + border)
|
||||
if(xPos < option.rect.x() + customIconsMargin + width * 3 + border)
|
||||
return SubElementType::end;
|
||||
else if (xPos < option.rect.x() + leftMargin + width * 4 + border)
|
||||
else if (xPos < option.rect.x() + customIconsMargin + width * 4 + border)
|
||||
return SubElementType::mid;
|
||||
else
|
||||
return SubElementType::none;
|
||||
@@ -460,6 +614,12 @@ bool ElementItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model,
|
||||
|
||||
if (mEvent->button() == Qt::RightButton)
|
||||
item->rightClicked = true;
|
||||
|
||||
QRect checkboxrect = QRect(leftMargin, option.rect.y(), customIconsMargin-leftMargin, option.rect.height());
|
||||
|
||||
if (mEvent->button() == Qt::LeftButton && checkboxrect.contains(mEvent->pos())) {
|
||||
Q_EMIT itemChecked(index, item->isVisible()?Qt::Unchecked:Qt::Checked);
|
||||
}
|
||||
}
|
||||
else if (event->type() == QEvent::MouseMove) {
|
||||
SubElementType typeUnderMouse;
|
||||
@@ -474,6 +634,7 @@ bool ElementItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model,
|
||||
item->hovered = typeUnderMouse;
|
||||
Q_EMIT itemHovered(index);
|
||||
}
|
||||
|
||||
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
||||
@@ -1144,6 +1305,7 @@ void TaskSketcherElements::slotElementsChanged(void)
|
||||
(tr("Other") + IdInformation()) +
|
||||
(construction ? (QString::fromLatin1("-") + tr("Construction")) : (internalAligned ? (QString::fromLatin1("-") + tr("Internal")) : QString::fromLatin1(""))) :
|
||||
(QString::fromLatin1("%1-").arg(i) + tr("Other")))
|
||||
, (*it) // geometry
|
||||
);
|
||||
|
||||
ui->listWidgetElements->addItem(itemN);
|
||||
@@ -1235,6 +1397,7 @@ void TaskSketcherElements::slotElementsChanged(void)
|
||||
(isNamingBoxChecked ?
|
||||
(tr("Other") + linkname) :
|
||||
(QString::fromLatin1("%1-").arg(i - 2) + tr("Other")))
|
||||
, (*it) // geometry
|
||||
);
|
||||
|
||||
ui->listWidgetElements->addItem(itemN);
|
||||
|
||||
@@ -43,71 +43,18 @@ class Ui_TaskSketcherElements;
|
||||
|
||||
|
||||
|
||||
// helper class to store additional information about the listWidget entry.
|
||||
class ElementItem : public QListWidgetItem
|
||||
{
|
||||
public:
|
||||
|
||||
enum class GeometryState {
|
||||
Normal,
|
||||
Construction,
|
||||
InternalAlignment,
|
||||
External
|
||||
};
|
||||
|
||||
// Struct to identify the selection/preselection of a subelement of the item
|
||||
enum class SubElementType {
|
||||
edge,
|
||||
start,
|
||||
end,
|
||||
mid,
|
||||
none
|
||||
};
|
||||
|
||||
ElementItem(int elementnr, int startingVertex, int midVertex, int endVertex,
|
||||
Base::Type geometryType, GeometryState state, const QString & lab) :
|
||||
ElementNbr(elementnr)
|
||||
, StartingVertex(startingVertex)
|
||||
, MidVertex(midVertex)
|
||||
, EndVertex(endVertex)
|
||||
, GeometryType(std::move(geometryType))
|
||||
, State(state)
|
||||
, isLineSelected(false)
|
||||
, isStartingPointSelected(false)
|
||||
, isEndPointSelected(false)
|
||||
, isMidPointSelected(false)
|
||||
, clickedOn(SubElementType::none)
|
||||
, hovered(SubElementType::none)
|
||||
, rightClicked(false)
|
||||
, label(lab)
|
||||
{}
|
||||
|
||||
~ElementItem() override {
|
||||
}
|
||||
|
||||
int ElementNbr;
|
||||
int StartingVertex;
|
||||
int MidVertex;
|
||||
int EndVertex;
|
||||
|
||||
Base::Type GeometryType;
|
||||
GeometryState State;
|
||||
|
||||
bool isLineSelected;
|
||||
bool isStartingPointSelected;
|
||||
bool isEndPointSelected;
|
||||
bool isMidPointSelected;
|
||||
|
||||
|
||||
SubElementType clickedOn;
|
||||
SubElementType hovered;
|
||||
bool rightClicked;
|
||||
|
||||
QString label;
|
||||
};
|
||||
|
||||
class ElementItem;
|
||||
class ElementView;
|
||||
|
||||
// Struct to identify the selection/preselection of a subelement of the item
|
||||
enum class SubElementType {
|
||||
edge,
|
||||
start,
|
||||
end,
|
||||
mid,
|
||||
none
|
||||
};
|
||||
|
||||
class ElementItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -122,10 +69,12 @@ public:
|
||||
|
||||
const int border = 1; //1px, looks good around buttons.
|
||||
const int leftMargin = 4; //4px on the left of icons, looks good.
|
||||
mutable int customIconsMargin = 4;
|
||||
const int textBottomMargin = 5; //5px center the text.
|
||||
|
||||
Q_SIGNALS:
|
||||
void itemHovered(QModelIndex);
|
||||
void itemChecked(QModelIndex, Qt::CheckState state);
|
||||
};
|
||||
|
||||
class ElementView : public QListWidget
|
||||
@@ -173,9 +122,13 @@ protected Q_SLOTS:
|
||||
void deleteSelectedItems();
|
||||
|
||||
void onIndexHovered(QModelIndex index);
|
||||
void onIndexChecked(QModelIndex, Qt::CheckState state);
|
||||
|
||||
Q_SIGNALS:
|
||||
void onItemHovered(QListWidgetItem *);
|
||||
|
||||
private:
|
||||
void changeLayer(int layer);
|
||||
};
|
||||
|
||||
class ElementFilterList : public QListWidget
|
||||
@@ -247,7 +200,6 @@ protected:
|
||||
Connection connectionElementsChanged;
|
||||
|
||||
private:
|
||||
using SubElementType = ElementItem::SubElementType;
|
||||
QWidget* proxy;
|
||||
std::unique_ptr<Ui_TaskSketcherElements> ui;
|
||||
int focusItemIndex;
|
||||
|
||||
Reference in New Issue
Block a user