2023-05-22 22:13:42 -04:00
|
|
|
#include "localdocsmodel.h"
|
|
|
|
|
2023-10-24 12:13:32 -04:00
|
|
|
#include "localdocs.h"
|
2024-04-25 13:16:52 -04:00
|
|
|
#include "network.h"
|
2023-10-24 12:13:32 -04:00
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
#include <QDateTime>
|
2024-06-04 14:47:11 -04:00
|
|
|
#include <QMap>
|
2024-06-24 18:49:23 -04:00
|
|
|
#include <QVector>
|
2024-06-04 14:47:11 -04:00
|
|
|
#include <QtGlobal>
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
2023-10-24 12:13:32 -04:00
|
|
|
LocalDocsCollectionsModel::LocalDocsCollectionsModel(QObject *parent)
|
|
|
|
: QSortFilterProxyModel(parent)
|
|
|
|
{
|
|
|
|
setSourceModel(LocalDocs::globalInstance()->localDocsModel());
|
2024-06-24 18:49:23 -04:00
|
|
|
|
|
|
|
connect(LocalDocs::globalInstance()->localDocsModel(),
|
|
|
|
&LocalDocsModel::updatingChanged, this, &LocalDocsCollectionsModel::maybeTriggerUpdatingCountChanged);
|
|
|
|
connect(this, &LocalDocsCollectionsModel::rowsInserted, this, &LocalDocsCollectionsModel::countChanged);
|
|
|
|
connect(this, &LocalDocsCollectionsModel::rowsRemoved, this, &LocalDocsCollectionsModel::countChanged);
|
|
|
|
connect(this, &LocalDocsCollectionsModel::modelReset, this, &LocalDocsCollectionsModel::countChanged);
|
|
|
|
connect(this, &LocalDocsCollectionsModel::layoutChanged, this, &LocalDocsCollectionsModel::countChanged);
|
2023-10-24 12:13:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool LocalDocsCollectionsModel::filterAcceptsRow(int sourceRow,
|
|
|
|
const QModelIndex &sourceParent) const
|
|
|
|
{
|
|
|
|
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
|
|
|
const QString collection = sourceModel()->data(index, LocalDocsModel::CollectionRole).toString();
|
|
|
|
return m_collections.contains(collection);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocalDocsCollectionsModel::setCollections(const QList<QString> &collections)
|
|
|
|
{
|
|
|
|
m_collections = collections;
|
|
|
|
invalidateFilter();
|
2024-06-24 18:49:23 -04:00
|
|
|
maybeTriggerUpdatingCountChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
int LocalDocsCollectionsModel::updatingCount() const
|
|
|
|
{
|
|
|
|
return m_updatingCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocalDocsCollectionsModel::maybeTriggerUpdatingCountChanged()
|
|
|
|
{
|
|
|
|
int updatingCount = 0;
|
|
|
|
for (int row = 0; row < sourceModel()->rowCount(); ++row) {
|
|
|
|
QModelIndex index = sourceModel()->index(row, 0);
|
|
|
|
const QString collection = sourceModel()->data(index, LocalDocsModel::CollectionRole).toString();
|
|
|
|
if (!m_collections.contains(collection))
|
|
|
|
continue;
|
|
|
|
bool updating = sourceModel()->data(index, LocalDocsModel::UpdatingRole).toBool();
|
|
|
|
if (updating)
|
|
|
|
++updatingCount;
|
|
|
|
}
|
|
|
|
if (updatingCount != m_updatingCount) {
|
|
|
|
m_updatingCount = updatingCount;
|
|
|
|
emit updatingCountChanged();
|
|
|
|
}
|
2023-10-24 12:13:32 -04:00
|
|
|
}
|
|
|
|
|
2023-05-22 22:13:42 -04:00
|
|
|
LocalDocsModel::LocalDocsModel(QObject *parent)
|
|
|
|
: QAbstractListModel(parent)
|
|
|
|
{
|
2024-06-24 18:49:23 -04:00
|
|
|
connect(this, &LocalDocsModel::rowsInserted, this, &LocalDocsModel::countChanged);
|
|
|
|
connect(this, &LocalDocsModel::rowsRemoved, this, &LocalDocsModel::countChanged);
|
|
|
|
connect(this, &LocalDocsModel::modelReset, this, &LocalDocsModel::countChanged);
|
|
|
|
connect(this, &LocalDocsModel::layoutChanged, this, &LocalDocsModel::countChanged);
|
2023-05-22 22:13:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int LocalDocsModel::rowCount(const QModelIndex &parent) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(parent);
|
|
|
|
return m_collectionList.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant LocalDocsModel::data(const QModelIndex &index, int role) const
|
|
|
|
{
|
|
|
|
if (!index.isValid() || index.row() < 0 || index.row() >= m_collectionList.size())
|
|
|
|
return QVariant();
|
|
|
|
|
|
|
|
const CollectionItem item = m_collectionList.at(index.row());
|
|
|
|
switch (role) {
|
|
|
|
case CollectionRole:
|
|
|
|
return item.collection;
|
|
|
|
case FolderPathRole:
|
|
|
|
return item.folder_path;
|
2023-06-03 10:08:59 -04:00
|
|
|
case InstalledRole:
|
|
|
|
return item.installed;
|
2023-10-24 12:13:32 -04:00
|
|
|
case IndexingRole:
|
|
|
|
return item.indexing;
|
2024-01-22 12:36:01 -05:00
|
|
|
case ErrorRole:
|
|
|
|
return item.error;
|
2024-06-24 18:49:23 -04:00
|
|
|
case ForceIndexingRole:
|
|
|
|
return item.forceIndexing;
|
2023-10-24 12:13:32 -04:00
|
|
|
case CurrentDocsToIndexRole:
|
|
|
|
return item.currentDocsToIndex;
|
|
|
|
case TotalDocsToIndexRole:
|
|
|
|
return item.totalDocsToIndex;
|
|
|
|
case CurrentBytesToIndexRole:
|
|
|
|
return quint64(item.currentBytesToIndex);
|
|
|
|
case TotalBytesToIndexRole:
|
|
|
|
return quint64(item.totalBytesToIndex);
|
2024-01-22 12:36:01 -05:00
|
|
|
case CurrentEmbeddingsToIndexRole:
|
|
|
|
return quint64(item.currentEmbeddingsToIndex);
|
|
|
|
case TotalEmbeddingsToIndexRole:
|
|
|
|
return quint64(item.totalEmbeddingsToIndex);
|
2024-06-24 18:49:23 -04:00
|
|
|
case TotalDocsRole:
|
|
|
|
return quint64(item.totalDocs);
|
|
|
|
case TotalWordsRole:
|
|
|
|
return quint64(item.totalWords);
|
|
|
|
case TotalTokensRole:
|
|
|
|
return quint64(item.totalTokens);
|
|
|
|
case StartUpdateRole:
|
|
|
|
return item.startUpdate;
|
|
|
|
case LastUpdateRole:
|
|
|
|
return item.lastUpdate;
|
|
|
|
case FileCurrentlyProcessingRole:
|
|
|
|
return item.fileCurrentlyProcessing;
|
|
|
|
case EmbeddingModelRole:
|
|
|
|
return item.embeddingModel;
|
|
|
|
case UpdatingRole:
|
|
|
|
return item.indexing || item.currentEmbeddingsToIndex != 0;
|
2023-05-22 22:13:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
|
|
|
QHash<int, QByteArray> LocalDocsModel::roleNames() const
|
|
|
|
{
|
|
|
|
QHash<int, QByteArray> roles;
|
|
|
|
roles[CollectionRole] = "collection";
|
|
|
|
roles[FolderPathRole] = "folder_path";
|
2023-06-03 10:08:59 -04:00
|
|
|
roles[InstalledRole] = "installed";
|
2023-10-24 12:13:32 -04:00
|
|
|
roles[IndexingRole] = "indexing";
|
2024-01-22 12:36:01 -05:00
|
|
|
roles[ErrorRole] = "error";
|
2024-06-24 18:49:23 -04:00
|
|
|
roles[ForceIndexingRole] = "forceIndexing";
|
2023-10-24 12:13:32 -04:00
|
|
|
roles[CurrentDocsToIndexRole] = "currentDocsToIndex";
|
|
|
|
roles[TotalDocsToIndexRole] = "totalDocsToIndex";
|
|
|
|
roles[CurrentBytesToIndexRole] = "currentBytesToIndex";
|
|
|
|
roles[TotalBytesToIndexRole] = "totalBytesToIndex";
|
2024-01-22 12:36:01 -05:00
|
|
|
roles[CurrentEmbeddingsToIndexRole] = "currentEmbeddingsToIndex";
|
|
|
|
roles[TotalEmbeddingsToIndexRole] = "totalEmbeddingsToIndex";
|
2024-06-24 18:49:23 -04:00
|
|
|
roles[TotalDocsRole] = "totalDocs";
|
|
|
|
roles[TotalWordsRole] = "totalWords";
|
|
|
|
roles[TotalTokensRole] = "totalTokens";
|
|
|
|
roles[StartUpdateRole] = "startUpdate";
|
|
|
|
roles[LastUpdateRole] = "lastUpdate";
|
|
|
|
roles[FileCurrentlyProcessingRole] = "fileCurrentlyProcessing";
|
|
|
|
roles[EmbeddingModelRole] = "embeddingModel";
|
|
|
|
roles[UpdatingRole] = "updating";
|
2023-05-22 22:13:42 -04:00
|
|
|
return roles;
|
|
|
|
}
|
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
void LocalDocsModel::updateCollectionItem(const CollectionItem &item)
|
2023-10-24 12:13:32 -04:00
|
|
|
{
|
|
|
|
for (int i = 0; i < m_collectionList.size(); ++i) {
|
2024-06-24 18:49:23 -04:00
|
|
|
CollectionItem &stored = m_collectionList[i];
|
|
|
|
if (stored.folder_id != item.folder_id)
|
2023-10-24 12:13:32 -04:00
|
|
|
continue;
|
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
QVector<int> changed;
|
|
|
|
if (stored.folder_path != item.folder_path)
|
|
|
|
changed.append(FolderPathRole);
|
|
|
|
if (stored.installed != item.installed)
|
|
|
|
changed.append(InstalledRole);
|
|
|
|
if (stored.indexing != item.indexing) {
|
|
|
|
changed.append(IndexingRole);
|
|
|
|
changed.append(UpdatingRole);
|
|
|
|
}
|
|
|
|
if (stored.error != item.error)
|
|
|
|
changed.append(ErrorRole);
|
|
|
|
if (stored.forceIndexing != item.forceIndexing)
|
|
|
|
changed.append(ForceIndexingRole);
|
|
|
|
if (stored.currentDocsToIndex != item.currentDocsToIndex)
|
|
|
|
changed.append(CurrentDocsToIndexRole);
|
|
|
|
if (stored.totalDocsToIndex != item.totalDocsToIndex)
|
|
|
|
changed.append(TotalDocsToIndexRole);
|
|
|
|
if (stored.currentBytesToIndex != item.currentBytesToIndex)
|
|
|
|
changed.append(CurrentBytesToIndexRole);
|
|
|
|
if (stored.totalBytesToIndex != item.totalBytesToIndex)
|
|
|
|
changed.append(TotalBytesToIndexRole);
|
|
|
|
if (stored.currentEmbeddingsToIndex != item.currentEmbeddingsToIndex) {
|
|
|
|
changed.append(CurrentEmbeddingsToIndexRole);
|
|
|
|
changed.append(UpdatingRole);
|
|
|
|
}
|
|
|
|
if (stored.totalEmbeddingsToIndex != item.totalEmbeddingsToIndex)
|
|
|
|
changed.append(TotalEmbeddingsToIndexRole);
|
|
|
|
if (stored.totalDocs != item.totalDocs)
|
|
|
|
changed.append(TotalDocsRole);
|
|
|
|
if (stored.totalWords != item.totalWords)
|
|
|
|
changed.append(TotalWordsRole);
|
|
|
|
if (stored.totalTokens != item.totalTokens)
|
|
|
|
changed.append(TotalTokensRole);
|
|
|
|
if (stored.startUpdate != item.startUpdate)
|
|
|
|
changed.append(StartUpdateRole);
|
|
|
|
if (stored.lastUpdate != item.lastUpdate)
|
|
|
|
changed.append(LastUpdateRole);
|
|
|
|
if (stored.fileCurrentlyProcessing != item.fileCurrentlyProcessing)
|
|
|
|
changed.append(FileCurrentlyProcessingRole);
|
|
|
|
if (stored.embeddingModel != item.embeddingModel)
|
|
|
|
changed.append(EmbeddingModelRole);
|
2023-10-24 12:13:32 -04:00
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
// preserve collection name as we ignore it for matching
|
|
|
|
QString collection = stored.collection;
|
|
|
|
stored = item;
|
|
|
|
stored.collection = collection;
|
2023-10-24 12:13:32 -04:00
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
emit dataChanged(this->index(i), this->index(i), changed);
|
2024-01-22 12:36:01 -05:00
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
if (changed.contains(UpdatingRole))
|
|
|
|
emit updatingChanged(item.collection);
|
|
|
|
}
|
2024-01-22 12:36:01 -05:00
|
|
|
}
|
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
void LocalDocsModel::addCollectionItem(const CollectionItem &item)
|
2023-06-03 10:08:59 -04:00
|
|
|
{
|
|
|
|
beginInsertRows(QModelIndex(), m_collectionList.size(), m_collectionList.size());
|
|
|
|
m_collectionList.append(item);
|
|
|
|
endInsertRows();
|
|
|
|
}
|
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
void LocalDocsModel::removeCollectionIf(std::function<bool(CollectionItem)> const &predicate)
|
|
|
|
{
|
2023-10-24 12:13:32 -04:00
|
|
|
for (int i = 0; i < m_collectionList.size();) {
|
2024-04-25 13:16:52 -04:00
|
|
|
if (predicate(m_collectionList.at(i))) {
|
2023-10-24 12:13:32 -04:00
|
|
|
beginRemoveRows(QModelIndex(), i, i);
|
|
|
|
m_collectionList.removeAt(i);
|
|
|
|
endRemoveRows();
|
2024-04-25 13:16:52 -04:00
|
|
|
|
|
|
|
Network::globalInstance()->trackEvent("doc_collection_remove", {
|
|
|
|
{"collection_count", m_collectionList.count()},
|
|
|
|
});
|
2023-10-24 12:13:32 -04:00
|
|
|
} else {
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-24 18:49:23 -04:00
|
|
|
void LocalDocsModel::removeFolderById(const QString &collection, int folder_id)
|
2023-10-24 12:13:32 -04:00
|
|
|
{
|
2024-06-24 18:49:23 -04:00
|
|
|
removeCollectionIf([collection, folder_id](const auto &c) {
|
|
|
|
return c.collection == collection && c.folder_id == folder_id;
|
|
|
|
});
|
2023-10-24 12:13:32 -04:00
|
|
|
}
|
|
|
|
|
2024-04-25 13:16:52 -04:00
|
|
|
void LocalDocsModel::removeCollectionPath(const QString &name, const QString &path)
|
2023-10-24 12:13:32 -04:00
|
|
|
{
|
2024-04-25 13:16:52 -04:00
|
|
|
removeCollectionIf([&name, &path](const auto &c) { return c.collection == name && c.folder_path == path; });
|
2023-10-24 12:13:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LocalDocsModel::collectionListUpdated(const QList<CollectionItem> &collectionList)
|
2023-05-22 22:13:42 -04:00
|
|
|
{
|
|
|
|
beginResetModel();
|
|
|
|
m_collectionList = collectionList;
|
|
|
|
endResetModel();
|
2023-05-25 11:16:01 -04:00
|
|
|
}
|