diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afe419586..6355f1ac1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,14 +20,14 @@ jobs: run: meson builddir - name: build run: ninja -v -C builddir + - name: install + run: ninja -C builddir install - name: test run: | sudo ifconfig lo0 alias 127.0.0.2 up sudo ifconfig lo0 alias 127.0.0.3 up sudo ifconfig lo0 alias 127.0.0.4 up ninja -v -C builddir test - - name: install - run: ninja -C builddir install build-on-linux: strategy: @@ -45,10 +45,10 @@ jobs: CXX: ${{ matrix.compiler }} - name: build run: ninja -v -C builddir - - name: test - run: xvfb-run ninja -v -C builddir test - name: install run: sudo ninja -C builddir install + - name: test + run: xvfb-run ninja -v -C builddir test codecov: runs-on: ubuntu-20.04 @@ -60,10 +60,10 @@ jobs: run: meson -D b_coverage=true builddir - name: build run: ninja -v -C builddir - - name: test - run: xvfb-run ninja -v -C builddir test - name: install run: sudo ninja -C builddir install + - name: test + run: xvfb-run ninja -v -C builddir test - name: lcov run: | lcov --directory . --capture --output-file coverage.info; # capture coverage info diff --git a/src/iptux/Application.cpp b/src/iptux/Application.cpp index 162ae3e08..e5de7f842 100644 --- a/src/iptux/Application.cpp +++ b/src/iptux/Application.cpp @@ -58,10 +58,13 @@ Application::Application(shared_ptr config) app = gtk_application_new (application_id.c_str(), G_APPLICATION_FLAGS_NONE); g_signal_connect_swapped(app, "startup", G_CALLBACK(onStartup), this); g_signal_connect_swapped(app, "activate", G_CALLBACK(onActivate), this); + + transModel = transModelNew(); } Application::~Application() { g_object_unref(app); + transModelDelete(transModel); delete window; } @@ -69,10 +72,19 @@ int Application::run(int argc, char** argv) { return g_application_run (G_APPLICATION (app), argc, argv); } +void Application::startup() { + Application::onStartup(*this); +} + +void Application::activate() { + Application::onActivate(*this); +} + void Application::onStartup(Application& self) { self.data = make_shared(self.config); - g_cthrd = new UiCoreThread(self.data); - self.window = new MainWindow(self.app, *g_cthrd); + self.cthrd = make_shared(self.data); + g_cthrd = self.cthrd.get(); + self.window = new MainWindow(&self, *g_cthrd); g_mwin = self.window; init_theme(); @@ -84,6 +96,7 @@ void Application::onStartup(Application& self) { { "help.report_bug", G_ACTION_CALLBACK(onReportBug), NULL, NULL, NULL, {0,0,0}}, { "tools.transmission", G_ACTION_CALLBACK(onToolsTransmission), NULL, NULL, NULL, {0,0,0}}, { "tools.shared_management", G_ACTION_CALLBACK(onToolsSharedManagement), NULL, NULL, NULL, {0,0,0}}, + { "trans_model_changed" }, }; g_action_map_add_action_entries (G_ACTION_MAP (self.app), diff --git a/src/iptux/Application.h b/src/iptux/Application.h index 94b9c93a1..75f449e25 100644 --- a/src/iptux/Application.h +++ b/src/iptux/Application.h @@ -5,11 +5,13 @@ #include "iptux-core/IptuxConfig.h" #include "iptux/UiProgramData.h" -#include "MainWindow.h" +#include "iptux/UiCoreThread.h" #include "ShareFile.h" namespace iptux { +class MainWindow; + class Application { public: explicit Application(std::shared_ptr config); @@ -17,15 +19,26 @@ class Application { int run(int argc, char** argv); + GtkApplication* getApp() {return app;} + std::shared_ptr getConfig() { return config; } + TransModel* getTransModel() { return transModel; } + private: std::shared_ptr config; std::shared_ptr data; + std::shared_ptr cthrd; GtkApplication* app; MainWindow* window; ShareFile* shareFile; + TransModel* transModel; bool started {false}; +public: + // for test + void startup(); + void activate(); + private: static void onStartup (Application& self); static void onActivate (Application& self); diff --git a/src/iptux/ApplicationTest.cpp b/src/iptux/ApplicationTest.cpp index 28eea0b5e..3c83a2321 100644 --- a/src/iptux/ApplicationTest.cpp +++ b/src/iptux/ApplicationTest.cpp @@ -10,4 +10,6 @@ TEST(Application, Constructor) { gtk_init(nullptr, nullptr); auto config = newTestIptuxConfig(); Application app(config); + app.startup(); + app.activate(); } diff --git a/src/iptux/MainWindow.cpp b/src/iptux/MainWindow.cpp index df1653854..91c9133ea 100644 --- a/src/iptux/MainWindow.cpp +++ b/src/iptux/MainWindow.cpp @@ -45,7 +45,7 @@ static gchar* palInfo2HintMarkup(const PalInfo *pal); /** * 类构造函数. */ -MainWindow::MainWindow(GtkApplication* app, UiCoreThread& coreThread) +MainWindow::MainWindow(Application* app, UiCoreThread& coreThread) : app(app), coreThread(coreThread), window(nullptr), @@ -93,8 +93,7 @@ void MainWindow::CreateWindow() { /* 创建主窗口 */ window = CreateMainWindow(); g_object_set_data(G_OBJECT(window), "iptux-config", &config); - g_object_set_data_full(G_OBJECT(window), "trans-model", transModelNew(), - GDestroyNotify(g_object_unref)); + g_object_set_data(G_OBJECT(window), "trans-model", app->getTransModel()); gtk_container_add(GTK_CONTAINER(window), CreateAllArea()); gtk_widget_show_all(window); @@ -109,12 +108,11 @@ void MainWindow::CreateWindow() { { "about", G_ACTION_CALLBACK(onAbout)}, { "clear_chat_history", G_ACTION_CALLBACK(onClearChatHistory)}, { "insert_picture", G_ACTION_CALLBACK(onInsertPicture)}, - { "trans_model_changed"}, }; - add_accelerator(app, "win.refresh", "F5"); - add_accelerator(app, "win.detect", "D"); - add_accelerator(app, "win.find", "F"); + add_accelerator(app->getApp(), "win.refresh", "F5"); + add_accelerator(app->getApp(), "win.detect", "D"); + add_accelerator(app->getApp(), "win.find", "F"); g_action_map_add_action_entries (G_ACTION_MAP (window), win_entries, G_N_ELEMENTS (win_entries), @@ -414,7 +412,7 @@ void MainWindow::MakeItemBlinking(GroupInfo *grpinf, bool blinking) { */ void MainWindow::OpenTransWindow() { if(transWindow == nullptr) { - transWindow = GTK_WIDGET(trans_window_new(GTK_WINDOW(window))); + transWindow = GTK_WIDGET(trans_window_new(app, GTK_WINDOW(window))); gtk_widget_show_all(transWindow); gtk_widget_hide(transWindow); g_signal_connect_swapped(transWindow, "delete-event", G_CALLBACK(onTransWindowDelete), this); @@ -448,7 +446,7 @@ void MainWindow::UpdateItemToTransTree(const TransFileModel& para) { /* 重设数据 */ transModelFillFromTransFileModel(model, &iter, para); g_action_group_activate_action( - G_ACTION_GROUP(window), + G_ACTION_GROUP(app->getApp()), "trans_model_changed", nullptr ); @@ -540,7 +538,7 @@ GtkWidget *MainWindow::CreateMainWindow() { GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE | /*GDK_HINT_RESIZE_INC |*/ GDK_HINT_WIN_GRAVITY | GDK_HINT_USER_POS | GDK_HINT_USER_SIZE); - window = gtk_application_window_new(app); + window = gtk_application_window_new(app->getApp()); gtk_window_set_icon_name(GTK_WINDOW(window), "iptux"); if(config->GetString("bind_ip").empty()) { gtk_window_set_title(GTK_WINDOW(window), _("iptux")); diff --git a/src/iptux/MainWindow.h b/src/iptux/MainWindow.h index e2dcd3d6e..8069fbb00 100644 --- a/src/iptux/MainWindow.h +++ b/src/iptux/MainWindow.h @@ -13,12 +13,14 @@ #define IPTUX_MAINWINDOW_H #include "iptux-core/IptuxConfig.h" +#include "iptux-core/Models.h" +#include "iptux-core/Event.h" + #include "iptux/UiProgramData.h" #include "iptux/WindowConfig.h" -#include "iptux-core/Models.h" #include "iptux/UiModels.h" -#include "iptux-core/Event.h" #include "iptux/UiCoreThread.h" +#include "iptux/Application.h" namespace iptux { @@ -38,7 +40,7 @@ enum class ActiveWindowType { */ class MainWindow { public: - MainWindow(GtkApplication* app, UiCoreThread& coreThread); + MainWindow(Application* app, UiCoreThread& coreThread); ~MainWindow(); GtkWidget* getWindow(); @@ -69,7 +71,7 @@ class MainWindow { void processEvent(std::shared_ptr event); private: - GtkApplication* app; + Application* app; UiCoreThread& coreThread; GtkWidget* window; GtkWidget* transWindow; diff --git a/src/iptux/TransWindow.cpp b/src/iptux/TransWindow.cpp index d55badf42..597fc4d9e 100644 --- a/src/iptux/TransWindow.cpp +++ b/src/iptux/TransWindow.cpp @@ -20,6 +20,7 @@ namespace iptux { class TransWindowPrivate { public: + Application* app; GtkWidget* transTreeviewWidget; public: @@ -38,18 +39,18 @@ static gboolean UpdateTransUI(GtkWindow *window); static TransWindowPrivate& getPriv(TransWindow* window); static shared_ptr trans_window_get_config(GtkWindow *pWindow); -TransWindow *trans_window_new(GtkWindow *parent) { - g_assert(g_object_get_data(G_OBJECT(parent), "iptux-config") != nullptr); - g_assert(g_object_get_data(G_OBJECT(parent), "trans-model") != nullptr); - g_assert(g_action_map_lookup_action(G_ACTION_MAP(parent), "trans_model_changed") != nullptr); - +TransWindow *trans_window_new(Application* app, GtkWindow *parent) { + g_assert(app != nullptr); GtkWindow *window; window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); TransWindowPrivate* priv = new TransWindowPrivate; + priv->app = app; g_object_set_data_full(G_OBJECT(window), IPTUX_PRIVATE, priv, GDestroyNotify(TransWindowPrivate::destroy)); - gtk_window_set_transient_for(window, parent); - gtk_window_set_destroy_with_parent(window, true); + if(parent) { + gtk_window_set_transient_for(window, parent); + gtk_window_set_destroy_with_parent(window, true); + } auto config = trans_window_get_config(window); gtk_window_set_title(GTK_WINDOW(window), _("Files Transmission Management")); @@ -63,7 +64,7 @@ TransWindow *trans_window_new(GtkWindow *parent) { g_signal_connect(window, "delete-event", G_CALLBACK(gtk_widget_hide), NULL); g_signal_connect(window, "configure-event", G_CALLBACK(TWinConfigureEvent), NULL); g_signal_connect_swapped( - g_action_map_lookup_action(G_ACTION_MAP(parent), "trans_model_changed"), + g_action_map_lookup_action(G_ACTION_MAP(app->getApp()), "trans_model_changed"), "activate", G_CALLBACK(UpdateTransUI), window @@ -90,13 +91,11 @@ gboolean TWinConfigureEvent(GtkWindow *window) { } shared_ptr trans_window_get_config(GtkWindow *window) { - GtkWindow* parent = gtk_window_get_transient_for(window); - return *(static_cast *>(g_object_get_data(G_OBJECT(parent), "iptux-config"))); + return getPriv(window).app->getConfig(); } -GtkTreeModel* trans_window_get_trans_model(GtkWindow* window) { - GtkWindow* parent = gtk_window_get_transient_for(window); - return GTK_TREE_MODEL(g_object_get_data(G_OBJECT(parent), "trans-model")); +TransModel* trans_window_get_trans_model(GtkWindow* window) { + return getPriv(window).app->getTransModel(); } diff --git a/src/iptux/TransWindow.h b/src/iptux/TransWindow.h index 17cfe5713..1015f33e0 100644 --- a/src/iptux/TransWindow.h +++ b/src/iptux/TransWindow.h @@ -3,10 +3,12 @@ #include +#include "iptux/Application.h" + namespace iptux { typedef GtkWindow TransWindow; -TransWindow* trans_window_new(GtkWindow* parent); +TransWindow* trans_window_new(Application* app, GtkWindow* parent); } diff --git a/src/iptux/TransWindowTest.cpp b/src/iptux/TransWindowTest.cpp new file mode 100644 index 000000000..518aac092 --- /dev/null +++ b/src/iptux/TransWindowTest.cpp @@ -0,0 +1,18 @@ +#include "gtest/gtest.h" + +#include "iptux/TransWindow.h" +#include "iptux-core/TestHelper.h" + +using namespace std; +using namespace iptux; + +TEST(TransWindow, Constructor) { + gtk_init(nullptr, nullptr); + auto config = newTestIptuxConfig(); + Application app(config); + app.startup(); + app.activate(); + + TransWindow* transWindow = trans_window_new(&app, nullptr); + gtk_widget_destroy(GTK_WIDGET(transWindow)); +} diff --git a/src/iptux/UiModels.cpp b/src/iptux/UiModels.cpp index 734f8fd63..d77079a8b 100644 --- a/src/iptux/UiModels.cpp +++ b/src/iptux/UiModels.cpp @@ -36,6 +36,10 @@ TransModel* transModelNew() { return GTK_TREE_MODEL(model); } +void transModelDelete(TransModel* model) { + g_object_unref(model); +} + void transModelFillFromTransFileModel(TransModel* model, GtkTreeIter* iter, const TransFileModel& para) { gtk_list_store_set( GTK_LIST_STORE(model), iter, diff --git a/src/iptux/UiModels.h b/src/iptux/UiModels.h index 1e0c9a676..81c926ce1 100644 --- a/src/iptux/UiModels.h +++ b/src/iptux/UiModels.h @@ -34,6 +34,7 @@ enum class TransModelColumn { }; typedef GtkTreeModel TransModel; TransModel* transModelNew(); +void transModelDelete(TransModel*); void transModelFillFromTransFileModel(TransModel* model, GtkTreeIter* iter, const TransFileModel&); enum class PalTreeModelSortKey { diff --git a/src/iptux/meson.build b/src/iptux/meson.build index 3d6bb1685..24e052ffa 100644 --- a/src/iptux/meson.build +++ b/src/iptux/meson.build @@ -83,6 +83,7 @@ test_sources = files([ 'ApplicationTest.cpp', 'LogSystemTest.cpp', 'TestMain.cpp', + 'TransWindowTest.cpp', 'UiCoreThreadTest.cpp', 'UiProgramDataTest.cpp', ])