feat: add manual group reordering with drag-and-drop

Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: yanxiatao <1960024760@qq.com>
This commit is contained in:
yanxiatao 2026-06-24 03:51:01 +08:00
parent f654ce8212
commit 46d296a398
4 changed files with 205 additions and 5 deletions

View file

@ -145,6 +145,32 @@ QStringList InstanceList::getLinkedInstancesById(const QString& id) const
return linkedInstances;
}
QStringList InstanceList::groupOrder() const
{
return m_groupOrder;
}
void InstanceList::moveGroup(const QString& group, int toIndex)
{
int fromIndex = m_groupOrder.indexOf(group);
qDebug() << "moveGroup: enter" << group << "from" << fromIndex << "to" << toIndex << "order before" << m_groupOrder;
if (fromIndex < 0)
return;
int size = m_groupOrder.size();
toIndex = qBound(0, toIndex, size);
if (fromIndex == toIndex)
return;
QString name = m_groupOrder.takeAt(fromIndex);
// After takeAt, insert position shifts if target was after the removed position
int insertAt = (fromIndex < toIndex) ? (toIndex - 1) : toIndex;
m_groupOrder.insert(insertAt, name);
qDebug() << "moveGroup: order after" << m_groupOrder;
emit groupOrderChanged();
saveGroupList();
}
int InstanceList::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
@ -293,6 +319,8 @@ void InstanceList::deleteGroup(const GroupId& name)
}
if (removed)
saveGroupList();
m_groupOrder.removeAll(name);
emit groupOrderChanged();
}
void InstanceList::renameGroup(const QString& src, const QString& dst)
@ -318,6 +346,10 @@ void InstanceList::renameGroup(const QString& src, const QString& dst)
}
if (modified)
saveGroupList();
int idx = m_groupOrder.indexOf(src);
if (idx >= 0)
m_groupOrder[idx] = dst;
emit groupOrderChanged();
}
bool InstanceList::isGroupCollapsed(const QString& group)
@ -692,7 +724,11 @@ void InstanceList::increaseGroupCount(const QString& group)
if (group.isEmpty())
return;
bool wasNew = !m_groupNameCache.contains(group);
++m_groupNameCache[group];
if (wasNew && !m_groupOrder.contains(group)) {
m_groupOrder.append(group);
}
}
void InstanceList::decreaseGroupCount(const QString& group)
@ -703,6 +739,7 @@ void InstanceList::decreaseGroupCount(const QString& group)
if (--m_groupNameCache[group] < 1) {
m_groupNameCache.remove(group);
m_collapsedGroups.remove(group);
m_groupOrder.removeAll(group);
}
}
@ -757,6 +794,16 @@ void InstanceList::saveGroupList()
ungrouped.insert("hidden", QJsonValue(true));
toplevel.insert("ungrouped", ungrouped);
}
// Save group order (deduplicate to prevent silent corruption)
QJsonArray orderArr;
QStringList savedOrder;
for (const auto& name : m_groupOrder) {
if (!savedOrder.contains(name) && (name.isEmpty() || m_groupNameCache.contains(name))) {
savedOrder.append(name);
orderArr.append(name);
}
}
toplevel.insert("groupOrder", orderArr);
QJsonDocument doc(toplevel);
try {
FS::write(groupFileName, doc.toJson());
@ -772,9 +819,13 @@ void InstanceList::loadGroupList()
QString groupFileName = m_instDir + "/instgroups.json";
// if there's no group file, fail
if (!QFileInfo(groupFileName).exists())
// if there's no group file, set up default state
if (!QFileInfo(groupFileName).exists()) {
m_groupOrder.clear();
m_groupOrder.append("");
m_groupsLoaded = true;
return;
}
QByteArray jsonData;
try {
@ -815,6 +866,7 @@ void InstanceList::loadGroupList()
m_instanceGroupIndex.clear();
m_groupNameCache.clear();
m_groupOrder.clear();
// Iterate through all the groups.
QJsonObject groupMapping = rootObj.value("groups").toObject();
@ -862,6 +914,32 @@ void InstanceList::loadGroupList()
// empty string represents ungrouped "group"
m_collapsedGroups.insert("");
}
// Load group order (added in formatVersion 1, optional)
if (rootObj.value("groupOrder").isArray()) {
QJsonArray orderArr = rootObj.value("groupOrder").toArray();
for (const auto& val : orderArr) {
QString name = val.toString();
m_groupOrder.append(name);
}
}
// Deduplicate group order (defense against previously-corrupted data)
QStringList uniqueOrder;
for (const auto& name : m_groupOrder) {
if (!uniqueOrder.contains(name))
uniqueOrder.append(name);
}
m_groupOrder = uniqueOrder;
// Treat ungrouped group (empty string) as a regular group for ordering
if (m_groupOrder.isEmpty()) {
m_groupOrder = m_groupNameCache.keys();
m_groupOrder.sort();
}
if (!m_groupOrder.contains(""))
m_groupOrder.append("");
m_groupsLoaded = true;
qDebug() << "Group list loaded.";
}