mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
501 lines
No EOL
11 KiB
C++
501 lines
No EOL
11 KiB
C++
#include "tab.hpp"
|
|
#include "tab/label.hpp"
|
|
#include "tab/page.hpp"
|
|
|
|
using namespace app::browser::main;
|
|
|
|
Tab::Tab(
|
|
sqlite3 * db,
|
|
const Glib::RefPtr<Gio::SimpleAction> & ACTION__UPDATE,
|
|
const Glib::RefPtr<Gio::SimpleAction> & ACTION__TAB_CLOSE_ACTIVE,
|
|
const Glib::RefPtr<Gio::SimpleAction> & ACTION__MAIN_TAB_CLOSE_ALL,
|
|
const Glib::RefPtr<Gio::SimpleAction> & ACTION__TAB_PAGE_NAVIGATION_HISTORY_BACK,
|
|
const Glib::RefPtr<Gio::SimpleAction> & ACTION__TAB_PAGE_NAVIGATION_HISTORY_FORWARD,
|
|
const Glib::RefPtr<Gio::SimpleAction> & ACTION__TAB_PAGE_NAVIGATION_RELOAD
|
|
) {
|
|
// Init database
|
|
DB::SESSION::init(
|
|
this->db = db
|
|
);
|
|
|
|
// Init actions
|
|
action__update = ACTION__UPDATE;
|
|
action__tab_close_active = ACTION__TAB_CLOSE_ACTIVE;
|
|
action__tab_close_all = ACTION__MAIN_TAB_CLOSE_ALL;
|
|
action__tab_page_navigation_history_back = ACTION__TAB_PAGE_NAVIGATION_HISTORY_BACK;
|
|
action__tab_page_navigation_history_forward = ACTION__TAB_PAGE_NAVIGATION_HISTORY_FORWARD;
|
|
action__tab_page_navigation_reload = ACTION__TAB_PAGE_NAVIGATION_RELOAD;
|
|
|
|
// Init widget
|
|
set_scrollable(
|
|
SCROLLABLE
|
|
);
|
|
|
|
signal_switch_page().connect(
|
|
[this](Gtk::Widget*, guint)
|
|
{
|
|
// Update window elements, e.g. tab label to header bar
|
|
action__update->activate();
|
|
}
|
|
);
|
|
}
|
|
|
|
int Tab::restore(
|
|
const sqlite3_int64 & APP_BROWSER_MAIN__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__session`
|
|
WHERE `app_browser_main__session__id` = %d ORDER BY `page_number` ASC
|
|
)SQL",
|
|
APP_BROWSER_MAIN__SESSION__ID
|
|
).c_str(),
|
|
-1,
|
|
SQLITE_PREPARE_NORMALIZE,
|
|
&statement,
|
|
nullptr
|
|
);
|
|
|
|
if (PREPARE_STATUS == SQLITE_OK)
|
|
{
|
|
close_all();
|
|
|
|
while (sqlite3_step(statement) == SQLITE_ROW)
|
|
{
|
|
const int PAGE_NUMBER = append(
|
|
_("Restore"),
|
|
sqlite3_column_int(
|
|
statement,
|
|
DB::SESSION::IS_CURRENT
|
|
) == 1
|
|
);
|
|
|
|
// Restore children components
|
|
get_tabLabel(
|
|
PAGE_NUMBER
|
|
)->restore(
|
|
sqlite3_column_int64(
|
|
statement,
|
|
DB::SESSION::ID
|
|
)
|
|
); // maybe not much reasons to restore as page title in use @TODO
|
|
|
|
get_tabPage(
|
|
PAGE_NUMBER
|
|
)->restore(
|
|
sqlite3_column_int64(
|
|
statement,
|
|
DB::SESSION::ID
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
return sqlite3_finalize(
|
|
statement
|
|
);
|
|
}
|
|
|
|
void Tab::save(
|
|
const sqlite3_int64 & APP_BROWSER_MAIN__SESSION__ID
|
|
) {
|
|
char * error; // @TODO
|
|
|
|
// Delete previous data
|
|
DB::SESSION::clean(
|
|
db,
|
|
APP_BROWSER_MAIN__SESSION__ID
|
|
); // @TODO run on background
|
|
|
|
// Save current tab session
|
|
for (int page_number = 0; page_number < get_n_pages(); page_number++)
|
|
{
|
|
// Create new session
|
|
const sqlite3_int64 APP_BROWSER_MAIN_TAB__SESSION__ID = DB::SESSION::add(
|
|
db,
|
|
APP_BROWSER_MAIN__SESSION__ID,
|
|
page_number,
|
|
page_number == get_current_page()
|
|
);
|
|
|
|
// Delegate save actions to children components
|
|
get_tabLabel(
|
|
page_number
|
|
)->save(
|
|
APP_BROWSER_MAIN_TAB__SESSION__ID
|
|
);
|
|
|
|
get_tabPage(
|
|
page_number
|
|
)->save(
|
|
APP_BROWSER_MAIN_TAB__SESSION__ID
|
|
);
|
|
}
|
|
}
|
|
|
|
// Actions
|
|
void Tab::update(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
// Get tab page
|
|
const auto TAB_PAGE = get_tabPage(
|
|
PAGE_NUMBER
|
|
);
|
|
|
|
// Update tab page component
|
|
TAB_PAGE->update();
|
|
|
|
// Update tab label component
|
|
get_tabLabel(
|
|
PAGE_NUMBER
|
|
)->set_label(
|
|
TAB_PAGE->get_title()
|
|
);
|
|
|
|
// Update tab actions status
|
|
action__tab_close_active->set_enabled(
|
|
get_n_pages() > 0
|
|
);
|
|
|
|
action__tab_close_all->set_enabled(
|
|
get_n_pages() > 0
|
|
);
|
|
}
|
|
|
|
void Tab::update(
|
|
const int & PAGE_NUMBER,
|
|
const Glib::ustring & URI
|
|
) {
|
|
// Get tab page
|
|
const auto TAB_PAGE = get_tabPage(
|
|
PAGE_NUMBER
|
|
);
|
|
|
|
// Update tab page component
|
|
TAB_PAGE->update(
|
|
URI
|
|
);
|
|
|
|
// Update tab label component
|
|
get_tabLabel(
|
|
PAGE_NUMBER
|
|
)->set_label(
|
|
TAB_PAGE->get_title()
|
|
);
|
|
|
|
// Update tab actions status
|
|
action__tab_close_active->set_enabled(
|
|
get_n_pages() > 0
|
|
);
|
|
|
|
action__tab_close_all->set_enabled(
|
|
get_n_pages() > 0
|
|
);
|
|
}
|
|
|
|
int Tab::append(
|
|
const Glib::ustring & LABEL_TEXT,
|
|
const bool & IS_CURRENT
|
|
) {
|
|
const auto TAB_PAGE = new tab::Page( // @TODO manage
|
|
db,
|
|
tab::Page::MIME::UNDEFINED,
|
|
LABEL_TEXT,
|
|
"", // @TODO restore feature
|
|
|
|
action__update,
|
|
action__tab_page_navigation_history_back,
|
|
action__tab_page_navigation_history_forward,
|
|
action__tab_page_navigation_reload
|
|
);
|
|
|
|
const auto TAB_LABEL = new tab::Label( // @TODO manage
|
|
db,
|
|
action__tab_close_active
|
|
);
|
|
|
|
const int PAGE_NUMBER = append_page(
|
|
* TAB_PAGE,
|
|
* TAB_LABEL
|
|
);
|
|
|
|
set_tab_reorderable(
|
|
* TAB_PAGE,
|
|
REORDERABLE
|
|
);
|
|
|
|
if (IS_CURRENT)
|
|
{
|
|
set_current_page(
|
|
PAGE_NUMBER
|
|
);
|
|
}
|
|
|
|
update(
|
|
PAGE_NUMBER
|
|
);
|
|
|
|
return PAGE_NUMBER;
|
|
};
|
|
|
|
void Tab::close(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
remove_page(
|
|
PAGE_NUMBER
|
|
);
|
|
|
|
// @TODO cleanup memory ot use managed children widgets
|
|
// @TODO fix GtkGizmo reported min height, but sizes must be >= 0
|
|
}
|
|
|
|
void Tab::close_left()
|
|
{} // @TODO
|
|
|
|
void Tab::close_right()
|
|
{} // @TODO
|
|
|
|
void Tab::close_all()
|
|
{
|
|
while (0 <= get_current_page())
|
|
{
|
|
close(
|
|
-1 // last
|
|
);
|
|
}
|
|
}
|
|
|
|
void Tab::page_navigation_reload(
|
|
const int & PAGE_NUMBER,
|
|
const bool & ADD_HISTORY
|
|
) {
|
|
get_tabPage(
|
|
PAGE_NUMBER
|
|
)->navigation_reload(
|
|
ADD_HISTORY
|
|
);
|
|
}
|
|
|
|
void Tab::page_navigation_history_back(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
get_tabPage(
|
|
PAGE_NUMBER
|
|
)->navigation_history_back();
|
|
}
|
|
|
|
void Tab::page_navigation_history_forward(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
get_tabPage(
|
|
PAGE_NUMBER
|
|
)->navigation_history_forward();
|
|
}
|
|
|
|
// Getters
|
|
Glib::ustring Tab::get_page_title(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
return get_tabPage(
|
|
PAGE_NUMBER
|
|
)->get_title();
|
|
};
|
|
|
|
Glib::ustring Tab::get_page_description(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
return get_tabPage(
|
|
PAGE_NUMBER
|
|
)->get_description();
|
|
};
|
|
|
|
tab::Label * Tab::get_tabLabel(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
// Get page pointer to find label widget
|
|
const auto PAGE = get_nth_page(
|
|
PAGE_NUMBER
|
|
);
|
|
|
|
if (PAGE == nullptr)
|
|
{
|
|
throw _("Page not found!"); // @TODO
|
|
}
|
|
|
|
// Get label widget by page pointer
|
|
const auto LABEL = get_tab_label(
|
|
* PAGE
|
|
);
|
|
|
|
if (LABEL == nullptr)
|
|
{
|
|
throw _("Label not found!"); // @TODO
|
|
}
|
|
|
|
// Downcast
|
|
const auto TAB_LABEL = dynamic_cast<tab::Label*>(
|
|
LABEL
|
|
);
|
|
|
|
if (TAB_LABEL == nullptr)
|
|
{
|
|
throw _("Tab label not found!"); // @TODO
|
|
}
|
|
|
|
return TAB_LABEL;
|
|
}
|
|
|
|
tab::Page * Tab::get_tabPage(
|
|
const int & PAGE_NUMBER
|
|
) {
|
|
// Get page widget
|
|
const auto PAGE = get_nth_page(
|
|
PAGE_NUMBER
|
|
);
|
|
|
|
if (PAGE == nullptr)
|
|
{
|
|
throw _("Page not found!"); // @TODO
|
|
}
|
|
|
|
// Downcast
|
|
const auto TAB_PAGE = dynamic_cast<tab::Page*>(
|
|
PAGE
|
|
);
|
|
|
|
if (TAB_PAGE == nullptr)
|
|
{
|
|
throw _("Tab page not found!"); // @TODO
|
|
}
|
|
|
|
return TAB_PAGE;
|
|
}
|
|
|
|
// Database
|
|
int Tab::DB::SESSION::init(
|
|
sqlite3 * db
|
|
) {
|
|
char * error;
|
|
|
|
return sqlite3_exec(
|
|
db,
|
|
R"SQL(
|
|
CREATE TABLE IF NOT EXISTS `app_browser_main_tab__session`
|
|
(
|
|
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `app_browser_main__session__id` INTEGER NOT NULL,
|
|
`time` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`page_number` INTEGER NOT NULL,
|
|
`is_current` INTEGER NOT NULL
|
|
)
|
|
)SQL",
|
|
nullptr,
|
|
nullptr,
|
|
&error
|
|
);
|
|
}
|
|
|
|
int Tab::DB::SESSION::clean(
|
|
sqlite3 * db,
|
|
const sqlite3_int64 & APP_BROWSER_MAIN__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__session`
|
|
WHERE `app_browser_main__session__id` = %d
|
|
)SQL",
|
|
APP_BROWSER_MAIN__SESSION__ID
|
|
).c_str(),
|
|
-1,
|
|
SQLITE_PREPARE_NORMALIZE,
|
|
&statement,
|
|
nullptr
|
|
);
|
|
|
|
if (PREPARE_STATUS == SQLITE_OK)
|
|
{
|
|
while (sqlite3_step(statement) == SQLITE_ROW)
|
|
{
|
|
const sqlite3_int64 APP_BROWSER_MAIN_TAB__SESSION__ID = sqlite3_column_int64(
|
|
statement,
|
|
DB::SESSION::ID
|
|
);
|
|
|
|
// Delete record
|
|
const int EXEC_STATUS = sqlite3_exec(
|
|
db,
|
|
Glib::ustring::sprintf(
|
|
R"SQL(
|
|
DELETE FROM `app_browser_main_tab__session` WHERE `id` = %d
|
|
)SQL",
|
|
APP_BROWSER_MAIN_TAB__SESSION__ID
|
|
).c_str(),
|
|
nullptr,
|
|
nullptr,
|
|
&error
|
|
);
|
|
|
|
// Delegate children dependencies cleanup
|
|
if (EXEC_STATUS == SQLITE_OK)
|
|
{
|
|
tab::Label::DB::SESSION::clean(
|
|
db,
|
|
APP_BROWSER_MAIN_TAB__SESSION__ID
|
|
);
|
|
|
|
tab::Page::DB::SESSION::clean(
|
|
db,
|
|
APP_BROWSER_MAIN_TAB__SESSION__ID
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return sqlite3_finalize(
|
|
statement
|
|
);
|
|
}
|
|
|
|
sqlite3_int64 Tab::DB::SESSION::add(
|
|
sqlite3 * db,
|
|
const sqlite3_int64 & APP_BROWSER_MAIN__SESSION__ID,
|
|
const int & PAGE_NUMBER,
|
|
const bool & IS_CURRENT
|
|
) {
|
|
char * error; // @TODO
|
|
|
|
sqlite3_exec(
|
|
db,
|
|
Glib::ustring::sprintf(
|
|
R"SQL(
|
|
INSERT INTO `app_browser_main_tab__session` (
|
|
`app_browser_main__session__id`,
|
|
`page_number`,
|
|
`is_current`
|
|
) VALUES (
|
|
%d,
|
|
%d,
|
|
%d
|
|
)
|
|
)SQL",
|
|
APP_BROWSER_MAIN__SESSION__ID,
|
|
PAGE_NUMBER,
|
|
IS_CURRENT ? 1 : 0
|
|
).c_str(),
|
|
nullptr,
|
|
nullptr,
|
|
&error
|
|
);
|
|
|
|
return sqlite3_last_insert_rowid(
|
|
db
|
|
);
|
|
} |