Browse Source

implement navigation history session save

CPP-GTK4
yggverse 3 months ago
parent
commit
a9d00188f4
  1. 37
      src/app/browser/main/tab/page/navigation.cpp
  2. 6
      src/app/browser/main/tab/page/navigation.hpp
  3. 246
      src/app/browser/main/tab/page/navigation/history.cpp
  4. 64
      src/app/browser/main/tab/page/navigation/history.hpp

37
src/app/browser/main/tab/page/navigation.cpp

@ -52,6 +52,7 @@ Navigation::Navigation(
); );
navigationHistory = Gtk::make_managed<navigation::History>( navigationHistory = Gtk::make_managed<navigation::History>(
db,
ACTION__NAVIGATION_HISTORY_BACK, ACTION__NAVIGATION_HISTORY_BACK,
ACTION__NAVIGATION_HISTORY_FORWARD ACTION__NAVIGATION_HISTORY_FORWARD
); );
@ -135,6 +136,13 @@ int Navigation::restore(
while (sqlite3_step(statement) == SQLITE_ROW) while (sqlite3_step(statement) == SQLITE_ROW)
{ {
// Restore children components // Restore children components
navigationHistory->restore(
sqlite3_column_int64(
statement,
DB::SESSION::ID
)
);
navigationRequest->restore( navigationRequest->restore(
sqlite3_column_int64( sqlite3_column_int64(
statement, statement,
@ -149,13 +157,33 @@ int Navigation::restore(
); );
} }
int Navigation::save( void Navigation::save(
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID
) { ) {
return navigationRequest->save( // Delete previous session
DB::SESSION::add( DB::SESSION::clean(
db,
APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID
);
// Create new record
const sqlite3_int64 APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID = DB::SESSION::add(
db, db,
APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID
);
// Delegate save action to children components
navigationHistory->save(
DB::SESSION::add(
db,
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
)
);
navigationRequest->save(
DB::SESSION::add(
db,
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
) )
); );
} }
@ -275,7 +303,8 @@ int Navigation::DB::SESSION::clean(
db, db,
Glib::ustring::sprintf( Glib::ustring::sprintf(
R"SQL( R"SQL(
SELECT * FROM `app_browser_main_tab_page_navigation__session` WHERE `app_browser_main_tab_page__session__id` = %d SELECT * FROM `app_browser_main_tab_page_navigation__session`
WHERE `app_browser_main_tab_page__session__id` = %d
)SQL", )SQL",
APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID
).c_str(), ).c_str(),

6
src/app/browser/main/tab/page/navigation.hpp

@ -94,11 +94,11 @@ namespace app::browser::main::tab::page
); );
int restore( int restore(
const sqlite3_int64 & APP_BROWSER_MAIN_TAB__SESSION__ID const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID
); // return sqlite3_finalize status code ); // return sqlite3_finalize status code
int save( void save(
const sqlite3_int64 & APP_BROWSER_MAIN_TAB__SESSION__ID const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE__SESSION__ID
); );
void history_add( void history_add(

246
src/app/browser/main/tab/page/navigation/history.cpp

@ -5,9 +5,16 @@
using namespace app::browser::main::tab::page::navigation; using namespace app::browser::main::tab::page::navigation;
History::History( History::History(
sqlite3 * db,
const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_BACK, const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_BACK,
const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_FORWARD const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_FORWARD
) { ) {
// Init database
DB::SESSION::init(
this->db = db
);
// Init widget
add_css_class( add_css_class(
"linked" // merge children elements "linked" // merge children elements
); );
@ -30,6 +37,106 @@ History::History(
} }
// Actions // Actions
void History::add(
const Glib::ustring & REQUEST,
const bool & UPDATE_MEMORY_INDEX
) {
memory.push_back(
{
REQUEST,
std::time(
nullptr
)
}
);
if (UPDATE_MEMORY_INDEX)
{
index = memory.size() - 1;
}
}
int History::restore(
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
) {
sqlite3_stmt* statement; // @TODO move to the DB model namespace
const int PREPARE_STATUS = sqlite3_prepare_v3(
db,
Glib::ustring::sprintf(
R"SQL(
SELECT * FROM `app_browser_main_tab_page_navigation_history__session`
WHERE `app_browser_main_tab_page_navigation__session__id` = %d
ORDER BY `id` DESC LIMIT 1
)SQL",
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
).c_str(),
-1,
SQLITE_PREPARE_NORMALIZE,
&statement,
nullptr
);
if (PREPARE_STATUS == SQLITE_OK)
{
// Use latest record as order
while (sqlite3_step(statement) == SQLITE_ROW)
{
// Cleanup
memory.clear();
// Restore
memory.push_back(
{
reinterpret_cast<const char*>(
sqlite3_column_text(
statement,
DB::SESSION::REQUEST
)
),
sqlite3_column_int(
statement,
DB::SESSION::TIME
)
}
);
if (sqlite3_column_int(statement, DB::SESSION::IS_CURRENT) == 1)
{
index = memory.size() - 1;
}
// Restore children components here (on available)
}
}
return sqlite3_finalize(
statement
);
}
void History::save(
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
) {
// Delete previous records for session
DB::SESSION::clean(
db,
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
);
// Add new records
for (const auto & VALUE : memory)
{
DB::SESSION::add(
db,
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID,
VALUE.time,
VALUE.request,
-1 == index // @TODO
);
}
}
void History::update() void History::update()
{ {
Memory match; Memory match;
@ -49,26 +156,6 @@ void History::update()
); );
} }
void History::add(
const Glib::ustring & REQUEST,
const bool & UPDATE_MEMORY_INDEX
) {
memory.push_back(
{
REQUEST,
std::time(
nullptr
),
true
}
);
if (UPDATE_MEMORY_INDEX)
{
index = memory.size() - 1;
}
}
bool History::try_back( bool History::try_back(
Memory & match, Memory & match,
const bool & UPDATE_MEMORY_INDEX const bool & UPDATE_MEMORY_INDEX
@ -116,3 +203,122 @@ bool History::try_forward(
return false; return false;
} }
} }
// Database model
int History::DB::SESSION::init(
sqlite3 * db
) {
char * error;
return sqlite3_exec(
db,
R"SQL(
CREATE TABLE IF NOT EXISTS `app_browser_main_tab_page_navigation_history__session`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `app_browser_main_tab_page_navigation__session__id` INTEGER NOT NULL,
`time` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
`request` VARCHAR (1024) NOT NULL,
`is_current` INTEGER NOT NULL
)
)SQL",
nullptr,
nullptr,
&error
);
}
int History::DB::SESSION::clean(
sqlite3 * db,
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
) {
char * error; // @TODO
sqlite3_stmt * statement;
const int PREPARE_STATUS = sqlite3_prepare_v3(
db,
Glib::ustring::sprintf(
R"SQL(
SELECT * FROM `app_browser_main_tab_page_navigation_history__session`
WHERE `app_browser_main_tab_page_navigation__session__id` = %d
)SQL",
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
).c_str(),
-1,
SQLITE_PREPARE_NORMALIZE,
&statement,
nullptr
);
if (PREPARE_STATUS == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
// Delete record
const int EXEC_STATUS = sqlite3_exec(
db,
Glib::ustring::sprintf(
R"SQL(
DELETE FROM `app_browser_main_tab_page_navigation_history__session` WHERE `id` = %d
)SQL",
sqlite3_column_int64(
statement,
DB::SESSION::ID
)
).c_str(),
nullptr,
nullptr,
&error
);
// Delegate children dependencies cleanup
if (EXEC_STATUS == SQLITE_OK)
{
// nothing here.
}
}
}
return sqlite3_finalize(
statement
);
}
sqlite3_int64 History::DB::SESSION::add(
sqlite3 * db,
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID,
const int & TIME,
const Glib::ustring & REQUEST,
const bool & IS_CURRENT
) {
char * error; // @TODO
sqlite3_exec(
db,
Glib::ustring::sprintf(
R"SQL(
INSERT INTO `app_browser_main_tab_page_navigation_history__session` (
`app_browser_main_tab_page_navigation__session__id`,
`time`,
`request`,
`is_current`
) VALUES (
'%d',
'%d',
'%s',
'%d'
)
)SQL",
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID,
TIME,
REQUEST,
IS_CURRENT
).c_str(),
nullptr,
nullptr,
&error
);
return sqlite3_last_insert_rowid(
db
);
}

