From 9f7b06ff47e12076a261b6a209b27c558741eb8a Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Sat, 11 Feb 2012 16:08:59 +0000 Subject: [PATCH] Comments on save preview and some minor changes for vote bars --- .gitignore | 1 + src/client/Client.cpp | 46 ++++++++++++++++++++ src/client/Client.h | 2 + src/interface/Label.h | 5 ++- src/interface/SaveButton.cpp | 4 +- src/interface/Spinner.cpp | 36 ++++++++++++++++ src/interface/Spinner.h | 29 +++++++++++++ src/interface/Textblock.cpp | 76 ++++++++++++++++++++++++++++++++ src/interface/Textblock.h | 33 ++++++++++++++ src/preview/Comment.h | 24 +++++++++++ src/preview/PreviewModel.cpp | 84 ++++++++++++++++++++++++++++++++++-- src/preview/PreviewModel.h | 10 +++++ src/preview/PreviewView.cpp | 64 ++++++++++++++++++++++++--- src/preview/PreviewView.h | 6 +++ src/search/SearchView.cpp | 5 +++ src/search/SearchView.h | 2 + 16 files changed, 413 insertions(+), 14 deletions(-) create mode 100644 src/interface/Spinner.cpp create mode 100644 src/interface/Spinner.h create mode 100644 src/interface/Textblock.cpp create mode 100644 src/interface/Textblock.h create mode 100644 src/preview/Comment.h diff --git a/.gitignore b/.gitignore index 33ad7a8de..2198a5122 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.a *.la *~ +*.pref \ No newline at end of file diff --git a/src/client/Client.cpp b/src/client/Client.cpp index ce7c9e68c..5054dc42a 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -422,6 +422,52 @@ Thumbnail * Client::GetPreview(int saveID, int saveDate) } } +std::vector * Client::GetComments(int saveID, int start, int count) +{ + lastError = ""; + std::vector * commentArray = new std::vector(); + + std::stringstream urlStream; + char * data; + int dataStatus, dataLength; + urlStream << "http://" << SERVER << "/Browse/View.json?ID=" << saveID << "&Mode=Comments&Start=" << start << "&Count=" << count; + data = http_simple_get((char *)urlStream.str().c_str(), &dataStatus, &dataLength); + if(dataStatus == 200 && data) + { + try + { + std::istringstream dataStream(data); + json::Array commentsArray; + json::Reader::Read(commentsArray, dataStream); + + for(int j = 0; j < commentsArray.Size(); j++) + { + json::Number tempUserID = commentsArray[j]["UserID"]; + json::String tempUsername = commentsArray[j]["Username"]; + json::String tempComment = commentsArray[j]["Text"]; + commentArray->push_back( + new Comment( + tempUserID.Value(), + tempUsername.Value(), + tempComment.Value() + ) + ); + } + } + catch (json::Exception &e) + { + lastError = "Could not read response"; + } + } + else + { + lastError = http_ret_text(dataStatus); + } + if(data) + free(data); + return commentArray; +} + std::vector * Client::SearchSaves(int start, int count, string query, string sort, int & resultCount) { lastError = ""; diff --git a/src/client/Client.h b/src/client/Client.h index 4ca02876b..46c18483a 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -7,6 +7,7 @@ #include "Config.h" #include "HTTP.h" +#include "preview/Comment.h" #include "search/Thumbnail.h" #include "search/Save.h" #include "Singleton.h" @@ -52,6 +53,7 @@ public: LoginStatus Login(string username, string password, User & user); void ClearThumbnailRequests(); std::vector * SearchSaves(int start, int count, string query, string sort, int & resultCount); + std::vector * GetComments(int saveID, int start, int count); Thumbnail * GetPreview(int saveID, int saveDate); Thumbnail * GetThumbnail(int saveID, int saveDate); Save * GetSave(int saveID, int saveDate); diff --git a/src/interface/Label.h b/src/interface/Label.h index b92514067..4f7ce7f9e 100644 --- a/src/interface/Label.h +++ b/src/interface/Label.h @@ -11,6 +11,7 @@ namespace ui { class Label : public Component { + protected: std::string text; ui::Point textPosition; HorizontalAlignment textHAlign; @@ -23,8 +24,8 @@ namespace ui //Label(std::string labelText); virtual ~Label(); - void TextPosition(); - void SetText(std::string text); + virtual void TextPosition(); + virtual void SetText(std::string text); HorizontalAlignment GetHAlignment() { return textHAlign; } VerticalAlignment GetVAlignment() { return textVAlign; } void SetAlignment(HorizontalAlignment hAlign, VerticalAlignment vAlign) { textHAlign = hAlign; textVAlign = vAlign; TextPosition(); } diff --git a/src/interface/SaveButton.cpp b/src/interface/SaveButton.cpp index fa848bf30..c25143497 100644 --- a/src/interface/SaveButton.cpp +++ b/src/interface/SaveButton.cpp @@ -103,8 +103,8 @@ void SaveButton::Draw(const Point& screenPos) g->drawrect(screenPos.X-3+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbBoxSize.X, thumbBoxSize.Y, 180, 180, 180, 255); g->drawrect(screenPos.X-3+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, 6, thumbBoxSize.Y, 180, 180, 180, 255); - int voteBar = max(10.0f, ((float)(thumbBoxSize.Y))*voteRatio); - g->fillrect(screenPos.X-3+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(thumbBoxSize.Y-voteBar)+(Size.Y-21-thumbBoxSize.Y)/2, 6, voteBar, voteColour.Red, voteColour.Green, voteColour.Blue, 255); + int voteBar = max(10.0f, ((float)(thumbBoxSize.Y-2))*voteRatio); + g->fillrect(1+screenPos.X-3+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, 1+(screenPos.Y-2)+(thumbBoxSize.Y-voteBar)+(Size.Y-21-thumbBoxSize.Y)/2, 4, voteBar, voteColour.Red, voteColour.Green, voteColour.Blue, 255); } else { diff --git a/src/interface/Spinner.cpp b/src/interface/Spinner.cpp new file mode 100644 index 000000000..1ecad8d47 --- /dev/null +++ b/src/interface/Spinner.cpp @@ -0,0 +1,36 @@ +/* + * Spinner.cpp + * + * Created on: Feb 11, 2012 + * Author: Simon + */ + + +#include +#include +#include "Spinner.h" + +using namespace ui; + +Spinner::Spinner(Point position, Point size): + Component(position, size), cValue(0) +{ +} +void Spinner::Tick(float dt) +{ + cValue += 0.05f; +} +void Spinner::Draw(const Point& screenPos) +{ + Graphics * g = ui::Engine::Ref().g; + int baseX = screenPos.X+(Size.X/2); + int baseY = screenPos.Y+(Size.Y/2); + for(float t = 0.0f; t < 1.0f; t+=0.05f) + { + g->drawblob(baseX+(sin(cValue+t)*(Size.X/2)), baseY+(cos(cValue+t)*(Size.X/2)), t*255, t*255, t*255); + } +} +Spinner::~Spinner() +{ + +} diff --git a/src/interface/Spinner.h b/src/interface/Spinner.h new file mode 100644 index 000000000..089b0b535 --- /dev/null +++ b/src/interface/Spinner.h @@ -0,0 +1,29 @@ +/* + * Spinner.h + * + * Created on: Feb 11, 2012 + * Author: Simon + */ + +#ifndef SPINNER_H_ +#define SPINNER_H_ + +#include "Component.h" + +namespace ui +{ + +class Spinner: public Component +{ + float cValue; +public: + Spinner(Point position, Point size); + virtual void Tick(float dt); + virtual void Draw(const Point& screenPos); + virtual ~Spinner(); +}; + +} + + +#endif /* SPINNER_H_ */ diff --git a/src/interface/Textblock.cpp b/src/interface/Textblock.cpp new file mode 100644 index 000000000..c37892599 --- /dev/null +++ b/src/interface/Textblock.cpp @@ -0,0 +1,76 @@ +/* + * Textblock.cpp + * + * Created on: Jan 29, 2012 + * Author: Simon + */ + +#include +#include "Textblock.h" + +using namespace ui; + +Textblock::Textblock(Point position, Point size, std::string textboxText): + Label(position, size, textboxText) +{ + if(size.Y==-1) + autoHeight = true; + else + autoHeight = false; + updateMultiline(); +} + +void Textblock::SetText(std::string text) +{ + this->text = text; + updateMultiline(); +} + +void Textblock::updateMultiline() +{ + char * rawText = (char*)malloc(text.length()+1); + memcpy(rawText, text.c_str(), text.length()); + rawText[text.length()] = 0; + + int lines = 1; + int currentWidth = 0; + char * lastSpace = NULL; + char * currentWord = rawText; + char * nextSpace; + while(true) + { + nextSpace = strchr(currentWord+1, ' '); + if(nextSpace) + nextSpace[0] = 0; + int width = Graphics::textwidth(currentWord); + if(width+currentWidth > Size.X-6) + { + currentWidth = width; + currentWord[0] = '\n'; + lines++; + } + else + currentWidth += width; + if(nextSpace) + nextSpace[0] = ' '; + if(!(currentWord = strchr(currentWord+1, ' '))) + break; + } + if(autoHeight) + { + Size.Y = lines*12; + } + textLines = rawText; +} + +void Textblock::Draw(const Point &screenPos) +{ + Graphics * g = ui::Engine::Ref().g; + //g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, textColour.Red, textColour.Green, textColour.Blue, 255); + g->drawtext(screenPos.X+3, screenPos.Y+3, textLines, textColour.Red, textColour.Green, textColour.Blue, 255); +} + +Textblock::~Textblock() { + // TODO Auto-generated destructor stub +} + diff --git a/src/interface/Textblock.h b/src/interface/Textblock.h new file mode 100644 index 000000000..99b79e6fa --- /dev/null +++ b/src/interface/Textblock.h @@ -0,0 +1,33 @@ +/* + * Textblock.h + * + * Created on: Jan 29, 2012 + * Author: Simon + */ + +#ifndef TEXTBLOCK_H_ +#define TEXTBLOCK_H_ + +#include +#include +#include +#include "Label.h" + +namespace ui +{ + +class Textblock: public ui::Label +{ + bool autoHeight; + void updateMultiline(); + std::string textLines; +public: + Textblock(Point position, Point size, std::string textboxText); + virtual void TextPosition() {} + virtual void SetText(std::string text); + virtual void Draw(const Point& screenPos); + virtual ~Textblock(); +}; +} + +#endif /* TEXTBLOCK_H_ */ diff --git a/src/preview/Comment.h b/src/preview/Comment.h new file mode 100644 index 000000000..a53f6cd1f --- /dev/null +++ b/src/preview/Comment.h @@ -0,0 +1,24 @@ +/* + * Comment.h + * + * Created on: Feb 11, 2012 + * Author: Simon + */ + +#ifndef COMMENT_H_ +#define COMMENT_H_ + +class Comment +{ +public: + int authorID; + std::string authorName; + std::string comment; + Comment(int userID, std::string username, std::string commentText): + authorID(userID), authorName(username), comment(commentText) + { + } +}; + + +#endif /* COMMENT_H_ */ diff --git a/src/preview/PreviewModel.cpp b/src/preview/PreviewModel.cpp index dba7aa1b0..371d917c6 100644 --- a/src/preview/PreviewModel.cpp +++ b/src/preview/PreviewModel.cpp @@ -11,11 +11,14 @@ PreviewModel::PreviewModel(): save(NULL), savePreview(NULL), + saveComments(NULL), doOpen(false), updateSavePreviewWorking(false), updateSavePreviewFinished(false), updateSaveInfoWorking(false), - updateSaveInfoFinished(false) + updateSaveInfoFinished(false), + updateSaveCommentsWorking(false), + updateSaveCommentsFinished(false) { // TODO Auto-generated constructor stub @@ -31,6 +34,11 @@ void * PreviewModel::updateSavePreviewTHelper(void * obj) return ((PreviewModel*)obj)->updateSavePreviewT(); } +void * PreviewModel::updateSaveCommentsTHelper(void * obj) +{ + return ((PreviewModel*)obj)->updateSaveCommentsT(); +} + void * PreviewModel::updateSaveInfoT() { Save * tempSave = Client::Ref().GetSave(tSaveID, tSaveDate); @@ -45,15 +53,38 @@ void * PreviewModel::updateSavePreviewT() return tempThumb; } +void * PreviewModel::updateSaveCommentsT() +{ + std::vector * tempComments = Client::Ref().GetComments(tSaveID, 0, 10); + updateSaveCommentsFinished = true; + return tempComments; +} + void PreviewModel::UpdateSave(int saveID, int saveDate) { this->tSaveID = saveID; this->tSaveDate = saveDate; - save = NULL; - savePreview = NULL; + if(save) + { + delete save; + save = NULL; + } + if(savePreview) + { + delete savePreview; + savePreview = NULL; + } + if(saveComments) + { + for(int i = 0; i < saveComments->size(); i++) + delete saveComments->at(i); + delete saveComments; + saveComments = NULL; + } notifyPreviewChanged(); notifySaveChanged(); + notifySaveCommentsChanged(); if(!updateSavePreviewWorking) { @@ -68,6 +99,13 @@ void PreviewModel::UpdateSave(int saveID, int saveDate) updateSaveInfoFinished = false; pthread_create(&updateSaveInfoThread, 0, &PreviewModel::updateSaveInfoTHelper, this); } + + if(!updateSaveCommentsWorking) + { + updateSaveCommentsWorking = true; + updateSaveCommentsFinished = false; + pthread_create(&updateSaveCommentsThread, 0, &PreviewModel::updateSaveCommentsTHelper, this); + } } void PreviewModel::SetDoOpen(bool doOpen) @@ -90,6 +128,11 @@ Save * PreviewModel::GetSave() return save; } +std::vector * PreviewModel::GetComments() +{ + return saveComments; +} + void PreviewModel::notifyPreviewChanged() { for(int i = 0; i < observers.size(); i++) @@ -106,6 +149,14 @@ void PreviewModel::notifySaveChanged() } } +void PreviewModel::notifySaveCommentsChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyCommentsChanged(this); + } +} + void PreviewModel::AddObserver(PreviewView * observer) { observers.push_back(observer); observer->NotifyPreviewChanged(this); @@ -118,6 +169,11 @@ void PreviewModel::Update() { if(updateSavePreviewFinished) { + if(savePreview) + { + delete savePreview; + savePreview = NULL; + } updateSavePreviewWorking = false; pthread_join(updateSavePreviewThread, (void**)(&savePreview)); notifyPreviewChanged(); @@ -128,11 +184,33 @@ void PreviewModel::Update() { if(updateSaveInfoFinished) { + if(save) + { + delete save; + save = NULL; + } updateSaveInfoWorking = false; pthread_join(updateSaveInfoThread, (void**)(&save)); notifySaveChanged(); } } + + if(updateSaveCommentsWorking) + { + if(updateSaveCommentsFinished) + { + if(saveComments) + { + for(int i = 0; i < saveComments->size(); i++) + delete saveComments->at(i); + delete saveComments; + saveComments = NULL; + } + updateSaveCommentsWorking = false; + pthread_join(updateSaveCommentsThread, (void**)(&saveComments)); + notifySaveCommentsChanged(); + } + } } PreviewModel::~PreviewModel() { diff --git a/src/preview/PreviewModel.h b/src/preview/PreviewModel.h index e0e596696..84ce83da8 100644 --- a/src/preview/PreviewModel.h +++ b/src/preview/PreviewModel.h @@ -12,6 +12,7 @@ #include #include "PreviewView.h" #include "search/Save.h" +#include "preview/Comment.h" #include "search/Thumbnail.h" using namespace std; @@ -22,8 +23,10 @@ class PreviewModel { vector observers; Save * save; Thumbnail * savePreview; + std::vector * saveComments; void notifyPreviewChanged(); void notifySaveChanged(); + void notifySaveCommentsChanged(); //Background retrieval int tSaveID; @@ -40,10 +43,17 @@ class PreviewModel { pthread_t updateSaveInfoThread; static void * updateSaveInfoTHelper(void * obj); void * updateSaveInfoT(); + + bool updateSaveCommentsWorking; + volatile bool updateSaveCommentsFinished; + pthread_t updateSaveCommentsThread; + static void * updateSaveCommentsTHelper(void * obj); + void * updateSaveCommentsT(); public: PreviewModel(); Thumbnail * GetPreview(); Save * GetSave(); + std::vector * GetComments(); void AddObserver(PreviewView * observer); void UpdateSave(int saveID, int saveDate); bool GetDoOpen(); diff --git a/src/preview/PreviewView.cpp b/src/preview/PreviewView.cpp index 3a731dc11..aae792d3c 100644 --- a/src/preview/PreviewView.cpp +++ b/src/preview/PreviewView.cpp @@ -5,6 +5,7 @@ * Author: Simon */ +#include #include "PreviewView.h" #include "interface/Point.h" #include "interface/Window.h" @@ -51,6 +52,11 @@ PreviewView::PreviewView(): saveNameLabel->SetAlignment(AlignLeft, AlignBottom); AddComponent(saveNameLabel); + saveDescriptionTextblock = new ui::Textblock(ui::Point(5, (YRES/2)+15+14+17), ui::Point((XRES/2)-10, Size.Y-((YRES/2)+15+14+17)-21), ""); + saveDescriptionTextblock->SetAlignment(AlignLeft, AlignTop); + saveDescriptionTextblock->SetTextColour(ui::Colour(180, 180, 180)); + AddComponent(saveDescriptionTextblock); + authorDateLabel = new ui::Label(ui::Point(5, (YRES/2)+15+14), ui::Point(100, 16), ""); authorDateLabel->SetAlignment(AlignLeft, AlignBottom); AddComponent(authorDateLabel); @@ -78,13 +84,13 @@ void PreviewView::OnDraw() if(!votesUp && !votesDown) return; else - factor = (float)(((float)(XRES/2))/((float)(votesUp+votesDown))); - g->fillrect(Position.X, Position.Y+YRES/2, XRES/2, 10, 200, 50, 50, 255); - g->fillrect(Position.X, Position.Y+YRES/2, (int)(((float)votesUp)*factor), 10, 50, 200, 50, 255); - g->fillrect(Position.X, Position.Y+(YRES/2), 14, 10, 0, 0, 0, 100); - g->fillrect(Position.X+(XRES/2)-14, Position.Y+(YRES/2), 14, 10, 0, 0, 0, 100); - g->draw_icon(Position.X+2, Position.Y+(YRES/2)+2, IconVoteUp); - g->draw_icon(Position.X+(XRES/2)-12, Position.Y+(YRES/2), IconVoteDown); + factor = (float)(((float)(XRES/2)-2)/((float)(votesUp+votesDown))); + g->fillrect(1+Position.X, 1+Position.Y+YRES/2, (XRES/2)-2, 8, 200, 50, 50, 255); + g->fillrect(1+Position.X, 1+Position.Y+YRES/2, (int)(((float)votesUp)*factor), 8, 50, 200, 50, 255); + g->fillrect(1+Position.X, 1+Position.Y+(YRES/2), 14, 8, 0, 0, 0, 100); + g->fillrect(Position.X+(XRES/2)-15, 1+Position.Y+(YRES/2), 14, 8, 0, 0, 0, 100); + g->draw_icon(1+Position.X+2, Position.Y+(YRES/2)+2, IconVoteUp); + g->draw_icon(Position.X+(XRES/2)-12, Position.Y+(YRES/2)-1, IconVoteDown); } void PreviewView::OnTick(float dt) @@ -107,6 +113,7 @@ void PreviewView::NotifySaveChanged(PreviewModel * sender) votesDown = save->votesDown; saveNameLabel->SetText(save->name); authorDateLabel->SetText("\bgAuthor:\bw " + save->userName + " \bgDate:\bw "); + saveDescriptionTextblock->SetText(save->Description); } else { @@ -114,6 +121,49 @@ void PreviewView::NotifySaveChanged(PreviewModel * sender) votesDown = 0; saveNameLabel->SetText(""); authorDateLabel->SetText(""); + saveDescriptionTextblock->SetText(""); + } +} + +void PreviewView::NotifyCommentsChanged(PreviewModel * sender) +{ + for(int i = 0; i < commentComponents.size(); i++) + { + RemoveComponent(commentComponents[i]); + delete commentComponents[i]; + } + commentComponents.clear(); + + int currentY = 0; + ui::Label * tempUsername; + ui::Textblock * tempComment; + std::vector * tempComments = sender->GetComments(); + if(tempComments) + { + for(int i = 0; i < tempComments->size(); i++) + { + tempUsername = new ui::Label(ui::Point((XRES/2) + 5, currentY+5), ui::Point(Size.X-((XRES/2) + 10), 16), tempComments->at(i)->authorName); + tempUsername->SetAlignment(AlignLeft, AlignBottom); + currentY += 16; + tempComment = new ui::Textblock(ui::Point((XRES/2) + 5, currentY+5), ui::Point(Size.X-((XRES/2) + 10), -1), tempComments->at(i)->comment); + tempComment->SetAlignment(AlignLeft, AlignTop); + tempComment->SetTextColour(ui::Colour(180, 180, 180)); + currentY += tempComment->Size.Y+4; + + if(currentY > Size.Y) + { + delete tempUsername; + delete tempComment; + break; + } + else + { + commentComponents.push_back(tempComment); + AddComponent(tempComment); + commentComponents.push_back(tempUsername); + AddComponent(tempUsername); + } + } } } diff --git a/src/preview/PreviewView.h b/src/preview/PreviewView.h index 9368732b9..11ed4bd88 100644 --- a/src/preview/PreviewView.h +++ b/src/preview/PreviewView.h @@ -7,12 +7,15 @@ #ifndef PREVIEWVIEW_H_ #define PREVIEWVIEW_H_ + +#include #include "interface/Window.h" #include "preview/PreviewController.h" #include "preview/PreviewModel.h" #include "interface/Button.h" #include "search/Thumbnail.h" #include "interface/Label.h" +#include "interface/Textblock.h" class PreviewModel; class PreviewController; @@ -23,6 +26,8 @@ class PreviewView: public ui::Window { ui::Button * browserOpenButton; ui::Label * saveNameLabel; ui::Label * authorDateLabel; + ui::Textblock * saveDescriptionTextblock; + std::vector commentComponents; int votesUp; int votesDown; public: @@ -30,6 +35,7 @@ public: PreviewView(); void NotifyPreviewChanged(PreviewModel * sender); void NotifySaveChanged(PreviewModel * sender); + void NotifyCommentsChanged(PreviewModel * sender); virtual void OnDraw(); virtual void OnTick(float dt); virtual void OnMouseDown(int x, int y, unsigned button); diff --git a/src/search/SearchView.cpp b/src/search/SearchView.cpp index b9c8bcb0e..584b7e37c 100644 --- a/src/search/SearchView.cpp +++ b/src/search/SearchView.cpp @@ -91,6 +91,9 @@ SearchView::SearchView(): AddComponent(searchField); AddComponent(infoLabel); + loadingSpinner = new ui::Spinner(ui::Point(((XRES+BARSIZE)/2)-12, ((YRES+MENUSIZE)/2)+12), ui::Point(24, 24)); + AddComponent(loadingSpinner); + ui::Label * searchPrompt = new ui::Label(ui::Point(10, 10), ui::Point(50, 16), "Search:"); searchPrompt->SetAlignment(AlignLeft, AlignBottom); AddComponent(searchPrompt); @@ -172,6 +175,7 @@ void SearchView::NotifySaveListChanged(SearchModel * sender) if(!sender->GetSavesLoaded()) { errorLabel->SetText("Loading..."); + loadingSpinner->Visible = true; } else { @@ -183,6 +187,7 @@ void SearchView::NotifySaveListChanged(SearchModel * sender) } else { + loadingSpinner->Visible = false; if(errorLabel) { RemoveComponent(errorLabel); diff --git a/src/search/SearchView.h b/src/search/SearchView.h index a2a529786..01034198e 100644 --- a/src/search/SearchView.h +++ b/src/search/SearchView.h @@ -6,6 +6,7 @@ #include "interface/SaveButton.h" #include "interface/Button.h" #include "interface/Label.h" +#include "interface/Spinner.h" #include "interface/Textbox.h" using namespace std; @@ -25,6 +26,7 @@ private: ui::Label * infoLabel; ui::Button * sortButton; ui::Button * ownButton; + ui::Spinner * loadingSpinner; void doSearch(); public: void NotifySaveListChanged(SearchModel * sender);