From c1453f1715f423707cf45f06e42a4f02a324025f Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Tue, 24 Mar 2020 17:31:32 +0200 Subject: [PATCH] Organization of groups - groups categories. Closes smart-pattern/valentina#15. --- ChangeLog.txt | 1 + src/app/valentina/dialogs/vwidgetgroups.cpp | 57 ++++++-- src/app/valentina/dialogs/vwidgetgroups.h | 5 +- src/app/valentina/dialogs/vwidgetgroups.ui | 39 +++++- src/app/valentina/mainwindow.cpp | 8 +- src/libs/ifc/schema/pattern/v0.8.7.xsd | 1 + src/libs/ifc/xml/vabstractpattern.cpp | 99 ++++++++++++-- src/libs/ifc/xml/vabstractpattern.h | 23 +++- src/libs/vmisc/compatibility.h | 23 ++++ .../dialogs/tools/dialogflippingbyaxis.cpp | 32 +++++ .../dialogs/tools/dialogflippingbyaxis.h | 7 + .../dialogs/tools/dialogflippingbyaxis.ui | 35 ++++- .../dialogs/tools/dialogflippingbyline.cpp | 32 +++++ .../dialogs/tools/dialogflippingbyline.h | 7 + .../dialogs/tools/dialogflippingbyline.ui | 35 ++++- src/libs/vtools/dialogs/tools/dialoggroup.cpp | 19 +++ src/libs/vtools/dialogs/tools/dialoggroup.h | 5 + src/libs/vtools/dialogs/tools/dialoggroup.ui | 42 +++++- src/libs/vtools/dialogs/tools/dialogmove.cpp | 32 +++++ src/libs/vtools/dialogs/tools/dialogmove.h | 7 + src/libs/vtools/dialogs/tools/dialogmove.ui | 35 ++++- .../vtools/dialogs/tools/dialogrotation.cpp | 32 +++++ .../vtools/dialogs/tools/dialogrotation.h | 7 + .../vtools/dialogs/tools/dialogrotation.ui | 39 +++++- src/libs/vtools/dialogs/tools/dialogtool.cpp | 7 + src/libs/vtools/dialogs/tools/dialogtool.h | 2 + .../flipping/vtoolflippingbyaxis.cpp | 1 + .../flipping/vtoolflippingbyline.cpp | 1 + .../operation/vabstractoperation.cpp | 12 +- .../drawTools/operation/vabstractoperation.h | 3 + .../tools/drawTools/operation/vtoolmove.cpp | 1 + .../drawTools/operation/vtoolrotation.cpp | 1 + src/libs/vtools/undocommands/undogroup.cpp | 32 +++++ src/libs/vtools/undocommands/undogroup.h | 19 +++ src/libs/vwidgets/vlineedit.cpp | 122 ++++++++++++++++++ src/libs/vwidgets/vlineedit.h | 29 +++++ 36 files changed, 793 insertions(+), 59 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 193cfe0d0..74b331d2f 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -46,6 +46,7 @@ - [smart-pattern/valentina#18] Auto-created Visibility Group for group operation. - Setting scale factor for export and print. - New layout generator option: Prefer one sheet solution. +- [smart-pattern/valentina#15] Organization of groups - groups categories # Version 0.6.2 (unreleased) - [#903] Bug in tool Cut Spline path. diff --git a/src/app/valentina/dialogs/vwidgetgroups.cpp b/src/app/valentina/dialogs/vwidgetgroups.cpp index af69c55e4..17d09e1a9 100644 --- a/src/app/valentina/dialogs/vwidgetgroups.cpp +++ b/src/app/valentina/dialogs/vwidgetgroups.cpp @@ -31,7 +31,9 @@ #include "../vtools/dialogs/tools/dialoggroup.h" #include "../vtools/undocommands/undogroup.h" #include "../vpatterndb/vcontainer.h" +#include "../vmisc/compatibility.h" +#include #include #include @@ -51,6 +53,7 @@ VWidgetGroups::VWidgetGroups(VAbstractPattern *doc, QWidget *parent) connect(ui->tableWidget, &QTableWidget::cellClicked, this, &VWidgetGroups::GroupVisibilityChanged); connect(ui->tableWidget, &QTableWidget::cellChanged, this, &VWidgetGroups::RenameGroup); connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, &VWidgetGroups::CtxMenu); + connect(ui->lineEditTags, &QLineEdit::textChanged, this, &VWidgetGroups::UpdateGroups); } //--------------------------------------------------------------------------------------------------------------------- @@ -110,6 +113,32 @@ void VWidgetGroups::SetMultipleGroupsVisibility(const QVector &groups, qApp->getUndoStack()->push(changeGroups); } +//--------------------------------------------------------------------------------------------------------------------- +QMap VWidgetGroups::FilterGroups(const QMap &groups) +{ + QMap filtered; + QSet filterCategories = ConvertToSet(VAbstractPattern::FilterGroupTags(ui->lineEditTags->text())); + + if (filterCategories.isEmpty()) + { + return groups; + } + + auto i = groups.constBegin(); + while (i != groups.constEnd()) + { + const VGroupData &data = i.value(); + QSet groupCategories = ConvertToSet(data.tags); + if (SetIntersects(filterCategories, groupCategories)) + { + filtered.insert(i.key(), data); + } + ++i; + } + + return filtered; +} + //--------------------------------------------------------------------------------------------------------------------- int VWidgetGroups::GroupRow(vidtype id) const { @@ -185,7 +214,7 @@ void VWidgetGroups::CtxMenu(const QPoint &pos) menu->addAction(QIcon(QStringLiteral("://icon/16x16/closed_eye.png")), tr("Hide")) : menu->addAction(QIcon(QStringLiteral("://icon/16x16/open_eye.png")), tr("Show")); - QAction *actionRename = menu->addAction(tr("Rename")); + QAction *actionPreferences = menu->addAction(QIcon::fromTheme(preferencesOtherIcon), tr("Preferences")); QAction *actionDelete = menu->addAction(QIcon::fromTheme(editDeleteIcon), tr("Delete")); menu->addSeparator(); QAction *actionHideAll = menu->addAction(tr("Hide All")); @@ -199,19 +228,22 @@ void VWidgetGroups::CtxMenu(const QPoint &pos) { SetGroupVisibility(id, not doc->GetGroupVisibility(id)); } - else if (selectedAction == actionRename) + else if (selectedAction == actionPreferences) { QScopedPointer fackeContainer(new VContainer(qApp->TrVars(), qApp->patternUnitP(), VContainer::UniqueNamespace())); QScopedPointer dialog(new DialogGroup(fackeContainer.data(), NULL_ID, this)); dialog->SetName(doc->GetGroupName(id)); + dialog->SetTags(doc->GetGroupTags(id)); + dialog->SetGroupCategories(doc->GetGroupCategories()); const int result = dialog->exec(); if (result == QDialog::Accepted) { - ::RenameGroup *renameGroup = new ::RenameGroup(doc, id, dialog->GetName()); - connect(renameGroup, &RenameGroup::UpdateGroups, this, &VWidgetGroups::UpdateGroups); - qApp->getUndoStack()->push(renameGroup); + ChangeGroupOptions *changeGroupOptions = new ChangeGroupOptions(doc, id, dialog->GetName(), + dialog->GetTags()); + connect(changeGroupOptions, &ChangeGroupOptions::UpdateGroups, this, &VWidgetGroups::UpdateGroups); + qApp->getUndoStack()->push(changeGroupOptions); } } else if (selectedAction == actionDelete) @@ -277,9 +309,13 @@ void VWidgetGroups::UpdateGroups() } //--------------------------------------------------------------------------------------------------------------------- -void VWidgetGroups::FillTable(const QMap > &groups) +void VWidgetGroups::FillTable(QMap groups) { emit doc->UpdateToolTip(); + ui->lineEditTags->SetCompletion(doc->GetGroupCategories()); + + groups = FilterGroups(groups); + ui->tableWidget->blockSignals(true); ui->tableWidget->clear(); @@ -290,12 +326,12 @@ void VWidgetGroups::FillTable(const QMap > &groups while (i != groups.constEnd()) { ++currentRow; - const QPair data = i.value(); + const VGroupData data = i.value(); QTableWidgetItem *item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignHCenter); - (data.second) ? item->setIcon(QIcon("://icon/16x16/open_eye.png")) - : item->setIcon(QIcon("://icon/16x16/closed_eye.png")); + (data.visible) ? item->setIcon(QIcon("://icon/16x16/open_eye.png")) + : item->setIcon(QIcon("://icon/16x16/closed_eye.png")); item->setData(Qt::UserRole, i.key()); @@ -306,8 +342,9 @@ void VWidgetGroups::FillTable(const QMap > &groups ui->tableWidget->setItem(currentRow, 0, item); - item = new QTableWidgetItem(data.first); + item = new QTableWidgetItem(data.name); item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); + item->setToolTip(tr("Categories: %1.").arg(data.tags.join(", "))); if(doc->GroupIsEmpty(i.key())) { diff --git a/src/app/valentina/dialogs/vwidgetgroups.h b/src/app/valentina/dialogs/vwidgetgroups.h index 0d0838a68..ba4e0f17c 100644 --- a/src/app/valentina/dialogs/vwidgetgroups.h +++ b/src/app/valentina/dialogs/vwidgetgroups.h @@ -34,6 +34,7 @@ class QTableWidgetItem; class VAbstractPattern; +struct VGroupData; namespace Ui { @@ -61,10 +62,12 @@ private: Ui::VWidgetGroups *ui; VAbstractPattern *doc; - void FillTable(const QMap > &groups); + void FillTable(QMap groups); void SetGroupVisibility(vidtype id, bool visible) const; void SetMultipleGroupsVisibility(const QVector &groups, bool visible) const; + QMap FilterGroups(const QMap &groups); + int GroupRow(vidtype id) const; }; diff --git a/src/app/valentina/dialogs/vwidgetgroups.ui b/src/app/valentina/dialogs/vwidgetgroups.ui index 006e30e6c..3a3ee72f3 100644 --- a/src/app/valentina/dialogs/vwidgetgroups.ui +++ b/src/app/valentina/dialogs/vwidgetgroups.ui @@ -7,7 +7,7 @@ 0 0 371 - 279 + 438 @@ -18,6 +18,30 @@ :/icon/64x64/icon64x64.png:/icon/64x64/icon64x64.png + + + + + + Tags: + + + + + + + Separate each tag with comma. + + + Filter by tags + + + true + + + + + @@ -47,16 +71,23 @@ false - - false - 10 + + false + + + + VCompleterLineEdit + QLineEdit +
vlineedit.h
+
+
diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index 8dc9b5c75..ffef16f93 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -648,6 +648,11 @@ void MainWindow::SetToolButton(bool checked, Tool t, const QString &cursor, cons case Tool::PlaceLabel: dialogTool->SetPiecesList(doc->GetActivePPPieces()); break; + case Tool::Rotation: + case Tool::Move: + case Tool::FlippingByAxis: + case Tool::FlippingByLine: + dialogTool->SetGroupCategories(doc->GetGroupCategories()); default: break; } @@ -1241,7 +1246,8 @@ void MainWindow::ClosedDialogGroup(int result) { const QPointer dialog = qobject_cast(dialogTool); SCASSERT(not dialog.isNull()) - const QDomElement group = doc->CreateGroup(pattern->getNextId(), dialog->GetName(), dialog->GetGroup()); + const QDomElement group = doc->CreateGroup(pattern->getNextId(), dialog->GetName(), dialog->GetTags(), + dialog->GetGroup()); if (not group.isNull()) { AddGroup *addGroup = new AddGroup(group, doc); diff --git a/src/libs/ifc/schema/pattern/v0.8.7.xsd b/src/libs/ifc/schema/pattern/v0.8.7.xsd index 7518ebdb6..26e7571a0 100644 --- a/src/libs/ifc/schema/pattern/v0.8.7.xsd +++ b/src/libs/ifc/schema/pattern/v0.8.7.xsd @@ -800,6 +800,7 @@ + diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp index 9fcd24466..c45c7a026 100644 --- a/src/libs/ifc/xml/vabstractpattern.cpp +++ b/src/libs/ifc/xml/vabstractpattern.cpp @@ -135,7 +135,8 @@ const QString VAbstractPattern::AttrNumber = QStringLiteral("number") const QString VAbstractPattern::AttrCheckUniqueness = QStringLiteral("checkUniqueness"); const QString VAbstractPattern::AttrManualPassmarkLength = QStringLiteral("manualPassmarkLength"); const QString VAbstractPattern::AttrPassmarkLength = QStringLiteral("passmarkLength"); -const QString VAbstractPattern::AttrOpacity = QStringLiteral("opacity"); +const QString VAbstractPattern::AttrOpacity = QStringLiteral("opacity"); +const QString VAbstractPattern::AttrTags = QStringLiteral("tags"); const QString VAbstractPattern::AttrAll = QStringLiteral("all"); @@ -283,6 +284,17 @@ QMap AdjustMaterials(QMap materials) return materials; } + +//--------------------------------------------------------------------------------------------------------------------- +QString PrepareGroupTags(QStringList tags) +{ + for (auto &tag : tags) + { + tag = tag.simplified(); + } + + return ConvertToList(ConvertToSet(tags)).join(','); +} } //--------------------------------------------------------------------------------------------------------------------- @@ -2428,19 +2440,22 @@ QDomElement VAbstractPattern::CreateGroups() } //--------------------------------------------------------------------------------------------------------------------- -QDomElement VAbstractPattern::CreateGroup(quint32 id, const QString &name, const QMap &groupData, - vidtype tool) +QDomElement VAbstractPattern::CreateGroup(quint32 id, const QString &name, const QStringList &tags, + const QMap &groupData, vidtype tool) { if (id == NULL_ID || groupData.isEmpty()) { return QDomElement(); } + const QString preparedTags = PrepareGroupTags(tags); + QDomElement group = createElement(TagGroup); SetAttribute(group, AttrId, id); SetAttribute(group, AttrName, name); SetAttribute(group, AttrVisible, true); SetAttributeOrRemoveIf(group, AttrTool, tool, tool == null_id); + SetAttributeOrRemoveIf(group, AttrTags, preparedTags, preparedTags.isEmpty()); auto i = groupData.constBegin(); while (i != groupData.constEnd()) @@ -2502,9 +2517,54 @@ void VAbstractPattern::SetGroupName(quint32 id, const QString &name) } //--------------------------------------------------------------------------------------------------------------------- -QMap > VAbstractPattern::GetGroups() +QStringList VAbstractPattern::GetGroupTags(vidtype id) { - QMap > data; + QStringList tags; + QDomElement group = elementById(id, TagGroup); + if (group.isElement()) + { + tags = FilterGroupTags(GetParametrEmptyString(group, AttrTags)); + } + + return tags; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractPattern::SetGroupTags(quint32 id, const QStringList &tags) +{ + QDomElement group = elementById(id, TagGroup); + if (group.isElement()) + { + const QString rawTags = tags.join(','); + SetAttributeOrRemoveIf(group, AttrTags, rawTags, rawTags.isEmpty()); + modified = true; + emit patternChanged(false); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList VAbstractPattern::GetGroupCategories() const +{ + QSet categories; + + const QDomNodeList groups = elementsByTagName(TagGroup); + for (int i=0; i < groups.size(); ++i) + { + const QDomElement group = groups.at(i).toElement(); + if (not group.isNull() && group.hasAttribute(AttrTags)) + { + QStringList groupTags = VAbstractPattern::FilterGroupTags(GetParametrEmptyString(group, AttrTags)); + categories.unite(ConvertToSet(groupTags)); + } + } + + return ConvertToList(categories); +} + +//--------------------------------------------------------------------------------------------------------------------- +QMap VAbstractPattern::GetGroups() +{ + QMap data; try { @@ -2521,11 +2581,13 @@ QMap > VAbstractPattern::GetGroups() { if (group.tagName() == TagGroup) { + VGroupData groupData; const quint32 id = GetParametrUInt(group, AttrId, QChar('0')); - const bool visible = GetParametrBool(group, AttrVisible, trueStr); - const QString name = GetParametrString(group, AttrName, tr("New group")); + groupData.visible = GetParametrBool(group, AttrVisible, trueStr); + groupData.name = GetParametrString(group, AttrName, tr("New group")); + groupData.tags = FilterGroupTags(GetParametrEmptyString(group, AttrTags)); - data.insert(id, qMakePair(name, visible)); + data.insert(id, groupData); } } } @@ -2539,7 +2601,7 @@ QMap > VAbstractPattern::GetGroups() } catch (const VExceptionConversionError &) { - return QMap >(); + return QMap(); } return data; @@ -2796,3 +2858,22 @@ QString VAbstractPattern::PieceDrawName(quint32 id) return draw.attribute(VAbstractPattern::AttrName); } + +//--------------------------------------------------------------------------------------------------------------------- +QStringList VAbstractPattern::FilterGroupTags(const QString &tags) +{ + if (tags.isEmpty()) + { + return QStringList(); + } + + QStringList list = tags.split(','); + for (auto &tag : list) + { + tag = tag.simplified(); + } + + list.removeAll(""); + + return ConvertToList(ConvertToSet(list)); +} diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h index b09cc2be5..6a3b7a981 100644 --- a/src/libs/ifc/xml/vabstractpattern.h +++ b/src/libs/ifc/xml/vabstractpattern.h @@ -78,6 +78,13 @@ struct VFinalMeasurement QString description; }; +struct VGroupData +{ + QString name{}; + bool visible{true}; + QStringList tags{}; +}; + QT_WARNING_POP class VAbstractPattern : public VDomDocument @@ -200,18 +207,27 @@ public: void ParseGroups(const QDomElement &domElement); QDomElement CreateGroups(); - QDomElement CreateGroup(quint32 id, const QString &name, const QMap &groupData, - vidtype tool=null_id); + QDomElement CreateGroup(quint32 id, const QString &name, const QStringList &tags, + const QMap &groupData, vidtype tool=null_id); vidtype GroupLinkedToTool(vidtype toolId) const; + QString GetGroupName(quint32 id); void SetGroupName(quint32 id, const QString &name); - QMap > GetGroups(); + + QStringList GetGroupTags(vidtype id); + void SetGroupTags(quint32 id, const QStringList &tags); + + QStringList GetGroupCategories() const; + + QMap GetGroups(); QMap GetGroupsContainingItem(quint32 toolId, quint32 objectId, bool containItem); QDomElement AddItemToGroup(quint32 toolId, quint32 objectId, quint32 groupId); QDomElement RemoveItemFromGroup(quint32 toolId, quint32 objectId, quint32 groupId); bool GroupIsEmpty(quint32 id); bool GetGroupVisibility(quint32 id); + static QStringList FilterGroupTags(const QString &tags); + QString PieceDrawName(quint32 id); static const QString TagPattern; @@ -290,6 +306,7 @@ public: static const QString AttrManualPassmarkLength; static const QString AttrPassmarkLength; static const QString AttrOpacity; + static const QString AttrTags; static const QString AttrAll; diff --git a/src/libs/vmisc/compatibility.h b/src/libs/vmisc/compatibility.h index 982f3ed91..f00bdccf0 100644 --- a/src/libs/vmisc/compatibility.h +++ b/src/libs/vmisc/compatibility.h @@ -195,4 +195,27 @@ inline void AppendTo(Cont &container, const Input &input) #endif // QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) } +//--------------------------------------------------------------------------------------------------------------------- +template +inline bool SetIntersects(const QSet &set1, const QSet &set2) +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + return set1.intersects(set2); +#else + const bool otherIsBigger = set2.size() > set1.size(); + const QSet &smallestSet = otherIsBigger ? set1 : set2; + const QSet &biggestSet = otherIsBigger ? set2 : set1; + typename QSet::const_iterator i = smallestSet.cbegin(); + typename QSet::const_iterator e = smallestSet.cend(); + while (i != e) + { + if (biggestSet.contains(*i)) + return true; + ++i; + } + return false; + +#endif +} + #endif // COMPATIBILITY_H diff --git a/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.cpp b/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.cpp index 00b70fc59..e370fc820 100644 --- a/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.cpp +++ b/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -173,6 +174,25 @@ void DialogFlippingByAxis::SetHasLinkedVisibilityGroup(bool linked) ui->groupBoxVisibilityGroup->setChecked(linked); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogFlippingByAxis::SetVisibilityGroupTags(const QStringList &tags) +{ + ui->lineEditGroupTags->setText(tags.join(", ")); +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList DialogFlippingByAxis::GetVisibilityGroupTags() const +{ + return ui->lineEditGroupTags->text().split(','); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogFlippingByAxis::SetGroupCategories(const QStringList &categories) +{ + m_groupTags = categories; + ui->lineEditGroupTags->SetCompletion(m_groupTags); +} + //--------------------------------------------------------------------------------------------------------------------- void DialogFlippingByAxis::ShowDialog(bool click) { @@ -342,6 +362,18 @@ void DialogFlippingByAxis::SaveData() operation->SetOriginPointId(GetOriginPointId()); operation->SetAxisType(GetAxisType()); operation->RefreshGeometry(); + + QStringList groupTags = ui->lineEditGroupTags->text().split(','); + for (auto &tag : groupTags) + { + tag = tag.trimmed(); + if (not m_groupTags.contains(tag)) + { + m_groupTags.append(tag); + } + } + + ui->lineEditGroupTags->SetCompletion(m_groupTags); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.h b/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.h index 680ceb517..234261fe0 100644 --- a/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.h +++ b/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.h @@ -71,6 +71,11 @@ public: bool HasLinkedVisibilityGroup() const; void SetHasLinkedVisibilityGroup(bool linked); + void SetVisibilityGroupTags(const QStringList &tags); + QStringList GetVisibilityGroupTags() const; + + virtual void SetGroupCategories(const QStringList &categories) override; + virtual void ShowDialog(bool click) override; public slots: @@ -106,6 +111,8 @@ private: bool flagGroupName; bool flagError; + QStringList m_groupTags{}; + static void FillComboBoxAxisType(QComboBox *box); }; diff --git a/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.ui b/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.ui index fc4491b3c..9ebf2e47f 100644 --- a/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.ui +++ b/src/libs/vtools/dialogs/tools/dialogflippingbyaxis.ui @@ -7,7 +7,7 @@ 0 0 304 - 207 + 237 @@ -62,15 +62,15 @@ false - - + + Name: - + Flipping by axis @@ -80,6 +80,26 @@ + + + + Tags: + + + + + + + Separate each tag with comma. + + + Add tags + + + true + + + @@ -95,6 +115,13 @@ + + + VCompleterLineEdit + QLineEdit +
vlineedit.h
+
+
diff --git a/src/libs/vtools/dialogs/tools/dialogflippingbyline.cpp b/src/libs/vtools/dialogs/tools/dialogflippingbyline.cpp index 3f98b32ae..9532bd364 100644 --- a/src/libs/vtools/dialogs/tools/dialogflippingbyline.cpp +++ b/src/libs/vtools/dialogs/tools/dialogflippingbyline.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -168,6 +169,25 @@ void DialogFlippingByLine::SetHasLinkedVisibilityGroup(bool linked) ui->groupBoxVisibilityGroup->setChecked(linked); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogFlippingByLine::SetVisibilityGroupTags(const QStringList &tags) +{ + ui->lineEditGroupTags->setText(tags.join(", ")); +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList DialogFlippingByLine::GetVisibilityGroupTags() const +{ + return ui->lineEditGroupTags->text().split(','); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogFlippingByLine::SetGroupCategories(const QStringList &categories) +{ + m_groupTags = categories; + ui->lineEditGroupTags->SetCompletion(m_groupTags); +} + //--------------------------------------------------------------------------------------------------------------------- void DialogFlippingByLine::ShowDialog(bool click) { @@ -366,6 +386,18 @@ void DialogFlippingByLine::SaveData() operation->SetFirstLinePointId(GetFirstLinePointId()); operation->SetSecondLinePointId(GetSecondLinePointId()); operation->RefreshGeometry(); + + QStringList groupTags = ui->lineEditGroupTags->text().split(','); + for (auto &tag : groupTags) + { + tag = tag.trimmed(); + if (not m_groupTags.contains(tag)) + { + m_groupTags.append(tag); + } + } + + ui->lineEditGroupTags->SetCompletion(m_groupTags); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogflippingbyline.h b/src/libs/vtools/dialogs/tools/dialogflippingbyline.h index be12128b6..27a4314a2 100644 --- a/src/libs/vtools/dialogs/tools/dialogflippingbyline.h +++ b/src/libs/vtools/dialogs/tools/dialogflippingbyline.h @@ -71,6 +71,11 @@ public: bool HasLinkedVisibilityGroup() const; void SetHasLinkedVisibilityGroup(bool linked); + void SetVisibilityGroupTags(const QStringList &tags); + QStringList GetVisibilityGroupTags() const; + + virtual void SetGroupCategories(const QStringList &categories) override; + virtual void ShowDialog(bool click) override; public slots: @@ -105,6 +110,8 @@ private: bool flagName; bool flagGroupName; bool flagError; + + QStringList m_groupTags{}; }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogflippingbyline.ui b/src/libs/vtools/dialogs/tools/dialogflippingbyline.ui index 7fa0ffcc0..788368f5c 100644 --- a/src/libs/vtools/dialogs/tools/dialogflippingbyline.ui +++ b/src/libs/vtools/dialogs/tools/dialogflippingbyline.ui @@ -7,7 +7,7 @@ 0 0 304 - 207 + 237
@@ -66,15 +66,15 @@ false - - + + Name: - + Flipping by line @@ -84,6 +84,26 @@ + + + + Tags: + + + + + + + Separate each tag with comma. + + + Add tags + + + true + + + @@ -99,6 +119,13 @@ + + + VCompleterLineEdit + QLineEdit +
vlineedit.h
+
+
diff --git a/src/libs/vtools/dialogs/tools/dialoggroup.cpp b/src/libs/vtools/dialogs/tools/dialoggroup.cpp index 8aad034bf..3b5f4a713 100644 --- a/src/libs/vtools/dialogs/tools/dialoggroup.cpp +++ b/src/libs/vtools/dialogs/tools/dialoggroup.cpp @@ -28,6 +28,7 @@ #include "dialoggroup.h" +#include #include #include "ui_dialoggroup.h" @@ -63,6 +64,24 @@ QString DialogGroup::GetName() const return ui->lineEditName->text(); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogGroup::SetTags(const QStringList &tags) +{ + ui->lineEditTags->setText(tags.join(", ")); +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList DialogGroup::GetTags() const +{ + return ui->lineEditTags->text().split(","); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogGroup::SetGroupCategories(const QStringList &categories) +{ + ui->lineEditTags->SetCompletion(categories); +} + //--------------------------------------------------------------------------------------------------------------------- void DialogGroup::ShowDialog(bool click) { diff --git a/src/libs/vtools/dialogs/tools/dialoggroup.h b/src/libs/vtools/dialogs/tools/dialoggroup.h index ec0efd4c9..5872b943e 100644 --- a/src/libs/vtools/dialogs/tools/dialoggroup.h +++ b/src/libs/vtools/dialogs/tools/dialoggroup.h @@ -54,6 +54,11 @@ public: void SetName(const QString &name); QString GetName() const; + void SetTags(const QStringList &tags); + QStringList GetTags() const; + + void SetGroupCategories(const QStringList &categories); + QMap GetGroup() const; virtual void ShowDialog(bool click) override; diff --git a/src/libs/vtools/dialogs/tools/dialoggroup.ui b/src/libs/vtools/dialogs/tools/dialoggroup.ui index 3983b99f8..436f2229f 100644 --- a/src/libs/vtools/dialogs/tools/dialoggroup.ui +++ b/src/libs/vtools/dialogs/tools/dialoggroup.ui @@ -6,8 +6,8 @@ 0 0 - 397 - 80 + 294 + 104
@@ -19,22 +19,45 @@ - - + + Group name: - + - Unique pattern piece name + Choose group name + + true + + + + + + + Tags: + + + + + + + Separate each tag with comma. + + + Add tags + + + true + @@ -51,6 +74,13 @@ + + + VCompleterLineEdit + QLineEdit +
vlineedit.h
+
+
diff --git a/src/libs/vtools/dialogs/tools/dialogmove.cpp b/src/libs/vtools/dialogs/tools/dialogmove.cpp index 2d84a78b8..c079a97a5 100644 --- a/src/libs/vtools/dialogs/tools/dialogmove.cpp +++ b/src/libs/vtools/dialogs/tools/dialogmove.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -283,6 +284,25 @@ void DialogMove::SetHasLinkedVisibilityGroup(bool linked) ui->groupBoxVisibilityGroup->setChecked(linked); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogMove::SetVisibilityGroupTags(const QStringList &tags) +{ + ui->lineEditGroupTags->setText(tags.join(", ")); +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList DialogMove::GetVisibilityGroupTags() const +{ + return ui->lineEditGroupTags->text().split(','); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogMove::SetGroupCategories(const QStringList &categories) +{ + m_groupTags = categories; + ui->lineEditGroupTags->SetCompletion(m_groupTags); +} + //--------------------------------------------------------------------------------------------------------------------- void DialogMove::ShowDialog(bool click) { @@ -551,6 +571,18 @@ void DialogMove::SaveData() operation->SetRotationAngle(formulaRotationAngle); operation->SetRotationOriginPointId(GetRotationOrigPointId()); operation->RefreshGeometry(); + + QStringList groupTags = ui->lineEditGroupTags->text().split(','); + for (auto &tag : groupTags) + { + tag = tag.trimmed(); + if (not m_groupTags.contains(tag)) + { + m_groupTags.append(tag); + } + } + + ui->lineEditGroupTags->SetCompletion(m_groupTags); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogmove.h b/src/libs/vtools/dialogs/tools/dialogmove.h index 8a6c582a5..741d8d144 100644 --- a/src/libs/vtools/dialogs/tools/dialogmove.h +++ b/src/libs/vtools/dialogs/tools/dialogmove.h @@ -76,6 +76,11 @@ public: bool HasLinkedVisibilityGroup() const; void SetHasLinkedVisibilityGroup(bool linked); + void SetVisibilityGroupTags(const QStringList &tags); + QStringList GetVisibilityGroupTags() const; + + virtual void SetGroupCategories(const QStringList &categories) override; + virtual void ShowDialog(bool click) override; public slots: @@ -138,6 +143,8 @@ private: bool flagName; bool flagGroupName; + QStringList m_groupTags{}; + void EvalAngle(); void EvalRotationAngle(); void EvalLength(); diff --git a/src/libs/vtools/dialogs/tools/dialogmove.ui b/src/libs/vtools/dialogs/tools/dialogmove.ui index d662c530e..defd52ef1 100644 --- a/src/libs/vtools/dialogs/tools/dialogmove.ui +++ b/src/libs/vtools/dialogs/tools/dialogmove.ui @@ -6,8 +6,8 @@ 0 0 - 304 - 402 + 424 + 432 @@ -605,15 +605,15 @@ false - - + + Name: - + Move @@ -623,6 +623,26 @@ + + + + Tags: + + + + + + + Separate each tag with comma. + + + Add tags + + + true + + + @@ -639,6 +659,11 @@ + + VCompleterLineEdit + QLineEdit +
vlineedit.h
+
VPlainTextEdit QPlainTextEdit diff --git a/src/libs/vtools/dialogs/tools/dialogrotation.cpp b/src/libs/vtools/dialogs/tools/dialogrotation.cpp index fd34ee534..306477be9 100644 --- a/src/libs/vtools/dialogs/tools/dialogrotation.cpp +++ b/src/libs/vtools/dialogs/tools/dialogrotation.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -196,6 +197,25 @@ void DialogRotation::SetHasLinkedVisibilityGroup(bool linked) ui->groupBoxVisibilityGroup->setChecked(linked); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogRotation::SetVisibilityGroupTags(const QStringList &tags) +{ + ui->lineEditGroupTags->setText(tags.join(", ")); +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList DialogRotation::GetVisibilityGroupTags() const +{ + return ui->lineEditGroupTags->text().split(','); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogRotation::SetGroupCategories(const QStringList &categories) +{ + m_groupTags = categories; + ui->lineEditGroupTags->SetCompletion(m_groupTags); +} + //--------------------------------------------------------------------------------------------------------------------- void DialogRotation::ShowDialog(bool click) { @@ -432,6 +452,18 @@ void DialogRotation::SaveData() operation->SetOriginPointId(GetOrigPointId()); operation->SetAngle(formulaAngle); operation->RefreshGeometry(); + + QStringList groupTags = ui->lineEditGroupTags->text().split(','); + for (auto &tag : groupTags) + { + tag = tag.trimmed(); + if (not m_groupTags.contains(tag)) + { + m_groupTags.append(tag); + } + } + + ui->lineEditGroupTags->SetCompletion(m_groupTags); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogrotation.h b/src/libs/vtools/dialogs/tools/dialogrotation.h index 285c3113f..89b1221d5 100644 --- a/src/libs/vtools/dialogs/tools/dialogrotation.h +++ b/src/libs/vtools/dialogs/tools/dialogrotation.h @@ -69,6 +69,11 @@ public: bool HasLinkedVisibilityGroup() const; void SetHasLinkedVisibilityGroup(bool linked); + void SetVisibilityGroupTags(const QStringList &tags); + QStringList GetVisibilityGroupTags() const; + + virtual void SetGroupCategories(const QStringList &categories) override; + virtual void ShowDialog(bool click) override; public slots: @@ -120,6 +125,8 @@ private: bool flagName; bool flagGroupName; bool flagError; + + QStringList m_groupTags{}; }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogrotation.ui b/src/libs/vtools/dialogs/tools/dialogrotation.ui index 260c0e9e5..84bc08968 100644 --- a/src/libs/vtools/dialogs/tools/dialogrotation.ui +++ b/src/libs/vtools/dialogs/tools/dialogrotation.ui @@ -7,7 +7,7 @@ 0 0 392 - 252 + 282
@@ -236,18 +236,38 @@ false - - + + + + + Tags: + + + + + + + Rotation + + + true + + + + Name: - - - - Rotation + + + + Separate each tag with comma. + + + Add tags true @@ -270,6 +290,11 @@ + + VCompleterLineEdit + QLineEdit +
vlineedit.h
+
VPlainTextEdit QPlainTextEdit diff --git a/src/libs/vtools/dialogs/tools/dialogtool.cpp b/src/libs/vtools/dialogs/tools/dialogtool.cpp index 2e69eb12c..ee514bfd0 100644 --- a/src/libs/vtools/dialogs/tools/dialogtool.cpp +++ b/src/libs/vtools/dialogs/tools/dialogtool.cpp @@ -799,6 +799,13 @@ void DialogTool::SetToolId(const quint32 &value) toolId = value; } +//--------------------------------------------------------------------------------------------------------------------- +void DialogTool::SetGroupCategories(const QStringList &categories) +{ + Q_UNUSED(categories) + // do nothing +} + //--------------------------------------------------------------------------------------------------------------------- void DialogTool::ShowDialog(bool click) { diff --git a/src/libs/vtools/dialogs/tools/dialogtool.h b/src/libs/vtools/dialogs/tools/dialogtool.h index 46e3775ae..c13c54651 100644 --- a/src/libs/vtools/dialogs/tools/dialogtool.h +++ b/src/libs/vtools/dialogs/tools/dialogtool.h @@ -90,6 +90,8 @@ public: quint32 GetToolId() const; void SetToolId(const quint32 &value); + virtual void SetGroupCategories(const QStringList &categories); + static void MoveListRowTop(QListWidget *list); static void MoveListRowUp(QListWidget *list); static void MoveListRowDown(QListWidget *list); diff --git a/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyaxis.cpp b/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyaxis.cpp index 5268f01f8..ca558230f 100644 --- a/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyaxis.cpp +++ b/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyaxis.cpp @@ -93,6 +93,7 @@ VToolFlippingByAxis *VToolFlippingByAxis::Create(const QPointer &dia initData.source = dialogTool->GetObjects(); initData.hasLinkedVisibilityGroup = dialogTool->HasLinkedVisibilityGroup(); initData.visibilityGroupName = dialogTool->GetVisibilityGroupName(); + initData.visibilityGroupTags = dialogTool->GetVisibilityGroupTags(); initData.scene = scene; initData.doc = doc; initData.data = data; diff --git a/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyline.cpp b/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyline.cpp index dcefbe79e..e862a99b7 100644 --- a/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyline.cpp +++ b/src/libs/vtools/tools/drawTools/operation/flipping/vtoolflippingbyline.cpp @@ -93,6 +93,7 @@ VToolFlippingByLine *VToolFlippingByLine::Create(const QPointer &dia initData.source = dialogTool->GetObjects(); initData.hasLinkedVisibilityGroup = dialogTool->HasLinkedVisibilityGroup(); initData.visibilityGroupName = dialogTool->GetVisibilityGroupName(); + initData.visibilityGroupTags = dialogTool->GetVisibilityGroupTags(); initData.scene = scene; initData.doc = doc; initData.data = data; diff --git a/src/libs/vtools/tools/drawTools/operation/vabstractoperation.cpp b/src/libs/vtools/tools/drawTools/operation/vabstractoperation.cpp index 53c76dc0c..e3b72e2fa 100644 --- a/src/libs/vtools/tools/drawTools/operation/vabstractoperation.cpp +++ b/src/libs/vtools/tools/drawTools/operation/vabstractoperation.cpp @@ -609,9 +609,9 @@ void VAbstractOperation::ApplyToolOptions(const QList &oldDependencies, { if (group != null_id) { - RenameGroup *renameGroup = new RenameGroup(doc, group, groupName); - connect(renameGroup, &RenameGroup::UpdateGroups, doc, &VAbstractPattern::UpdateVisiblityGroups); - qApp->getUndoStack()->push(renameGroup); + ChangeGroupOptions *groupOptions = new ChangeGroupOptions(doc, group, groupName, groupTags); + connect(groupOptions, &ChangeGroupOptions::UpdateGroups, doc, &VAbstractPattern::UpdateVisiblityGroups); + qApp->getUndoStack()->push(groupOptions); } else { @@ -619,6 +619,7 @@ void VAbstractOperation::ApplyToolOptions(const QList &oldDependencies, initData.id = m_id; initData.hasLinkedVisibilityGroup = hasLinkedGroup; initData.visibilityGroupName = groupName; + initData.visibilityGroupTags = groupTags; initData.data = &(VDataTool::data); initData.doc = doc; initData.source = source; @@ -790,7 +791,7 @@ bool VAbstractOperation::NeedUpdateVisibilityGroup() const { if (group != null_id) { - if (groupName != doc->GetGroupName(group)) + if (groupName != doc->GetGroupName(group) || groupTags != doc->GetGroupTags(group)) { return true; // rename group } @@ -916,7 +917,8 @@ void VAbstractOperation::CreateVisibilityGroup(const VAbstractOperationInitData const QMap groupData = VisibilityGroupDataFromSource(initData.data, initData.source); vidtype groupId = initData.data->getNextId(); - const QDomElement group = initData.doc->CreateGroup(groupId, initData.visibilityGroupName, groupData, initData.id); + const QDomElement group = initData.doc->CreateGroup(groupId, initData.visibilityGroupName, + initData.visibilityGroupTags, groupData, initData.id); if (not group.isNull()) { AddGroup *addGroup = new AddGroup(group, initData.doc); diff --git a/src/libs/vtools/tools/drawTools/operation/vabstractoperation.h b/src/libs/vtools/tools/drawTools/operation/vabstractoperation.h index dcb8bcdd8..926411a72 100644 --- a/src/libs/vtools/tools/drawTools/operation/vabstractoperation.h +++ b/src/libs/vtools/tools/drawTools/operation/vabstractoperation.h @@ -60,6 +60,7 @@ struct VAbstractOperationInitData : VAbstractToolInitData QVector source{}; QVector destination{}; QString visibilityGroupName{}; + QStringList visibilityGroupTags{}; bool hasLinkedVisibilityGroup{false}; }; @@ -134,6 +135,7 @@ protected: bool hasLinkedGroup{false}; QString groupName{}; + QStringList groupTags{}; VAbstractOperation(VAbstractPattern *doc, VContainer *data, quint32 id, const QString &suffix, const QVector &source, const QVector &destination, @@ -187,6 +189,7 @@ void VAbstractOperation::SetDialogVisibilityGroupData(QPointer dialogTool) { dialogTool->SetHasLinkedVisibilityGroup(true); dialogTool->SetVisibilityGroupName(doc->GetGroupName(group)); + dialogTool->SetVisibilityGroupTags(doc->GetGroupTags(group)); } else { diff --git a/src/libs/vtools/tools/drawTools/operation/vtoolmove.cpp b/src/libs/vtools/tools/drawTools/operation/vtoolmove.cpp index c0b641bf9..24c5bf9b4 100644 --- a/src/libs/vtools/tools/drawTools/operation/vtoolmove.cpp +++ b/src/libs/vtools/tools/drawTools/operation/vtoolmove.cpp @@ -149,6 +149,7 @@ VToolMove *VToolMove::Create(const QPointer &dialog, VMainGraphicsSc initData.source = dialogTool->GetObjects(); initData.hasLinkedVisibilityGroup = dialogTool->HasLinkedVisibilityGroup(); initData.visibilityGroupName = dialogTool->GetVisibilityGroupName(); + initData.visibilityGroupTags = dialogTool->GetVisibilityGroupTags(); initData.scene = scene; initData.doc = doc; initData.data = data; diff --git a/src/libs/vtools/tools/drawTools/operation/vtoolrotation.cpp b/src/libs/vtools/tools/drawTools/operation/vtoolrotation.cpp index 85d18f76e..1d4428f33 100644 --- a/src/libs/vtools/tools/drawTools/operation/vtoolrotation.cpp +++ b/src/libs/vtools/tools/drawTools/operation/vtoolrotation.cpp @@ -117,6 +117,7 @@ VToolRotation *VToolRotation::Create(const QPointer &dialog, VMainGr initData.source = dialogTool->GetObjects(); initData.hasLinkedVisibilityGroup = dialogTool->HasLinkedVisibilityGroup(); initData.visibilityGroupName = dialogTool->GetVisibilityGroupName(); + initData.visibilityGroupTags = dialogTool->GetVisibilityGroupTags(); initData.scene = scene; initData.doc = doc; initData.data = data; diff --git a/src/libs/vtools/undocommands/undogroup.cpp b/src/libs/vtools/undocommands/undogroup.cpp index 76f8ca088..8b9def919 100644 --- a/src/libs/vtools/undocommands/undogroup.cpp +++ b/src/libs/vtools/undocommands/undogroup.cpp @@ -145,6 +145,38 @@ void RenameGroup::redo() emit UpdateGroups(); } +//ChangeGroupOptions +//--------------------------------------------------------------------------------------------------------------------- +ChangeGroupOptions::ChangeGroupOptions(VAbstractPattern *doc, quint32 id, const QString &name, const QStringList &tags, + QUndoCommand *parent) + : VUndoCommand(QDomElement(), doc, parent), + newName(name), + newTags(tags) +{ + setText(tr("rename group")); + nodeId = id; + oldName = doc->GetGroupName(nodeId); + oldTags = doc->GetGroupTags(nodeId); +} + +//--------------------------------------------------------------------------------------------------------------------- +void ChangeGroupOptions::undo() +{ + qCDebug(vUndo, "Undo."); + doc->SetGroupName(nodeId, oldName); + doc->SetGroupTags(nodeId, oldTags); + emit UpdateGroups(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void ChangeGroupOptions::redo() +{ + qCDebug(vUndo, "Redo."); + doc->SetGroupName(nodeId, newName); + doc->SetGroupTags(nodeId, newTags); + emit UpdateGroups(); +} + //AddItemToGroup //--------------------------------------------------------------------------------------------------------------------- AddItemToGroup::AddItemToGroup(const QDomElement &xml, VAbstractPattern *doc, quint32 groupId, QUndoCommand *parent) diff --git a/src/libs/vtools/undocommands/undogroup.h b/src/libs/vtools/undocommands/undogroup.h index 791ff6dea..e3185fc8c 100644 --- a/src/libs/vtools/undocommands/undogroup.h +++ b/src/libs/vtools/undocommands/undogroup.h @@ -69,6 +69,25 @@ private: QString oldName{}; }; +class ChangeGroupOptions : public VUndoCommand +{ + Q_OBJECT +public: + ChangeGroupOptions(VAbstractPattern *doc, quint32 id, const QString &name, const QStringList &tags, + QUndoCommand *parent = nullptr); + virtual ~ChangeGroupOptions()=default; + virtual void undo() override; + virtual void redo() override; +signals: + void UpdateGroups(); +private: + Q_DISABLE_COPY(ChangeGroupOptions) + QString newName; + QString oldName{}; + QStringList newTags; + QStringList oldTags{}; +}; + class AddItemToGroup : public VUndoCommand { Q_OBJECT diff --git a/src/libs/vwidgets/vlineedit.cpp b/src/libs/vwidgets/vlineedit.cpp index d00e656f6..623c5c3aa 100644 --- a/src/libs/vwidgets/vlineedit.cpp +++ b/src/libs/vwidgets/vlineedit.cpp @@ -28,6 +28,72 @@ #include "vlineedit.h" +#include +#include +#include +#include +#include + +#include "../vmisc/compatibility.h" + +namespace +{ +class MultiSelectCompleter : public QCompleter +{ +public: + MultiSelectCompleter(QObject* parent=nullptr); + MultiSelectCompleter(const QStringList& items, QObject* parent=nullptr); + virtual ~MultiSelectCompleter() =default; + + virtual QString pathFromIndex(const QModelIndex& index) const override; + virtual QStringList splitPath(const QString& path) const override; + +private: + Q_DISABLE_COPY(MultiSelectCompleter) +}; +} + +//MultiSelectCompleter +//--------------------------------------------------------------------------------------------------------------------- +MultiSelectCompleter::MultiSelectCompleter(QObject *parent) + : QCompleter(parent) +{} + +//--------------------------------------------------------------------------------------------------------------------- +MultiSelectCompleter::MultiSelectCompleter(const QStringList& items, QObject* parent) + : QCompleter(items, parent) +{} + +//--------------------------------------------------------------------------------------------------------------------- +QString MultiSelectCompleter::pathFromIndex(const QModelIndex& index) const +{ + QString path = QCompleter::pathFromIndex(index); + + QString text = static_cast(widget())->text(); + + int pos = text.lastIndexOf(','); + if (pos >= 0) + { + path = text.left(pos) + ", " + path; + } + + return path; +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList MultiSelectCompleter::splitPath( const QString& path ) const +{ + int pos = path.lastIndexOf(',') + 1; + + while (pos < path.length() && path.at(pos) == QLatin1Char(' ')) + { + pos++; + } + + return QStringList(path.mid(pos)); +} + +//VLineEdit //--------------------------------------------------------------------------------------------------------------------- VLineEdit::VLineEdit(QWidget *parent) : QLineEdit(parent), @@ -74,3 +140,59 @@ void VLineEdit::mousePressEvent(QMouseEvent *e) } } +// VCompleterLineEdit +//--------------------------------------------------------------------------------------------------------------------- +VCompleterLineEdit::VCompleterLineEdit(QWidget *parent) + : VLineEdit(parent), + m_model(new QStringListModel(this)) +{ + setCompleter(new MultiSelectCompleter()); + completer()->setModel(m_model); + completer()->setCompletionMode(QCompleter::PopupCompletion); + completer()->setCaseSensitivity(Qt::CaseInsensitive); + connect(this, &VCompleterLineEdit::textEdited, this, &VCompleterLineEdit::ShowCompletion); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCompleterLineEdit::SetCompletion(const QStringList &list) +{ + m_model->setStringList(list); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCompleterLineEdit::focusInEvent(QFocusEvent *e) +{ + QLineEdit::focusInEvent(e); + // force completion when line edit is focued in + completer()->complete(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCompleterLineEdit::ShowCompletion() +{ +// PrepareCompletion(); + + // force to show all items when text is empty + completer()->setCompletionMode(text().isEmpty() ? QCompleter::UnfilteredPopupCompletion + : QCompleter::PopupCompletion); + if (text().isEmpty()) + { + // completion list will be hidden now; we will show it again after a delay + QTimer::singleShot(100, this, &VCompleterLineEdit::CompletionPopup); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCompleterLineEdit::CompletionPopup() +{ + // apparently, complete() works only in event handler + QApplication::postEvent(this, new QEvent(QEvent::User)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCompleterLineEdit::customEvent(QEvent *e) +{ + QLineEdit::customEvent(e); + // force completion after text is deleted + completer()->complete(); +} diff --git a/src/libs/vwidgets/vlineedit.h b/src/libs/vwidgets/vlineedit.h index 096eef4e4..23a75a35c 100644 --- a/src/libs/vwidgets/vlineedit.h +++ b/src/libs/vwidgets/vlineedit.h @@ -31,6 +31,8 @@ #include +class QStringListModel; + class VLineEdit : public QLineEdit { Q_OBJECT @@ -47,4 +49,31 @@ private: bool m_selectOnMousePress; }; +/*! Line edit widget with auto completion based on QStringListModel. + Modified behaviour: completion list will appear even when contents of + line edit is empty. Full list of options will be showed when line edit + has focus and is empty. + */ +class VCompleterLineEdit : public VLineEdit +{ + Q_OBJECT +public: + explicit VCompleterLineEdit(QWidget *parent = nullptr); + + //! Set list of options used for completion. + void SetCompletion(const QStringList &list); + +protected: + virtual void focusInEvent(QFocusEvent *e) override; + virtual void customEvent(QEvent* e) override; + +private slots: + void ShowCompletion(); + void CompletionPopup(); + +private: + Q_DISABLE_COPY(VCompleterLineEdit) + QStringListModel *m_model; +}; + #endif // VLINEEDIT_H