mirror of
https://github.com/joel16/VITA-Homebrew-Sorter.git
synced 2024-11-23 11:29:50 +00:00
gui: Add new tab to swap page positions and span all buttons to available window width
This commit is contained in:
parent
c2d0028fb5
commit
562b196d7d
@ -43,6 +43,7 @@ struct AppEntries {
|
|||||||
namespace AppList {
|
namespace AppList {
|
||||||
int Get(AppEntries &entries);
|
int Get(AppEntries &entries);
|
||||||
int Save(std::vector<AppInfoIcon> &entries);
|
int Save(std::vector<AppInfoIcon> &entries);
|
||||||
|
int SavePages(std::vector<AppInfoPage> &entries);
|
||||||
bool SortAppAsc(const AppInfoIcon &entryA, const AppInfoIcon &entryB);
|
bool SortAppAsc(const AppInfoIcon &entryA, const AppInfoIcon &entryB);
|
||||||
bool SortAppDesc(const AppInfoIcon &entryA, const AppInfoIcon &entryB);
|
bool SortAppDesc(const AppInfoIcon &entryA, const AppInfoIcon &entryB);
|
||||||
bool SortChildAppAsc(const AppInfoChild &entryA, const AppInfoChild &entryB);
|
bool SortChildAppAsc(const AppInfoChild &entryA, const AppInfoChild &entryB);
|
||||||
|
@ -205,6 +205,87 @@ namespace AppList {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SavePages(std::vector<AppInfoPage> &entries) {
|
||||||
|
int ret = 0;
|
||||||
|
sqlite3 *db = nullptr;
|
||||||
|
char *error = nullptr;
|
||||||
|
char db_path_backup[] = "ur0:shell/db/app.db.sort.bkp";
|
||||||
|
|
||||||
|
if (R_FAILED(ret = FS::CopyFile(db_path, db_path_backup)))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READWRITE, nullptr);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
Log::Error("sqlite3_open_v2 failed to open %s\n", db_path);
|
||||||
|
FS::RemoveFile(db_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock power and prevent auto suspend.
|
||||||
|
Power::Lock();
|
||||||
|
|
||||||
|
const char *prepare_query[] = {
|
||||||
|
"BEGIN TRANSACTION",
|
||||||
|
"PRAGMA foreign_keys = off",
|
||||||
|
"DROP TABLE IF EXISTS tbl_appinfo_page_sort",
|
||||||
|
"CREATE TABLE tbl_appinfo_page_sort AS SELECT * FROM tbl_appinfo_page"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
ret = sqlite3_exec(db, prepare_query[i], nullptr, nullptr, &error);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
AppList::Error(prepare_query[i], error, db, db_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update tbl_appinfo_page_sort with swapped pages
|
||||||
|
for (unsigned int i = 0; i < entries.size(); i++) {
|
||||||
|
std::string query = std::string("UPDATE tbl_appinfo_page_sort ")
|
||||||
|
+ "SET pageNo = " + std::to_string(entries[i].pageNo) + " WHERE pageId = "
|
||||||
|
+ std::to_string(entries[i].pageId) + ";";
|
||||||
|
|
||||||
|
ret = sqlite3_exec(db, query.c_str(), nullptr, nullptr, &error);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
AppList::Error(query, error, db, db_path);
|
||||||
|
|
||||||
|
// If sorting fails, drop tbl_appinfo_page_sort.
|
||||||
|
query = std::string("DROP TABLE IF EXISTS tbl_appinfo_page_sort");
|
||||||
|
int ret_next = sqlite3_exec(db, query.c_str(), nullptr, nullptr, &error);
|
||||||
|
if (ret_next != SQLITE_OK) {
|
||||||
|
AppList::Error(query, error, db, db_path);
|
||||||
|
return ret_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *finish_query[] = {
|
||||||
|
"DROP TABLE tbl_appinfo_page",
|
||||||
|
"CREATE TABLE tbl_appinfo_page(pageId INTEGER PRIMARY KEY NOT NULL, pageNo INT NOT NULL, themeFile TEXT, bgColor INT, texWidth INT, texHeight INT, imageWidth INT, imageHeight INT, reserved01, reserved02, reserved03, reserved04, reserved05)",
|
||||||
|
"CREATE INDEX idx_page_no ON tbl_appinfo_page ( pageNo )",
|
||||||
|
"INSERT INTO tbl_appinfo_page SELECT * FROM tbl_appinfo_page_sort",
|
||||||
|
"DROP TABLE tbl_appinfo_page_sort",
|
||||||
|
"CREATE TRIGGER tgr_deletePage2 AFTER DELETE ON tbl_appinfo_page WHEN OLD.pageNo >= 0 BEGIN UPDATE tbl_appinfo_page SET pageNo = pageNo - 1 WHERE tbl_appinfo_page.pageNo > OLD.pageNo; END",
|
||||||
|
"CREATE TRIGGER tgr_insertPage2 BEFORE INSERT ON tbl_appinfo_page WHEN NEW.pageNo >= 0 BEGIN UPDATE tbl_appinfo_page SET pageNo = pageNo + 1 WHERE tbl_appinfo_page.pageNo >= NEW.pageNo; END",
|
||||||
|
"PRAGMA foreign_keys = on",
|
||||||
|
"COMMIT"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; ++i) {
|
||||||
|
ret = sqlite3_exec(db, finish_query[i], nullptr, nullptr, &error);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
AppList::Error(finish_query[i], error, db, db_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Power::Unlock();
|
||||||
|
sqlite3_close(db);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool SortAppAsc(const AppInfoIcon &entryA, const AppInfoIcon &entryB) {
|
bool SortAppAsc(const AppInfoIcon &entryA, const AppInfoIcon &entryB) {
|
||||||
std::string entryAname = cfg.sort_by == SortTitle? entryA.title : entryA.titleId;
|
std::string entryAname = cfg.sort_by == SortTitle? entryA.title : entryA.titleId;
|
||||||
std::string entryBname = cfg.sort_by == SortTitle? entryB.title : entryB.titleId;
|
std::string entryBname = cfg.sort_by == SortTitle? entryB.title : entryB.titleId;
|
||||||
|
115
source/gui.cpp
115
source/gui.cpp
@ -33,7 +33,8 @@ namespace Renderer {
|
|||||||
namespace GUI {
|
namespace GUI {
|
||||||
enum State {
|
enum State {
|
||||||
StateNone,
|
StateNone,
|
||||||
StateConfirm,
|
StateConfirmSort,
|
||||||
|
StateConfirmSwap,
|
||||||
StateRestore,
|
StateRestore,
|
||||||
StateLoadoutRestore,
|
StateLoadoutRestore,
|
||||||
StateWarning,
|
StateWarning,
|
||||||
@ -59,6 +60,7 @@ namespace GUI {
|
|||||||
static const ImVec2 tex_size = ImVec2(20, 20);
|
static const ImVec2 tex_size = ImVec2(20, 20);
|
||||||
static const char *sort_by[] = {"Title", "Title ID"};
|
static const char *sort_by[] = {"Title", "Title ID"};
|
||||||
static const char *sort_folders[] = {"Both", "Apps only", "Folders only"};
|
static const char *sort_folders[] = {"Both", "Apps only", "Folders only"};
|
||||||
|
static int old_page_id = -1;
|
||||||
|
|
||||||
static void SetupPopup(const char *id) {
|
static void SetupPopup(const char *id) {
|
||||||
ImGui::OpenPopup(id);
|
ImGui::OpenPopup(id);
|
||||||
@ -96,18 +98,23 @@ namespace GUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Prompt(State &state, std::vector<AppInfoIcon> &entries, std::vector<SceIoDirent> &loadouts, const std::string &db_name) {
|
static void Prompt(State &state, AppEntries &entries, std::vector<SceIoDirent> &loadouts, const std::string &db_name) {
|
||||||
if (state == StateNone)
|
if (state == StateNone)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string title, prompt;
|
std::string title, prompt;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case StateConfirm:
|
case StateConfirmSort:
|
||||||
title = "Confirm";
|
title = "Confirm";
|
||||||
prompt = "Are you sure you want to apply this sorting method? This may take a minute.";
|
prompt = "Are you sure you want to apply this sorting method? This may take a minute.";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case StateConfirmSwap:
|
||||||
|
title = "Confirm";
|
||||||
|
prompt = "Are you sure you want to apply this change?";
|
||||||
|
break;
|
||||||
|
|
||||||
case StateRestore:
|
case StateRestore:
|
||||||
title = "Restore Backup";
|
title = "Restore Backup";
|
||||||
prompt = "Are you sure you want to restore this backup?";
|
prompt = "Are you sure you want to restore this backup?";
|
||||||
@ -147,7 +154,7 @@ namespace GUI {
|
|||||||
if (ImGui::BeginPopupModal(title.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (ImGui::BeginPopupModal(title.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
ImGui::Text(prompt.c_str());
|
ImGui::Text(prompt.c_str());
|
||||||
|
|
||||||
if ((state == StateConfirm) || (state == StateRestore) || (state == StateLoadoutRestore)) {
|
if ((state == StateConfirmSort) || (state == StateRestore) || (state == StateLoadoutRestore)) {
|
||||||
ImGui::Dummy(ImVec2(0.0f, 5.0f));
|
ImGui::Dummy(ImVec2(0.0f, 5.0f));
|
||||||
ImGui::Text("You must reboot your device for the changes to take effect.");
|
ImGui::Text("You must reboot your device for the changes to take effect.");
|
||||||
}
|
}
|
||||||
@ -160,10 +167,19 @@ namespace GUI {
|
|||||||
|
|
||||||
if (ImGui::Button("Ok", ImVec2(120, 0))) {
|
if (ImGui::Button("Ok", ImVec2(120, 0))) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case StateConfirm:
|
case StateConfirmSort:
|
||||||
AppList::Backup();
|
AppList::Backup();
|
||||||
backupExists = true;
|
backupExists = true;
|
||||||
if ((AppList::Save(entries)) == 0)
|
if ((AppList::Save(entries.icons)) == 0)
|
||||||
|
state = StateDone;
|
||||||
|
else
|
||||||
|
state = StateError;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateConfirmSwap:
|
||||||
|
AppList::Backup();
|
||||||
|
backupExists = true;
|
||||||
|
if ((AppList::SavePages(entries.pages)) == 0)
|
||||||
state = StateDone;
|
state = StateDone;
|
||||||
else
|
else
|
||||||
state = StateError;
|
state = StateError;
|
||||||
@ -300,16 +316,16 @@ namespace GUI {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
GUI::DisableButtonInit(cfg.sort_mode == SortDefault);
|
GUI::DisableButtonInit(cfg.sort_mode == SortDefault);
|
||||||
if (ImGui::Button("Apply Sort"))
|
if (ImGui::Button("Apply Sort", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 0.0f)))
|
||||||
state = StateConfirm;
|
state = StateConfirmSort;
|
||||||
GUI::DisableButtonExit(cfg.sort_mode == SortDefault);
|
GUI::DisableButtonExit(cfg.sort_mode == SortDefault);
|
||||||
|
|
||||||
if (backupExists) {
|
ImGui::SameLine();
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
if (ImGui::Button("Restore Backup"))
|
GUI::DisableButtonInit(!backupExists);
|
||||||
state = StateRestore;
|
if (ImGui::Button("Restore Backup", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f)))
|
||||||
}
|
state = StateRestore;
|
||||||
|
GUI::DisableButtonExit(!backupExists);
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
@ -401,6 +417,68 @@ namespace GUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PagesTab(AppEntries &entries, State &state) {
|
||||||
|
ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter;
|
||||||
|
|
||||||
|
if (ImGui::BeginTabItem("Pages")) {
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
|
if (ImGui::Button("Reset", ImVec2(ImGui::GetContentRegionAvail().x * 0.33f, 0.0f))) {
|
||||||
|
AppList::Get(entries);
|
||||||
|
old_page_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (ImGui::Button("Apply Changes", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 0.0f)))
|
||||||
|
state = StateConfirmSwap;
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
GUI::DisableButtonInit(!backupExists);
|
||||||
|
if (ImGui::Button("Restore Backup", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f)))
|
||||||
|
state = StateRestore;
|
||||||
|
GUI::DisableButtonExit(!backupExists);
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
|
if (ImGui::BeginTable("PagesList", 3, tableFlags)) {
|
||||||
|
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
ImGui::TableSetupColumn("pageId");
|
||||||
|
ImGui::TableSetupColumn("pageNo");
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < entries.pages.size(); i++) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Image(reinterpret_cast<ImTextureID>(icons[DB].id), tex_size);
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%d", entries.pages[i].pageId);
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
std::string pageNo = std::to_string(entries.pages[i].pageNo);
|
||||||
|
const bool is_selected = (old_page_id == static_cast<int>(i));
|
||||||
|
if (ImGui::Selectable(pageNo.c_str(), is_selected)) {
|
||||||
|
if (old_page_id == -1)
|
||||||
|
old_page_id = i;
|
||||||
|
else {
|
||||||
|
int temp = entries.pages[i].pageNo;
|
||||||
|
entries.pages[i].pageNo = entries.pages[old_page_id].pageNo;
|
||||||
|
entries.pages[old_page_id].pageNo = temp;
|
||||||
|
old_page_id = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void LoadoutsTab(std::vector<SceIoDirent> &loadouts, State &state, int &date_format, std::string &loadout_name) {
|
static void LoadoutsTab(std::vector<SceIoDirent> &loadouts, State &state, int &date_format, std::string &loadout_name) {
|
||||||
ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter |
|
ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter |
|
||||||
ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY;
|
ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY;
|
||||||
@ -408,9 +486,9 @@ namespace GUI {
|
|||||||
if (ImGui::BeginTabItem("Loadouts")) {
|
if (ImGui::BeginTabItem("Loadouts")) {
|
||||||
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
if (ImGui::Button("Backup current loadout")) {
|
if (ImGui::Button("Backup current loadout", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f))) {
|
||||||
if (R_SUCCEEDED(Loadouts::Backup()))
|
if (R_SUCCEEDED(Loadouts::Backup()))
|
||||||
FS::GetDirList("ux0:data/VITAHomebrewSorter/loadouts", loadouts);
|
FS::GetDirList("ux0:data/VITAHomebrewSorter/loadouts", loadouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
@ -515,11 +593,15 @@ namespace GUI {
|
|||||||
int RenderLoop(void) {
|
int RenderLoop(void) {
|
||||||
bool done = false;
|
bool done = false;
|
||||||
backupExists = (FS::FileExists("ux0:/data/VITAHomebrewSorter/backup/app.db") || FS::FileExists("ux0:/data/VITAHomebrewSorter/backup/app.db.bkp"));
|
backupExists = (FS::FileExists("ux0:/data/VITAHomebrewSorter/backup/app.db") || FS::FileExists("ux0:/data/VITAHomebrewSorter/backup/app.db.bkp"));
|
||||||
|
|
||||||
AppEntries entries;
|
AppEntries entries;
|
||||||
std::vector<SceIoDirent> loadouts;
|
std::vector<SceIoDirent> loadouts;
|
||||||
|
|
||||||
AppList::Get(entries);
|
AppList::Get(entries);
|
||||||
FS::GetDirList("ux0:data/VITAHomebrewSorter/loadouts", loadouts);
|
FS::GetDirList("ux0:data/VITAHomebrewSorter/loadouts", loadouts);
|
||||||
|
|
||||||
int date_format = Utils::GetDateFormat();
|
int date_format = Utils::GetDateFormat();
|
||||||
|
|
||||||
std::string loadout_name;
|
std::string loadout_name;
|
||||||
State state = StateNone;
|
State state = StateNone;
|
||||||
SceCtrlData pad = { 0 };
|
SceCtrlData pad = { 0 };
|
||||||
@ -532,6 +614,7 @@ namespace GUI {
|
|||||||
if (ImGui::Begin("VITA Homebrew Sorter", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse)) {
|
if (ImGui::Begin("VITA Homebrew Sorter", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse)) {
|
||||||
if (ImGui::BeginTabBar("VITA Homebrew Sorter tabs")) {
|
if (ImGui::BeginTabBar("VITA Homebrew Sorter tabs")) {
|
||||||
GUI::SortTab(entries, state);
|
GUI::SortTab(entries, state);
|
||||||
|
GUI::PagesTab(entries, state);
|
||||||
GUI::DisableButtonInit(!cfg.beta_features);
|
GUI::DisableButtonInit(!cfg.beta_features);
|
||||||
GUI::LoadoutsTab(loadouts, state, date_format, loadout_name);
|
GUI::LoadoutsTab(loadouts, state, date_format, loadout_name);
|
||||||
GUI::DisableButtonExit(!cfg.beta_features);
|
GUI::DisableButtonExit(!cfg.beta_features);
|
||||||
@ -541,7 +624,7 @@ namespace GUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUI::ExitWindow();
|
GUI::ExitWindow();
|
||||||
GUI::Prompt(state, entries.icons, loadouts, loadout_name.c_str());
|
GUI::Prompt(state, entries, loadouts, loadout_name.c_str());
|
||||||
Renderer::End(true, ImVec4(0.45f, 0.55f, 0.60f, 1.00f));
|
Renderer::End(true, ImVec4(0.45f, 0.55f, 0.60f, 1.00f));
|
||||||
|
|
||||||
pad = Utils::ReadControls();
|
pad = Utils::ReadControls();
|
||||||
|
Loading…
Reference in New Issue
Block a user