This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/src/gui/search/SearchModel.cpp
2023-10-15 12:04:22 +02:00

304 lines
6.2 KiB
C++

#include "SearchModel.h"
#include "SearchView.h"
#include "Format.h"
#include "client/SaveInfo.h"
#include "client/GameSave.h"
#include "client/Client.h"
#include "client/http/SearchSavesRequest.h"
#include "client/http/SearchTagsRequest.h"
#include <algorithm>
#include <thread>
#include <cmath>
SearchModel::SearchModel():
currentSort(http::sortByVotes),
currentPage(1),
resultCount(0),
showOwn(false),
showFavourite(false),
showTags(true)
{
}
void SearchModel::SetShowTags(bool show)
{
showTags = show;
}
bool SearchModel::GetShowTags()
{
return showTags;
}
void SearchModel::BeginSearchSaves(int start, int count, String query, http::Sort sort, http::Category category)
{
lastError = "";
resultCount = 0;
searchSaves = std::make_unique<http::SearchSavesRequest>(start, count, query.ToUtf8(), sort, category);
searchSaves->Start();
}
std::vector<std::unique_ptr<SaveInfo>> SearchModel::EndSearchSaves()
{
std::vector<std::unique_ptr<SaveInfo>> saveArray;
try
{
std::tie(resultCount, saveArray) = searchSaves->Finish();
}
catch (const http::RequestError &ex)
{
lastError = ByteString(ex.what()).FromUtf8();
}
searchSaves.reset();
return saveArray;
}
void SearchModel::BeginGetTags(int start, int count, String query)
{
lastError = "";
ByteStringBuilder urlStream;
urlStream << SCHEME << SERVER << "/Browse/Tags.json?Start=" << start << "&Count=" << count;
if(query.length())
{
urlStream << "&Search_Query=";
if(query.length())
urlStream << format::URLEncode(query.ToUtf8());
}
getTags = std::make_unique<http::SearchTagsRequest>(start, count, query.ToUtf8());
getTags->Start();
}
std::vector<std::pair<ByteString, int>> SearchModel::EndGetTags()
{
std::vector<std::pair<ByteString, int>> tagArray;
try
{
tagArray = getTags->Finish();
}
catch (const http::RequestError &ex)
{
lastError = ByteString(ex.what()).FromUtf8();
}
getTags.reset();
return tagArray;
}
bool SearchModel::UpdateSaveList(int pageNumber, String query)
{
//Threading
if (!searchSaves)
{
lastQuery = query;
lastError = "";
saveListLoaded = false;
saveList.clear();
//resultCount = 0;
currentPage = pageNumber;
if(pageNumber == 1 && !showOwn && !showFavourite && currentSort == http::sortByVotes && query == "")
SetShowTags(true);
else
SetShowTags(false);
notifySaveListChanged();
notifyTagListChanged();
notifyPageChanged();
selected.clear();
notifySelectedChanged();
if (GetShowTags() && !tagList.size() && !getTags)
{
BeginGetTags(0, 24, "");
}
auto category = http::categoryNone;
if (showFavourite)
{
category = http::categoryFavourites;
}
if (showOwn && Client::Ref().GetAuthUser().UserID)
{
category = http::categoryMyOwn;
}
BeginSearchSaves((currentPage-1)*20, 20, lastQuery, currentSort, category);
return true;
}
return false;
}
void SearchModel::SetLoadedSave(std::unique_ptr<SaveInfo> save)
{
loadedSave = std::move(save);
}
const SaveInfo *SearchModel::GetLoadedSave() const
{
return loadedSave.get();
}
std::unique_ptr<SaveInfo> SearchModel::TakeLoadedSave()
{
return std::move(loadedSave);
}
std::vector<SaveInfo *> SearchModel::GetSaveList() // non-owning
{
std::vector<SaveInfo *> nonOwningSaveList;
std::transform(saveList.begin(), saveList.end(), std::back_inserter(nonOwningSaveList), [](auto &ptr) {
return ptr.get();
});
return nonOwningSaveList;
}
std::vector<std::pair<ByteString, int> > SearchModel::GetTagList()
{
return tagList;
}
void SearchModel::Update()
{
if (searchSaves && searchSaves->CheckDone())
{
saveListLoaded = true;
lastError = "";
saveList = EndSearchSaves();
notifyPageChanged();
notifySaveListChanged();
}
if (getTags && getTags->CheckDone())
{
lastError = "";
tagList = EndGetTags();
notifyTagListChanged();
}
}
void SearchModel::AddObserver(SearchView * observer)
{
observers.push_back(observer);
observer->NotifySaveListChanged(this);
observer->NotifyPageChanged(this);
observer->NotifySortChanged(this);
observer->NotifyShowOwnChanged(this);
observer->NotifyTagListChanged(this);
}
void SearchModel::SelectSave(int saveID)
{
for (size_t i = 0; i < selected.size(); i++)
{
if (selected[i] == saveID)
{
return;
}
}
selected.push_back(saveID);
notifySelectedChanged();
}
void SearchModel::SelectAllSaves()
{
if (selected.size() == saveList.size())
{
for (auto &save : saveList)
{
DeselectSave(save->id);
}
}
else
{
for (auto &save : saveList)
{
SelectSave(save->id);
}
}
}
void SearchModel::DeselectSave(int saveID)
{
bool changed = false;
restart:
for (size_t i = 0; i < selected.size(); i++)
{
if (selected[i] == saveID)
{
selected.erase(selected.begin()+i);
changed = true;
goto restart; //Just ensure all cases are removed.
}
}
if(changed)
notifySelectedChanged();
}
void SearchModel::notifySaveListChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifySaveListChanged(this);
}
}
void SearchModel::notifyTagListChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifyTagListChanged(this);
}
}
void SearchModel::notifyPageChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifyPageChanged(this);
}
}
void SearchModel::notifySortChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifySortChanged(this);
}
}
void SearchModel::notifyShowOwnChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifyShowOwnChanged(this);
}
}
void SearchModel::notifyShowFavouriteChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifyShowOwnChanged(this);
}
}
void SearchModel::notifySelectedChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifySelectedChanged(this);
}
}
int SearchModel::GetPageCount()
{
if (!showOwn && !showFavourite && currentSort == http::sortByVotes && lastQuery == "")
return std::max(1, (int)(ceil(resultCount/20.0f))+1); //add one for front page (front page saves are repeated twice)
else
return std::max(1, (int)(ceil(resultCount/20.0f)));
}