Front end halfway finished

This commit is contained in:
Paul 2018-03-02 00:32:44 +01:00
parent 5419b34061
commit aa3fde2010
15 changed files with 163 additions and 47 deletions

View File

@ -6,7 +6,7 @@
#include <vector>
#include <cstring>
#include <iostream>
#include "../common/c_processes.h"
#include "../common/functions.h"
#include "../steam/steam_api.h"
class CAchievementsDAO

View File

@ -14,7 +14,7 @@
#include <vector>
#include "Achievement_t.h"
#include "AchievementsDAO.h"
#include "../common/c_processes.h"
#include "../common/functions.h"
#include "../common/lodepng.h"
#include "../steam/steam_api.h"

View File

@ -39,13 +39,12 @@ m_builder(nullptr)
*/
void
MainPickerWindow::reset_game_list() {
//TODO
//for each m_rows
// gtk_widget_destroy
gtk_container_foreach(GTK_CONTAINER(m_game_list), (GtkCallback)gtk_widget_destroy, NULL);
//TODO refresh the view but I dont know how to
for (std::map<unsigned long, GtkWidget*>::iterator it = m_rows.begin(); it != m_rows.end(); ++it)
{
gtk_widget_destroy( GTK_WIDGET(it->second) );
}
m_rows.clear();
}
// => reset_game_list
@ -108,14 +107,18 @@ MainPickerWindow::refresh_app_icon(const unsigned long app_id) {
//TODO make sure app_id is index of m_rows
GList *children;
GtkImage *img;
GdkPixbuf *pixbuf;
GError *error;
std::string path(g_cache_folder);
error = nullptr;
path += "/";
path += std::to_string(app_id);
path += "/banner";
children = gtk_container_get_children(GTK_CONTAINER(m_rows[app_id])); //children = the layout
children = gtk_container_get_children(GTK_CONTAINER(children->data)); //children = first element of layout
//children = g_list_next(children); //children = second element of layout...
//children = g_list_next(children); //children = second element of layout...
img = GTK_IMAGE(children->data);
if( !GTK_IS_IMAGE(img) ) {
@ -125,6 +128,53 @@ MainPickerWindow::refresh_app_icon(const unsigned long app_id) {
}
g_list_free(children);
gtk_image_set_from_file(img, path.c_str());
pixbuf = gdk_pixbuf_new_from_file(path.c_str(), &error);
if (error != NULL) {
std::cerr << "Error while loading an app's logo: " << std::endl;
std::cerr << "AppId: " << app_id << std::endl;
std::cerr << "Message: " << error->message << std::endl;
}
else {
//Quick and jerky, quality isn't key here
// Is the excess of memory freed though?
pixbuf = gdk_pixbuf_scale_simple(pixbuf, 146, 68, GDK_INTERP_NEAREST);
gtk_image_set_from_pixbuf(img, pixbuf);
}
}
// => refresh_app_icon
// => refresh_app_icon
void
MainPickerWindow::filter_games(const char* filter_text) {
const std::string text_filter(filter_text);
std::string text_label;
gtk_widget_show_all( GTK_WIDGET(m_game_list) );
if(text_filter.empty()) {
return;
}
for (std::map<unsigned long, GtkWidget*>::iterator it = m_rows.begin(); it != m_rows.end(); ++it)
{
GList *children;
GtkLabel* label;
children = gtk_container_get_children(GTK_CONTAINER(it->second)); //children = the layout
children = gtk_container_get_children(GTK_CONTAINER(children->data)); //children = first element of layout
children = g_list_next(children); //children = label
label = GTK_LABEL( children->data );
if( !GTK_IS_LABEL(label) ) {
std::cerr << "The layout may have been modified, please tell me you're a dev, look at MainPikerWindow Blah blah TODO" << std::endl;
exit(EXIT_FAILURE);
}
text_label = std::string( gtk_label_get_text( GTK_LABEL(label) ) );
//Holy shit C++, why can't you even do case insensitive comparisons wtf
//strstri is just a shitty workaround there's no way to do this properly
if(!strstri(text_label, text_filter)) {
gtk_widget_hide( GTK_WIDGET(it->second) );
}
}
}

View File

@ -3,6 +3,7 @@
#include <gtk/gtk.h>
#include <iostream>
#include <map>
#include "../common/functions.h"
#include "globals.h"
#include "Game.h"
@ -45,6 +46,12 @@ public:
*/
void refresh_app_icon(const unsigned long app_id);
/**
* Filters the game list. For a title to stay displayed,
* filter_text must be included in it
*/
void filter_games(const char* filter_text);
/**
* Getter for the main window
*/

View File

@ -9,7 +9,7 @@
#include <dirent.h>
#include "Game.h"
#include "SteamAppDAO.h"
#include "../common/c_processes.h"
#include "../common/functions.h"
/**
* MySteam is a class that aims to retrieve as much data as

View File

@ -4,6 +4,17 @@
//TODO: Find a more elegant way to fix this shit.
std::map<unsigned long, std::string> SteamAppDAO::m_app_names = std::map<unsigned long, std::string>();
/**
* Lazy singleton pattern
*/
SteamAppDAO*
SteamAppDAO::get_instance() {
static SteamAppDAO me;
return &me;
}
// => get_instance
void
SteamAppDAO::update_name_database() {
bool need_to_redownload = false;

View File

@ -7,18 +7,18 @@
#include <dirent.h>
#include <fstream>
#include <sstream>
#include "../common/c_processes.h"
#include "../common/functions.h"
#include "../common/Downloader.h"
#include "globals.h"
#include "MainPickerWindow.h"
class SteamAppDAO : public Observer<unsigned long> {
public:
//TODO tidy
static SteamAppDAO* get_instance() {
static SteamAppDAO me;
return &me;
}
/**
* Singleton method to get the unique instance
*/
static SteamAppDAO* get_instance();
/**
* Redownloads http://api.steampowered.com/ISteamApps/GetAppList/v0002/
* if necessary. Redownloads every few days.
@ -45,6 +45,9 @@ public:
*/
void update(unsigned long i);
/**
* Delete these to avoid any singleton bypass
*/
SteamAppDAO(SteamAppDAO const&) = delete;
void operator=(SteamAppDAO const&) = delete;
private:

View File

@ -95,4 +95,14 @@ extern "C"
on_main_window_show() {
on_ask_game_refresh(); //Run this async?
}
void
on_search_changed(GtkWidget* search_widget) {
const char* filter_text = gtk_entry_get_text( GTK_ENTRY(search_widget) );
//if !g_steam->isgamerunning
g_main_gui->filter_games(filter_text);
//else
//g_main_gui->filter_stats()
}
}

View File

@ -1,5 +1,11 @@
#include "Downloader.h"
Downloader*
Downloader::get_instance() {
static Downloader me;
return &me;
}
void
Downloader::download_file(const std::string& file_url, const std::string& local_path, const unsigned long& dl_id) {
//If the file exists, there's no need to download it again.

View File

@ -1,29 +1,43 @@
#ifndef DOWNLOADER
#define DOWNLOADER
#pragma once
#include "ObserverClasses.h"
#include "c_processes.h"
#include "functions.h"
#include <curl/curl.h>
#include <string>
#include <future>
//TODO comment & tidy
/**
* This class is used to download files from the internet
* It follows a single singleton pattern and is meant to be very basic
* It inherits Subject, and will notify observers only on a successful
* download.
*/
class Downloader : public Subject<unsigned long> {
public:
static Downloader* get_instance() {
static Downloader me;
return &me;
};
/**
* Singleton method to get the unique instance
*/
static Downloader* get_instance();
/**
* Downloads a file synchronously. If the download fails, the program will exit.
* If the local_path already exists on the disk, the download will be skipped (as it if was successful)
* The download ID is something that will be passed to every observer once the download
* completed successfully.
*/
void download_file(const std::string& file_url, const std::string& local_path, const unsigned long& dl_id);
/**
* Does the same thing than download_file, but asynchronously.
*/
void download_file_async(const std::string& file_url, const std::string& local_path, const unsigned long& dl_id);
/**
* Delete these, as no one will need them with the singleton pattern
*/
Downloader(Downloader const&) = delete;
void operator=(Downloader const&) = delete;
private:
Downloader() {};
~Downloader() {};
};
#endif
};

View File

@ -1,4 +1,4 @@
#include "c_processes.h"
#include "functions.h"
pid_t create_process()
{
@ -18,9 +18,20 @@ bool file_exists(const std::string& name) {
char* concat(const char *s1, const char *s2)
{
char *result = (char*)malloc(strlen(s1)+strlen(s2)+1);//+1 for the null-terminator
char *result = (char*)malloc(strlen(s1)+strlen(s2)+1); //+1 for the null-terminator
//in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
bool strstri(const std::string & strHaystack, const std::string & strNeedle)
{
auto it = std::search(
strHaystack.begin(), strHaystack.end(),
strNeedle.begin(), strNeedle.end(),
[](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }
);
return (it != strHaystack.end() );
}

View File

@ -5,6 +5,8 @@
#include <errno.h>
#include <sys/stat.h>
#include <cstring>
#include <algorithm>
#include <cctype>
/**
* Wrapper for fork()
@ -20,4 +22,9 @@ bool file_exists(const std::string& name);
/**
* Concatenates two C strings
*/
char* concat(const char *s1, const char *s2);
char* concat(const char *s1, const char *s2);
/**
* Insensitive "string in string"
*/
bool strstri(const std::string & strHaystack, const std::string & strNeedle);

View File

@ -18,11 +18,11 @@
</packing>
</child>
<child>
<object class="GtkSpinner">
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">7</property>
<property name="active">True</property>
<property name="pixel_size">35</property>
<property name="icon_name">face-glasses</property>
</object>
<packing>
<property name="expand">False</property>
@ -34,11 +34,13 @@
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Loading your game library</property>
<property name="label" translatable="yes">It doesn't look like Sam could find anything interesting here...
You can still wait for him to bring more results</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">7</property>
<property name="position">2</property>
</packing>
</child>
@ -105,6 +107,9 @@
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<property name="placeholder_text" translatable="yes">Name of the game...</property>
<property name="input_hints">GTK_INPUT_HINT_NO_SPELLCHECK | GTK_INPUT_HINT_NONE</property>
<signal name="search-changed" handler="on_search_changed" swapped="no"/>
</object>
</child>
</object>
@ -113,7 +118,6 @@
<property name="height_request">500</property>
<property name="can_focus">False</property>
<property name="icon_name">face-wink</property>
<signal name="action-removed" handler="on_close_button_clicked" swapped="no"/>
<signal name="delete-event" handler="on_close_button_clicked" swapped="no"/>
<signal name="show" handler="on_main_window_show" swapped="no"/>
<child>

View File

@ -7,6 +7,6 @@ SCRIPTPATH=`dirname $SCRIPT`
g++ -g `pkg-config --cflags gtk+-3.0` -rdynamic -export-dynamic -pthread -Wall SAM.Picker/*.cpp common/*.cpp -L$SCRIPTPATH/bin -o $SCRIPTPATH/bin/samrewritten `pkg-config --libs gtk+-3.0` -lpthread -lgmodule-2.0 -lsteam_api -lcurl \
&& \
g++ -g SAM.Game/*.cpp common/c_processes.cpp common/lodepng.cpp -lsteam_api -L$SCRIPTPATH/bin -o $SCRIPTPATH/bin/samgame \
g++ -g SAM.Game/*.cpp common/functions.cpp common/lodepng.cpp -lsteam_api -L$SCRIPTPATH/bin -o $SCRIPTPATH/bin/samgame \
&& \
./bin/launch.sh

View File

@ -1,7 +0,0 @@
Most recent logged in user (useless) from cache:
/home/paul/.local/share/Steam/config/loginusers.vdf
All owned games from cache (WRONG):
/home/paul/.local/share/Steam/userdata/<steamid3>/config/localconfig.vdf
SEE if I cannot get all owned games with stats from /appcache.