Skip to content

Commit

Permalink
fix profile manager
Browse files Browse the repository at this point in the history
  • Loading branch information
arm64v8a committed Jul 22, 2023
1 parent 7f664b1 commit 9afa9f3
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 84 deletions.
107 changes: 76 additions & 31 deletions db/Database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,88 @@
#include "fmt/includes.h"

#include <QFile>
#include <QDir>
#include <QColor>

namespace NekoGui {

ProfileManager *profileManager = new ProfileManager();

ProfileManager::ProfileManager() : JsonStore("groups/pm.json") {
callback_after_load = [this]() { LoadManager(); };
callback_before_save = [this]() { SaveManager(); };
_add(new configItem("profiles", &_profiles, itemType::integerList));
_add(new configItem("groups", &_groups, itemType::integerList));
_add(new configItem("groups", &groupsTabOrder, itemType::integerList));
}

QList<int> filterIntJsonFile(const QString &path) {
QList<int> result;
QDir dr(path);
auto entryList = dr.entryList(QDir::Files);
for (auto e: entryList) {
e = e.toLower();
if (!e.endsWith(".json", Qt::CaseInsensitive)) continue;
e = e.remove(".json", Qt::CaseInsensitive);
bool ok;
auto id = e.toInt(&ok);
if (ok) {
result << id;
}
}
std::sort(result.begin(), result.end());
return result;
}

void ProfileManager::LoadManager() {
JsonStore::Load();
//
profiles = {};
groups = {};
QList<int> invalidProfileId;
for (auto id: _profiles) {
profilesIdOrder = filterIntJsonFile("profiles");
groupsIdOrder = filterIntJsonFile("groups");
// Load Proxys
QList<int> delProfile;
for (auto id: profilesIdOrder) {
auto ent = LoadProxyEntity(QString("profiles/%1.json").arg(id));
// Corrupted profile?
if (ent == nullptr || ent->bean == nullptr || ent->bean->version == -114514) {
// clear invalid profile
invalidProfileId << id;
delProfile << id;
continue;
}
profiles[id] = ent;
}
for (auto id: _groups) {
groups[id] = LoadGroup(QString("groups/%1.json").arg(id));
}
for (auto id: invalidProfileId) {
// Clear Corrupted profile
for (auto id: delProfile) {
DeleteProfile(id);
}
// Load Groups
auto loadedOrder = groupsTabOrder;
groupsTabOrder = {};
for (auto id: groupsIdOrder) {
auto ent = LoadGroup(QString("groups/%1.json").arg(id));
// Corrupted group?
if (ent->id != id) {
continue;
}
// Ensure order contains every group
if (!loadedOrder.contains(id)) {
loadedOrder << id;
}
groups[id] = ent;
}
// Ensure groups contains order
for (auto id: loadedOrder) {
if (groups.count(id)) {
groupsTabOrder << id;
}
}
// First setup
if (groups.empty()) {
auto defaultGroup = NekoGui::ProfileManager::NewGroup();
defaultGroup->name = QObject::tr("Default");
NekoGui::profileManager->AddGroup(defaultGroup);
}
}

void ProfileManager::SaveManager() {
JsonStore::Save();
}

std::shared_ptr<ProxyEntity> ProfileManager::LoadProxyEntity(const QString &jsonPath) {
Expand Down Expand Up @@ -153,7 +200,7 @@ namespace NekoGui {
if (profiles.empty()) {
return 0;
} else {
return profiles.lastKey() + 1;
return profilesIdOrder.last() + 1;
}
}

Expand All @@ -165,8 +212,7 @@ namespace NekoGui {
ent->gid = gid < 0 ? dataStore->current_group : gid;
ent->id = NewProfileID();
profiles[ent->id] = ent;
_profiles.push_back(ent->id);
Save();
profilesIdOrder.push_back(ent->id);

ent->fn = QString("profiles/%1.json").arg(ent->id);
ent->Save();
Expand All @@ -176,9 +222,8 @@ namespace NekoGui {
void ProfileManager::DeleteProfile(int id) {
if (id < 0) return;
if (dataStore->started_id == id) return;
profiles.remove(id);
_profiles.removeAll(id);
Save();
profiles.erase(id);
profilesIdOrder.removeAll(id);
QFile(QString("profiles/%1.json").arg(id)).remove();
}

Expand All @@ -199,7 +244,7 @@ namespace NekoGui {
}

std::shared_ptr<ProxyEntity> ProfileManager::GetProfile(int id) {
return profiles.value(id, nullptr);
return profiles.count(id) ? profiles[id] : nullptr;
}

// Group
Expand Down Expand Up @@ -228,7 +273,7 @@ namespace NekoGui {
if (groups.empty()) {
return 0;
} else {
return groups.lastKey() + 1;
return groupsIdOrder.last() + 1;
}
}

Expand All @@ -239,31 +284,31 @@ namespace NekoGui {

ent->id = NewGroupID();
groups[ent->id] = ent;
_groups.push_back(ent->id);
Save();
groupsIdOrder.push_back(ent->id);
groupsTabOrder.push_back(ent->id);

ent->fn = QString("groups/%1.json").arg(ent->id);
ent->Save();
return true;
}

void ProfileManager::DeleteGroup(int gid) {
if (groups.count() == 1) return;
if (groups.size() <= 1) return;
QList<int> toDelete;
for (const auto &profile: profiles) {
if (profile->gid == gid) toDelete += profile->id; // map访问中,不能操作
for (const auto &[id, profile]: profiles) {
if (profile->gid == gid) toDelete += id; // map访问中,不能操作
}
for (const auto &id: toDelete) {
DeleteProfile(id);
}
groups.remove(gid);
_groups.removeAll(gid);
Save();
groups.erase(gid);
groupsIdOrder.removeAll(gid);
groupsTabOrder.removeAll(gid);
QFile(QString("groups/%1.json").arg(gid)).remove();
}

std::shared_ptr<Group> ProfileManager::GetGroup(int id) {
return groups.value(id, nullptr);
return groups.count(id) ? groups[id] : nullptr;
}

std::shared_ptr<Group> ProfileManager::CurrentGroup() {
Expand All @@ -272,8 +317,8 @@ namespace NekoGui {

QList<std::shared_ptr<ProxyEntity>> Group::Profiles() const {
QList<std::shared_ptr<ProxyEntity>> ret;
for (const auto &ent: profileManager->profiles) {
if (id == ent->gid) ret += ent;
for (const auto &[_, profile]: profileManager->profiles) {
if (id == profile->gid) ret += profile;
}
return ret;
}
Expand Down
25 changes: 16 additions & 9 deletions db/Database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@
#include "Group.hpp"

namespace NekoGui {
class ProfileManager : public JsonStore {
class ProfileManager : private JsonStore {
public:
// JsonStore

// order -> id
QList<int> groupsTabOrder;

// Manager
QMap<int, std::shared_ptr<ProxyEntity>> profiles;
QMap<int, std::shared_ptr<Group>> groups;

// JSON
QList<int> _profiles;
QList<int> _groups; // with order
std::map<int, std::shared_ptr<ProxyEntity>> profiles;
std::map<int, std::shared_ptr<Group>> groups;

ProfileManager();

// LoadManager Reset and loads profiles & groups
void LoadManager();

void SaveManager();

[[nodiscard]] static std::shared_ptr<ProxyEntity> NewProxyEntity(const QString &type);

[[nodiscard]] static std::shared_ptr<Group> NewGroup();
Expand All @@ -38,9 +45,9 @@ namespace NekoGui {
std::shared_ptr<Group> CurrentGroup();

private:
void LoadManager();

void SaveManager();
// sort by id
QList<int> profilesIdOrder;
QList<int> groupsIdOrder;

[[nodiscard]] int NewProfileID() const;

Expand Down
9 changes: 2 additions & 7 deletions main/NekoGui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,13 +348,8 @@ namespace NekoGui {
}

QStringList Routing::List() {
QStringList l;
QDir d;
if (d.exists(ROUTES_PREFIX)) {
QDir dr(ROUTES_PREFIX);
return dr.entryList(QDir::Files);
}
return l;
QDir dr(ROUTES_PREFIX);
return dr.entryList(QDir::Files);
}

void Routing::SetToActive(const QString &name) {
Expand Down
5 changes: 0 additions & 5 deletions rpc/gRPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ namespace QtGrpc {
QString serviceName;
QByteArray nekoray_auth;

// TODO Fixed?
// https://github.com/semlanik/qtprotobuf/issues/116
// setCachingEnabled: 5 bytesDownloaded
// QNetworkReplyImpl: backend error: caching was enabled after some bytes had been written

// async
QNetworkReply *post(const QString &method, const QString &service, const QByteArray &args) {
QUrl callUrl = url_base + "/" + service + "/" + method;
Expand Down
6 changes: 5 additions & 1 deletion translations/fa_IR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1301,7 +1301,7 @@ This needs to be run NekoBox with administrator privileges.</source>
</message>
<message>
<source>Default</source>
<translation>پیش فرض</translation>
<translation type="vanished">پیش فرض</translation>
</message>
<message>
<source>Load routing and apply: %1</source>
Expand Down Expand Up @@ -1650,6 +1650,10 @@ Direct: %2</source>
<source>As Subscription (add to this group)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Default</source>
<translation type="unfinished">پیش فرض</translation>
</message>
</context>
<context>
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
Expand Down
6 changes: 5 additions & 1 deletion translations/ru_RU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,7 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun</translation>
</message>
<message>
<source>Default</source>
<translation>По умолчанию</translation>
<translation type="vanished">По умолчанию</translation>
</message>
<message>
<source>Load routing and apply: %1</source>
Expand Down Expand Up @@ -1646,6 +1646,10 @@ Release note:
<source>Used: %1 Remain: %2 Expire: %3</source>
<translation>Использовано: %1, осталось: %2, истекло: %3</translation>
</message>
<message>
<source>Default</source>
<translation type="unfinished">По умолчанию</translation>
</message>
</context>
<context>
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
Expand Down
6 changes: 5 additions & 1 deletion translations/zh_CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ This needs to be run NekoBox with administrator privileges.</source>
</message>
<message>
<source>Default</source>
<translation>默认</translation>
<translation type="vanished">默认</translation>
</message>
<message>
<source>Confirmation</source>
Expand Down Expand Up @@ -1644,6 +1644,10 @@ Release note:
<source>As Subscription (add to this group)</source>
<translation>作为订阅(添加到该组)</translation>
</message>
<message>
<source>Default</source>
<translation type="unfinished">默认</translation>
</message>
</context>
<context>
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
Expand Down
12 changes: 6 additions & 6 deletions ui/dialog_manage_groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
DialogManageGroups::DialogManageGroups(QWidget *parent) : QDialog(parent), ui(new Ui::DialogManageGroups) {
ui->setupUi(this);

for (auto id: NekoGui::profileManager->_groups) {
for (auto id: NekoGui::profileManager->groupsTabOrder) {
AddGroupToListIfExist(id)
}

Expand Down Expand Up @@ -53,10 +53,10 @@ void DialogManageGroups::on_add_clicked() {

void DialogManageGroups::on_update_all_clicked() {
if (QMessageBox::question(this, tr("Confirmation"), tr("Update all subscriptions?")) == QMessageBox::StandardButton::Yes) {
for (const auto &gid: NekoGui::profileManager->_groups) {
for (const auto &gid: NekoGui::profileManager->groupsTabOrder) {
auto group = NekoGui::profileManager->GetGroup(gid);
if (group == nullptr || group->url.isEmpty()) continue;
UI_update_one_group(NekoGui::profileManager->_groups.indexOf(gid));
UI_update_one_group(NekoGui::profileManager->groupsTabOrder.indexOf(gid));
return;
}
}
Expand All @@ -68,15 +68,15 @@ void UI_update_one_group(int _order) {
std::shared_ptr<NekoGui::Group> nextGroup;
forever {
nextOrder += 1;
if (nextOrder >= NekoGui::profileManager->_groups.length()) break;
auto nextGid = NekoGui::profileManager->_groups[nextOrder];
if (nextOrder >= NekoGui::profileManager->groupsTabOrder.size()) break;
auto nextGid = NekoGui::profileManager->groupsTabOrder[nextOrder];
nextGroup = NekoGui::profileManager->GetGroup(nextGid);
if (nextGroup == nullptr || nextGroup->url.isEmpty()) continue;
break;
}

// calculate this group
auto group = NekoGui::profileManager->GetGroup(NekoGui::profileManager->_groups[_order]);
auto group = NekoGui::profileManager->GetGroup(NekoGui::profileManager->groupsTabOrder[_order]);
if (group == nullptr) return;

// v2.2: listener is moved to GroupItem, no refresh here.
Expand Down
4 changes: 2 additions & 2 deletions ui/edit/dialog_edit_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ DialogEditGroup::DialogEditGroup(const std::shared_ptr<NekoGui::Group> &ent, QWi

connect(ui->copy_links, &QPushButton::clicked, this, [=] {
QStringList links;
for (const auto &profile: NekoGui::profileManager->profiles) {
for (const auto &[_, profile]: NekoGui::profileManager->profiles) {
if (profile->gid != ent->id) continue;
links += profile->bean->ToShareLink();
}
Expand All @@ -53,7 +53,7 @@ DialogEditGroup::DialogEditGroup(const std::shared_ptr<NekoGui::Group> &ent, QWi
});
connect(ui->copy_links_nkr, &QPushButton::clicked, this, [=] {
QStringList links;
for (const auto &profile: NekoGui::profileManager->profiles) {
for (const auto &[_, profile]: NekoGui::profileManager->profiles) {
if (profile->gid != ent->id) continue;
links += profile->bean->ToNekorayShareLink(profile->type);
}
Expand Down
Loading

0 comments on commit 9afa9f3

Please sign in to comment.