64
src/app/browser/main/tab/page/navigation/history.hpp

@ -8,6 +8,7 @@
#include <glibmm/ustring.h> #include <glibmm/ustring.h>
#include <gtkmm/box.h> #include <gtkmm/box.h>
#include <gtkmm/object.h> #include <gtkmm/object.h>
#include <sqlite3.h>
#include <vector> #include <vector>
namespace app::browser::main::tab::page::navigation namespace app::browser::main::tab::page::navigation
@ -20,12 +21,63 @@ namespace app::browser::main::tab::page::navigation
class History : public Gtk::Box class History : public Gtk::Box
{ {
private:
/*
* History class database
*
* Allowed parental access to enums and relationship methods
*/
struct DB
{
// APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION_REQUEST__*
struct SESSION
{
enum
{
ID,
APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID,
TIME,
REQUEST,
IS_CURRENT
}; // table fields index
static int init(
sqlite3 * db
); // return sqlite3_exec status code
static int clean(
sqlite3 * db,
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
); // return sqlite3_finalize status code
static sqlite3_int64 add(
sqlite3 * db,
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID,
const int & TIME,
const Glib::ustring & REQUEST,
const bool & IS_CURRENT
); // return sqlite3_last_insert_rowid
};
};
/*
* Internal members
*/
private:
// Database
sqlite3 * db;
// Components // Components
history::Back * historyBack; history::Back * historyBack;
history::Forward * historyForward; history::Forward * historyForward;
// Extras
int index = -1; int index = -1;
/*
* History class API
*/
public: public:
// Extras // Extras
@ -33,13 +85,13 @@ namespace app::browser::main::tab::page::navigation
{ {
Glib::ustring request; Glib::ustring request;
std::time_t time; // event unix time std::time_t time; // event unix time
bool permanent; // save in database (on application close) @TODO
}; };
// Define navigation history storage // Define navigation history storage
std::vector<Memory> memory; std::vector<Memory> memory;
History( History(
sqlite3 * db,
const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_BACK, const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_BACK,
const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_FORWARD const Glib::RefPtr<Gio::SimpleAction> & ACTION__HISTORY_FORWARD
); );
@ -50,9 +102,15 @@ namespace app::browser::main::tab::page::navigation
const bool & UPDATE_MEMORY_INDEX const bool & UPDATE_MEMORY_INDEX
); );
void update(); int restore(
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
); // return sqlite3_finalize status code
void save(
const sqlite3_int64 & APP_BROWSER_MAIN_TAB_PAGE_NAVIGATION__SESSION__ID
);
void save(); // @TODO save history to the permanent storage void update();
bool try_back( bool try_back(
Memory & match, Memory & match,

Loading…
Cancel
Save