Rewrote the Edit Groups Dialog.
This commit is contained in:
+167
-118
@@ -1,28 +1,52 @@
|
||||
#include "lc_global.h"
|
||||
#include "lc_qeditgroupsdialog.h"
|
||||
#include "ui_lc_qeditgroupsdialog.h"
|
||||
#include "lc_application.h"
|
||||
#include "lc_model.h"
|
||||
#include "piece.h"
|
||||
#include "group.h"
|
||||
|
||||
lcQEditGroupsDialog::lcQEditGroupsDialog(QWidget* Parent, const QMap<lcPiece*, lcGroup*>& PieceParents, const QMap<lcGroup*, lcGroup*>& GroupParents, lcModel* Model)
|
||||
: QDialog(Parent), mPieceParents(PieceParents), mGroupParents(GroupParents)
|
||||
constexpr uintptr_t LC_GROUPDIALOG_NEW_GROUP = ~0;
|
||||
|
||||
class lcEditGroupsDialogDelegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
lcEditGroupsDialogDelegate(QObject* Parent)
|
||||
: QItemDelegate(Parent)
|
||||
{
|
||||
}
|
||||
|
||||
void setModelData(QWidget* Editor, QAbstractItemModel* Model, const QModelIndex& Index) const
|
||||
{
|
||||
QLineEdit* LineEdit = qobject_cast<QLineEdit *>(Editor);
|
||||
|
||||
if (!LineEdit->isModified())
|
||||
return;
|
||||
|
||||
QString Text = LineEdit->text().trimmed();
|
||||
|
||||
lcQEditGroupsDialog* Dialog = qobject_cast<lcQEditGroupsDialog*>(parent());
|
||||
|
||||
if (Dialog && !Dialog->CanRenameGroup(Text))
|
||||
return;
|
||||
|
||||
QItemDelegate::setModelData(Editor, Model, Index);
|
||||
}
|
||||
};
|
||||
|
||||
lcQEditGroupsDialog::lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model)
|
||||
: QDialog(Parent), mModel(Model)
|
||||
{
|
||||
mLastItemClicked = nullptr;
|
||||
mModel = Model;
|
||||
ui = new Ui::lcQEditGroupsDialog;
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
QPushButton* NewGroup = ui->buttonBox->addButton(tr("&New Group"), QDialogButtonBox::ActionRole);
|
||||
|
||||
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &lcQEditGroupsDialog::onItemClicked);
|
||||
connect(ui->treeWidget, &QTreeWidget::itemDoubleClicked, this, &lcQEditGroupsDialog::onItemDoubleClicked);
|
||||
connect(NewGroup, &QPushButton::clicked, this, &lcQEditGroupsDialog::NewGroupClicked);
|
||||
|
||||
QPushButton *newGroup = ui->buttonBox->addButton(tr("New Group"), QDialogButtonBox::ActionRole);
|
||||
|
||||
connect(newGroup, &QPushButton::clicked, this, &lcQEditGroupsDialog::on_newGroup_clicked);
|
||||
|
||||
AddChildren(ui->treeWidget->invisibleRootItem(), nullptr);
|
||||
PopulateTree();
|
||||
|
||||
ui->treeWidget->setItemDelegate(new lcEditGroupsDialogDelegate(this));
|
||||
ui->treeWidget->expandAll();
|
||||
}
|
||||
|
||||
@@ -31,139 +55,164 @@ lcQEditGroupsDialog::~lcQEditGroupsDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::accept()
|
||||
bool lcQEditGroupsDialog::CanRenameGroup(const QString& Text) const
|
||||
{
|
||||
UpdateParents(ui->treeWidget->invisibleRootItem(), nullptr);
|
||||
|
||||
QDialog::accept();
|
||||
if (Text.isEmpty())
|
||||
return false;
|
||||
|
||||
std::function<bool(QTreeWidgetItem*)> ScanGroups = [&ScanGroups, &Text](QTreeWidgetItem* ParentItem)
|
||||
{
|
||||
for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++)
|
||||
{
|
||||
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex);
|
||||
|
||||
if (ChildItem->data(0, GroupRole).value<uintptr_t>())
|
||||
{
|
||||
if (ChildItem->text(0) == Text || !ScanGroups(ChildItem))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return ScanGroups(ui->treeWidget->invisibleRootItem());
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::reject()
|
||||
{
|
||||
for (int GroupIdx = 0; GroupIdx < mNewGroups.size(); GroupIdx++)
|
||||
mModel->RemoveGroup(mNewGroups[GroupIdx]);
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::on_newGroup_clicked()
|
||||
void lcQEditGroupsDialog::NewGroupClicked()
|
||||
{
|
||||
QTreeWidgetItem* CurrentItem = ui->treeWidget->currentItem();
|
||||
|
||||
|
||||
if (CurrentItem && CurrentItem->data(0, PieceRole).value<uintptr_t>())
|
||||
CurrentItem = CurrentItem->parent();
|
||||
|
||||
|
||||
if (!CurrentItem)
|
||||
CurrentItem = ui->treeWidget->invisibleRootItem();
|
||||
|
||||
lcGroup* ParentGroup = (lcGroup*)CurrentItem->data(0, GroupRole).value<uintptr_t>();
|
||||
|
||||
lcGroup* NewGroup = mModel->AddGroup(tr("Group #"), ParentGroup);
|
||||
mGroupParents[NewGroup] = ParentGroup;
|
||||
mNewGroups.append(NewGroup);
|
||||
|
||||
QTreeWidgetItem* GroupItem = new QTreeWidgetItem(CurrentItem, QStringList(NewGroup->mName));
|
||||
|
||||
QString Prefix = tr("Group #");
|
||||
int MaxIndex = 0;
|
||||
|
||||
std::function<void(QTreeWidgetItem*)> ScanGroups = [&ScanGroups, &Prefix, &MaxIndex](QTreeWidgetItem* ParentItem)
|
||||
{
|
||||
for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++)
|
||||
{
|
||||
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex);
|
||||
|
||||
if (ChildItem->data(0, GroupRole).value<uintptr_t>())
|
||||
{
|
||||
QString Name = ChildItem->text(0);
|
||||
|
||||
if (Name.startsWith(Prefix))
|
||||
{
|
||||
bool Ok = false;
|
||||
int GroupNumber = Name.mid(Prefix.length()).toInt(&Ok);
|
||||
|
||||
if (Ok && GroupNumber > MaxIndex)
|
||||
MaxIndex = GroupNumber;
|
||||
}
|
||||
|
||||
ScanGroups(ChildItem);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ScanGroups(ui->treeWidget->invisibleRootItem());
|
||||
|
||||
QString Name = Prefix + QString::number(MaxIndex + 1);
|
||||
|
||||
QTreeWidgetItem* GroupItem = new QTreeWidgetItem(CurrentItem, QStringList(Name));
|
||||
GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
|
||||
GroupItem->setData(0, GroupRole, QVariant::fromValue<uintptr_t>((uintptr_t)NewGroup));
|
||||
GroupItem->setData(0, GroupRole, QVariant::fromValue<uintptr_t>(LC_GROUPDIALOG_NEW_GROUP));
|
||||
GroupItem->setExpanded(true);
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::onItemClicked(QTreeWidgetItem *item, int column)
|
||||
lcQEditGroupsDialog::GroupInfo lcQEditGroupsDialog::GetGroupInfo(QTreeWidgetItem* ParentItem) const
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
|
||||
if (item->flags() & Qt::ItemIsEditable)
|
||||
lcQEditGroupsDialog::GroupInfo GroupInfo;
|
||||
|
||||
GroupInfo.Name = ParentItem->text(0);
|
||||
|
||||
uintptr_t GroupPointer = ParentItem->data(0, GroupRole).value<uintptr_t>();
|
||||
GroupInfo.Group = (GroupPointer == LC_GROUPDIALOG_NEW_GROUP) ? nullptr : reinterpret_cast<lcGroup*>(GroupPointer);
|
||||
|
||||
for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++)
|
||||
{
|
||||
mClickTimer.stop();
|
||||
|
||||
if (mLastItemClicked != item)
|
||||
{
|
||||
mLastItemClicked = item;
|
||||
mEditableDoubleClicked = false;
|
||||
}
|
||||
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex);
|
||||
|
||||
if (ChildItem->data(0, GroupRole).value<uintptr_t>())
|
||||
GroupInfo.ChildGroups.emplace_back(GetGroupInfo(ChildItem));
|
||||
else
|
||||
{
|
||||
mClickTimer.start(QApplication::doubleClickInterval() + 50, this);
|
||||
lcPiece* Piece = reinterpret_cast<lcPiece*>(ChildItem->data(0, PieceRole).value<uintptr_t>());
|
||||
|
||||
if (Piece)
|
||||
GroupInfo.ChildPieces.push_back(Piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GroupInfo;
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::onItemDoubleClicked(QTreeWidgetItem *item, int column)
|
||||
lcQEditGroupsDialog::GroupInfo lcQEditGroupsDialog::GetGroups() const
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
|
||||
if (item->flags() & Qt::ItemIsEditable)
|
||||
{
|
||||
mEditableDoubleClicked = true;
|
||||
}
|
||||
return GetGroupInfo(ui->treeWidget->invisibleRootItem());
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::timerEvent(QTimerEvent *event)
|
||||
void lcQEditGroupsDialog::PopulateTree()
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
mClickTimer.stop();
|
||||
if (!mEditableDoubleClicked)
|
||||
const std::vector<std::unique_ptr<lcGroup>>& Groups = mModel->GetGroups();
|
||||
std::unordered_map<lcGroup*, QTreeWidgetItem*> AddedGroups;
|
||||
std::vector<lcGroup*> GroupsToAdd;
|
||||
|
||||
AddedGroups[nullptr] = ui->treeWidget->invisibleRootItem();
|
||||
|
||||
auto CreateGroupItem = [&AddedGroups](lcGroup* Group)
|
||||
{
|
||||
ui->treeWidget->editItem(mLastItemClicked);
|
||||
}
|
||||
|
||||
mEditableDoubleClicked = false;
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::UpdateParents(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup)
|
||||
{
|
||||
for (int ChildIdx = 0; ChildIdx < ParentItem->childCount(); ChildIdx++)
|
||||
{
|
||||
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIdx);
|
||||
|
||||
lcPiece* Piece = (lcPiece*)ChildItem->data(0, PieceRole).value<uintptr_t>();
|
||||
|
||||
if (Piece)
|
||||
{
|
||||
mPieceParents[Piece] = ParentGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcGroup* Group = (lcGroup*)ChildItem->data(0, GroupRole).value<uintptr_t>();
|
||||
|
||||
// todo: validate unique group name
|
||||
if (Group)
|
||||
Group->mName = ChildItem->text(0);
|
||||
|
||||
mGroupParents[Group] = ParentGroup;
|
||||
|
||||
UpdateParents(ChildItem, Group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcQEditGroupsDialog::AddChildren(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup)
|
||||
{
|
||||
for (QMap<lcGroup*, lcGroup*>::const_iterator it = mGroupParents.constBegin(); it != mGroupParents.constEnd(); it++)
|
||||
{
|
||||
lcGroup* Group = it.key();
|
||||
lcGroup* Parent = it.value();
|
||||
|
||||
if (Parent != ParentGroup)
|
||||
continue;
|
||||
|
||||
QTreeWidgetItem* ParentItem = AddedGroups.find(Group->mGroup)->second;
|
||||
|
||||
if (!ParentItem)
|
||||
return false;
|
||||
|
||||
QTreeWidgetItem* GroupItem = new QTreeWidgetItem(ParentItem, QStringList(Group->mName));
|
||||
GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
|
||||
GroupItem->setData(0, GroupRole, QVariant::fromValue<uintptr_t>((uintptr_t)Group));
|
||||
|
||||
AddChildren(GroupItem, Group);
|
||||
}
|
||||
|
||||
for (QMap<lcPiece*, lcGroup*>::const_iterator it = mPieceParents.constBegin(); it != mPieceParents.constEnd(); it++)
|
||||
|
||||
AddedGroups[Group] = GroupItem;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
for (const std::unique_ptr<lcGroup>& Group : Groups)
|
||||
if (!CreateGroupItem(Group.get()))
|
||||
GroupsToAdd.push_back(Group.get());
|
||||
|
||||
while (!GroupsToAdd.empty())
|
||||
{
|
||||
lcPiece* Piece = it.key();
|
||||
lcGroup* Parent = it.value();
|
||||
|
||||
if (Parent != ParentGroup)
|
||||
continue;
|
||||
|
||||
QTreeWidgetItem* PieceItem = new QTreeWidgetItem(ParentItem, QStringList(Piece->GetName()));
|
||||
PieceItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
PieceItem->setData(0, PieceRole, QVariant::fromValue<uintptr_t>((uintptr_t)Piece));
|
||||
size_t GroupCount = GroupsToAdd.size();
|
||||
|
||||
for (auto GroupIt = GroupsToAdd.begin(); GroupIt != GroupsToAdd.end();)
|
||||
{
|
||||
if (CreateGroupItem(*GroupIt))
|
||||
GroupIt = GroupsToAdd.erase(GroupIt);
|
||||
else
|
||||
++GroupIt;
|
||||
}
|
||||
|
||||
if (GroupCount == GroupsToAdd.size())
|
||||
break;
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<lcPiece>>& Pieces = mModel->GetPieces();
|
||||
|
||||
for (const std::unique_ptr<lcPiece>& Piece : Pieces)
|
||||
{
|
||||
QTreeWidgetItem* ParentItem = AddedGroups.find(Piece->GetGroup())->second;
|
||||
|
||||
if (ParentItem)
|
||||
{
|
||||
QTreeWidgetItem* PieceItem = new QTreeWidgetItem(ParentItem, QStringList(Piece->GetName()));
|
||||
PieceItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
PieceItem->setData(0, PieceRole, QVariant::fromValue<uintptr_t>((uintptr_t)Piece.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-28
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class lcQEditGroupsDialog;
|
||||
}
|
||||
@@ -11,37 +9,33 @@ class lcQEditGroupsDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcQEditGroupsDialog(QWidget* Parent, const QMap<lcPiece*, lcGroup*>& PieceParents, const QMap<lcGroup*, lcGroup*>& GroupParents, lcModel* Model);
|
||||
~lcQEditGroupsDialog();
|
||||
lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model);
|
||||
virtual ~lcQEditGroupsDialog();
|
||||
|
||||
QMap<lcPiece*, lcGroup*> mPieceParents;
|
||||
QMap<lcGroup*, lcGroup*> mGroupParents;
|
||||
QList<lcGroup*> mNewGroups;
|
||||
//QList<lcGroup*> mDeletedGroups; // todo: support deleting groups in the edit groups dialog
|
||||
struct GroupInfo
|
||||
{
|
||||
QString Name;
|
||||
lcGroup* Group;
|
||||
std::vector<GroupInfo> ChildGroups;
|
||||
std::vector<lcPiece*> ChildPieces;
|
||||
};
|
||||
|
||||
GroupInfo GetGroups() const;
|
||||
bool CanRenameGroup(const QString& Text) const;
|
||||
|
||||
protected slots:
|
||||
void NewGroupClicked();
|
||||
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
PieceRole = Qt::UserRole,
|
||||
GroupRole
|
||||
};
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
void on_newGroup_clicked();
|
||||
void onItemClicked(QTreeWidgetItem* Item, int Column);
|
||||
void onItemDoubleClicked(QTreeWidgetItem* Item, int Column);
|
||||
|
||||
private:
|
||||
Ui::lcQEditGroupsDialog *ui;
|
||||
|
||||
void UpdateParents(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup);
|
||||
void AddChildren(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup);
|
||||
|
||||
void timerEvent(QTimerEvent* Event) override;
|
||||
|
||||
lcModel* mModel;
|
||||
QTreeWidgetItem* mLastItemClicked;
|
||||
bool mEditableDoubleClicked;
|
||||
QBasicTimer mClickTimer;
|
||||
|
||||
GroupInfo GetGroupInfo(QTreeWidgetItem* ParentItem) const;
|
||||
void PopulateTree();
|
||||
|
||||
Ui::lcQEditGroupsDialog* ui = nullptr;
|
||||
const lcModel* mModel = nullptr;
|
||||
};
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
<set>QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed|QAbstractItemView::EditTrigger::SelectedClicked</set>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
<enum>QAbstractItemView::DragDropMode::InternalMove</enum>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
@@ -41,10 +41,10 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user