diff --git a/src/iptux/AboutDialog.cpp b/src/iptux/AboutDialog.cpp index 256a4e65..75ae7b1e 100644 --- a/src/iptux/AboutDialog.cpp +++ b/src/iptux/AboutDialog.cpp @@ -73,8 +73,12 @@ AboutDialog* aboutDialogNew() { void aboutDialogRun(AboutDialog* aboutDialog, GtkWindow* parent) { gtk_window_set_transient_for(GTK_WINDOW(aboutDialog), parent); - gtk_dialog_run(GTK_DIALOG(aboutDialog)); - gtk_widget_hide(GTK_WIDGET(aboutDialog)); + g_signal_connect(aboutDialog, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint, gpointer) { + gtk_widget_hide(GTK_WIDGET(dialog)); + }), + NULL); + gtk_widget_show(GTK_WIDGET(aboutDialog)); } void aboutDialogEntry(GtkWindow* parent) { diff --git a/src/iptux/DataSettings.cpp b/src/iptux/DataSettings.cpp index 5b4b00b9..783fdf17 100644 --- a/src/iptux/DataSettings.cpp +++ b/src/iptux/DataSettings.cpp @@ -88,38 +88,48 @@ void DataSettings::ResetDataEntry(Application* app, GtkWidget* parent) { return; } - DataSettings dset(app, parent); - GtkWidget* dialog = GTK_WIDGET(dset.dialog()); + DataSettings* dset = new DataSettings(app, parent); + GtkWidget* dialog = GTK_WIDGET(dset->dialog()); app->setPreferenceDialog(dialog); + g_signal_connect( + dialog, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint response_id, gpointer user_data) { + DataSettings* dset = static_cast(user_data); + Application* app = dset->app; + + switch (response_id) { + case GTK_RESPONSE_OK: + if (dset->Save()) { + if (app->getProgramData()->need_restart()) { + pop_warning(GTK_WIDGET(dialog), + _("The program needs to be restarted to take effect!")); + } + app->setPreferenceDialog(NULL); + gtk_widget_destroy(GTK_WIDGET(dialog)); + delete dset; + } + break; + case GTK_RESPONSE_APPLY: + if (dset->Save()) { + if (app->getProgramData()->need_restart()) { + pop_warning(GTK_WIDGET(dialog), + _("The program needs to be restarted to take effect!")); + } + } + // Keep dialog open + break; + default: + app->setPreferenceDialog(NULL); + gtk_widget_destroy(GTK_WIDGET(dialog)); + delete dset; + break; + } + }), + dset); + /* 运行对话框 */ gtk_widget_show_all(dialog); - bool done = false; - while (!done) { - switch (gtk_dialog_run(GTK_DIALOG(dialog))) { - case GTK_RESPONSE_OK: - if (dset.Save()) { - if (app->getProgramData()->need_restart()) { - pop_warning(dialog, - _("The program needs to be restarted to take effect!")); - } - done = true; - } - break; - case GTK_RESPONSE_APPLY: - if (dset.Save()) { - if (app->getProgramData()->need_restart()) { - pop_warning(dialog, - _("The program needs to be restarted to take effect!")); - } - } - break; - default: - done = true; - break; - } - } - app->setPreferenceDialog(NULL); } /** @@ -1194,21 +1204,21 @@ gint DataSettings::IconfileGetItemPos(GtkTreeModel* model, * @param widset widget set */ void DataSettings::AddNewIcon(GtkWidget* button, GData** widset) { - GtkWidget *parent, *combo; - GtkTreeModel* model; - gchar* filename; - gint active; - - parent = GTK_WIDGET(g_datalist_get_data(widset, "dialog-widget")); - if (!(filename = choose_file_with_preview(_("Please select a face picture"), - parent))) - return; + GtkWidget* parent = GTK_WIDGET(g_datalist_get_data(widset, "dialog-widget")); + + choose_file_with_preview_async( + _("Please select a face picture"), parent, [widset, button](gchar* filename) { + if (!filename) { + return; + } - combo = GTK_WIDGET(g_object_get_data(G_OBJECT(button), "icon-combo-widget")); - model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); - active = IconfileGetItemPos(model, filename); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), active); - g_free(filename); + GtkWidget* combo = GTK_WIDGET( + g_object_get_data(G_OBJECT(button), "icon-combo-widget")); + GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); + gint active = IconfileGetItemPos(model, filename); + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), active); + g_free(filename); + }); } /** @@ -1216,28 +1226,30 @@ void DataSettings::AddNewIcon(GtkWidget* button, GData** widset) { * @param widset widget set */ void DataSettings::ChoosePhoto(GData** widset) { - GtkWidget *image, *parent; - GdkPixbuf* pixbuf; - gchar path[MAX_PATHLEN]; - gchar* filename; - - parent = GTK_WIDGET(g_datalist_get_data(widset, "dialog-widget")); - if (!(filename = choose_file_with_preview(_("Please select a personal photo"), - parent))) - return; + GtkWidget* parent = GTK_WIDGET(g_datalist_get_data(widset, "dialog-widget")); + + choose_file_with_preview_async( + _("Please select a personal photo"), parent, [widset](gchar* filename) { + if (!filename) { + return; + } - if ((pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) { - snprintf(path, MAX_PATHLEN, "%s" PHOTO_PATH "/photo", - g_get_user_config_dir()); - pixbuf_shrink_scale_1(&pixbuf, MAX_PHOTOSIZE, MAX_PHOTOSIZE); - gdk_pixbuf_save(pixbuf, path, "bmp", NULL, - NULL); // 命中率极高,不妨直接保存 - image = GTK_WIDGET(g_datalist_get_data(widset, "photo-image-widget")); - pixbuf_shrink_scale_1(&pixbuf, MAX_PREVIEWSIZE, MAX_PREVIEWSIZE); - gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf); - g_object_unref(pixbuf); - } - g_free(filename); + GdkPixbuf* pixbuf; + if ((pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) { + gchar path[MAX_PATHLEN]; + snprintf(path, MAX_PATHLEN, "%s" PHOTO_PATH "/photo", + g_get_user_config_dir()); + pixbuf_shrink_scale_1(&pixbuf, MAX_PHOTOSIZE, MAX_PHOTOSIZE); + gdk_pixbuf_save(pixbuf, path, "bmp", NULL, + NULL); // 命中率极高,不妨直接保存 + GtkWidget* image = + GTK_WIDGET(g_datalist_get_data(widset, "photo-image-widget")); + pixbuf_shrink_scale_1(&pixbuf, MAX_PREVIEWSIZE, MAX_PREVIEWSIZE); + gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf); + g_object_unref(pixbuf); + } + g_free(filename); + }); } /** @@ -1388,11 +1400,6 @@ void DataSettings::CellEditText(GtkCellRendererText* renderer, */ void DataSettings::ImportNetSegment(DataSettings* dset) { GtkWidget *dialog, *parent; - GtkTreeModel* model; - GtkTreeIter iter; - gchar* filename; - GSList *list, *tlist; - NetSegment* pns; parent = GTK_WIDGET(g_datalist_get_data(&dset->widset, "dialog-widget")); dialog = gtk_file_chooser_dialog_new( @@ -1403,31 +1410,37 @@ void DataSettings::ImportNetSegment(DataSettings* dset) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), g_get_home_dir()); - switch (gtk_dialog_run(GTK_DIALOG(dialog))) { - case GTK_RESPONSE_ACCEPT: - model = - GTK_TREE_MODEL(g_datalist_get_data(&dset->mdlset, "network-model")); - gtk_list_store_clear(GTK_LIST_STORE(model)); - list = NULL; - filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - dset->ReadNetSegment(filename, &list); - g_free(filename); - tlist = list; - while (tlist) { - pns = (NetSegment*)tlist->data; - gtk_list_store_append(GTK_LIST_STORE(model), &iter); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, - pns->startip.c_str(), 1, pns->endip.c_str(), 2, - pns->description.c_str(), -1); - tlist = g_slist_next(tlist); - } - for (tlist = list; tlist; tlist = g_slist_next(tlist)) - delete (NetSegment*)tlist->data; - g_slist_free(list); - default: - break; - } - gtk_widget_destroy(dialog); + g_signal_connect_data( + dialog, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint response_id, gpointer user_data) { + DataSettings* dset = static_cast(user_data); + if (response_id == GTK_RESPONSE_ACCEPT) { + GtkTreeModel* model = GTK_TREE_MODEL( + g_datalist_get_data(&dset->mdlset, "network-model")); + gtk_list_store_clear(GTK_LIST_STORE(model)); + GSList* list = NULL; + gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + dset->ReadNetSegment(filename, &list); + g_free(filename); + GSList* tlist = list; + while (tlist) { + NetSegment* pns = (NetSegment*)tlist->data; + GtkTreeIter iter; + gtk_list_store_append(GTK_LIST_STORE(model), &iter); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, + pns->startip.c_str(), 1, pns->endip.c_str(), 2, + pns->description.c_str(), -1); + tlist = g_slist_next(tlist); + } + for (tlist = list; tlist; tlist = g_slist_next(tlist)) + delete (NetSegment*)tlist->data; + g_slist_free(list); + } + gtk_widget_destroy(GTK_WIDGET(dialog)); + }), + dset, nullptr, G_CONNECT_AFTER); + + gtk_widget_show(dialog); } /** @@ -1436,11 +1449,6 @@ void DataSettings::ImportNetSegment(DataSettings* dset) { */ void DataSettings::ExportNetSegment(DataSettings* dset) { GtkWidget *dialog, *parent; - GtkTreeModel* model; - GtkTreeIter iter; - gchar* filename; - GSList *list, *tlist; - NetSegment* ns; parent = GTK_WIDGET(g_datalist_get_data(&dset->widset, "dialog-widget")); dialog = gtk_file_chooser_dialog_new( @@ -1450,38 +1458,42 @@ void DataSettings::ExportNetSegment(DataSettings* dset) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), g_get_home_dir()); - switch (gtk_dialog_run(GTK_DIALOG(dialog))) { - case GTK_RESPONSE_ACCEPT: - model = - GTK_TREE_MODEL(g_datalist_get_data(&dset->mdlset, "network-model")); - if (!gtk_tree_model_get_iter_first(model, &iter)) - break; - list = NULL; - do { - char* startip; - char* endip; - char* description; - gtk_tree_model_get(model, &iter, 0, &startip, 1, &endip, 2, - &description, -1); - ns = new NetSegment; - if (startip) - ns->startip = startip; - if (endip) - ns->endip = endip; - if (description) - ns->description = description; - list = g_slist_append(list, ns); - } while (gtk_tree_model_iter_next(model, &iter)); - filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - dset->WriteNetSegment(filename, list); - g_free(filename); - for (tlist = list; tlist; tlist = g_slist_next(tlist)) - delete (NetSegment*)tlist->data; - g_slist_free(list); - default: - break; - } - gtk_widget_destroy(dialog); + g_signal_connect_data( + dialog, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint response_id, gpointer user_data) { + DataSettings* dset = static_cast(user_data); + if (response_id == GTK_RESPONSE_ACCEPT) { + GtkTreeModel* model = GTK_TREE_MODEL( + g_datalist_get_data(&dset->mdlset, "network-model")); + GtkTreeIter iter; + if (gtk_tree_model_get_iter_first(model, &iter)) { + GSList* list = NULL; + do { + char *startip, *endip, *description; + gtk_tree_model_get(model, &iter, 0, &startip, 1, &endip, 2, + &description, -1); + NetSegment* ns = new NetSegment; + if (startip) + ns->startip = startip; + if (endip) + ns->endip = endip; + if (description) + ns->description = description; + list = g_slist_append(list, ns); + } while (gtk_tree_model_iter_next(model, &iter)); + gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + dset->WriteNetSegment(filename, list); + g_free(filename); + for (GSList* tlist = list; tlist; tlist = g_slist_next(tlist)) + delete (NetSegment*)tlist->data; + g_slist_free(list); + } + } + gtk_widget_destroy(GTK_WIDGET(dialog)); + }), + dset, nullptr, G_CONNECT_AFTER); + + gtk_widget_show(dialog); } /** diff --git a/src/iptux/DialogBase.cpp b/src/iptux/DialogBase.cpp index dc15c844..29a08a80 100644 --- a/src/iptux/DialogBase.cpp +++ b/src/iptux/DialogBase.cpp @@ -333,49 +333,6 @@ GtkWidget* DialogBase::CreateHistoryArea() { return frame; } -/** - * 选择附件. - * @param fileattr 文件类型 - * @return 文件链表 - */ -GSList* DialogBase::PickEnclosure(FileAttr fileattr) { - GtkWidget* dialog; - GtkFileChooserAction action; - const char* title; - GSList* list; - - if (fileattr == FileAttr::REGULAR) { - action = GTK_FILE_CHOOSER_ACTION_OPEN; - title = _("Choose enclosure files"); - } else if (fileattr == FileAttr::DIRECTORY) { - action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - title = _("Choose enclosure folders"); - } else { - g_assert(false); - } - dialog = gtk_file_chooser_dialog_new(title, GTK_WINDOW(getWindow()), action, - _("_Open"), GTK_RESPONSE_ACCEPT, - _("_Cancel"), GTK_RESPONSE_CANCEL, NULL); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), FALSE); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), - g_get_home_dir()); - - switch (gtk_dialog_run(GTK_DIALOG(dialog))) { - case GTK_RESPONSE_ACCEPT: - list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - break; - case GTK_RESPONSE_CANCEL: - default: - list = NULL; - break; - } - gtk_widget_destroy(dialog); - - return list; -} - /** * 发送附件消息. * @return 是否发送数据 @@ -427,13 +384,13 @@ void DialogBase::FeedbackMsg(const gchar* msg) { * @param dlgpr 对话框类 */ void DialogBase::AttachRegular(DialogBase* dlgpr) { - GSList* list; - - if (!(list = dlgpr->PickEnclosure(FileAttr::REGULAR))) - return; - dlgpr->AttachEnclosure(list); - g_slist_foreach(list, GFunc(g_free), NULL); - g_slist_free(list); + dlgpr->PickEnclosureAsync(FileAttr::REGULAR, [dlgpr](GSList* list) { + if (!list) + return; + dlgpr->AttachEnclosure(list); + g_slist_foreach(list, GFunc(g_free), NULL); + g_slist_free(list); + }); } /** @@ -441,13 +398,13 @@ void DialogBase::AttachRegular(DialogBase* dlgpr) { * @param dlgpr 对话框类 */ void DialogBase::AttachFolder(DialogBase* dlgpr) { - GSList* list; - - if (!(list = dlgpr->PickEnclosure(FileAttr::DIRECTORY))) - return; - dlgpr->AttachEnclosure(list); - g_slist_foreach(list, GFunc(g_free), NULL); - g_slist_free(list); + dlgpr->PickEnclosureAsync(FileAttr::DIRECTORY, [dlgpr](GSList* list) { + if (!list) + return; + dlgpr->AttachEnclosure(list); + g_slist_foreach(list, GFunc(g_free), NULL); + g_slist_free(list); + }); } /** @@ -929,25 +886,34 @@ void DialogBase::OnSaveImage(DialogBase* self) { TRUE); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "image.png"); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char* save_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - - GError* error = NULL; - GFile* source = g_file_new_for_path(path); - GFile* destination = g_file_new_for_path(save_path); - gboolean success = g_file_copy(source, destination, G_FILE_COPY_OVERWRITE, - NULL, NULL, NULL, &error); - if (!success) { - LOG_ERROR("Failed to save image: %s", error->message); - g_error_free(error); - } - - g_object_unref(source); - g_object_unref(destination); - g_free(save_path); - } - - gtk_widget_destroy(dialog); + gchar* source_path = g_strdup(path); + g_signal_connect_data( + dialog, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint response_id, gpointer user_data) { + gchar* source_path = static_cast(user_data); + if (response_id == GTK_RESPONSE_ACCEPT) { + char* save_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + GError* error = NULL; + GFile* source = g_file_new_for_path(source_path); + GFile* destination = g_file_new_for_path(save_path); + gboolean success = g_file_copy(source, destination, G_FILE_COPY_OVERWRITE, + NULL, NULL, NULL, &error); + if (!success) { + LOG_ERROR("Failed to save image: %s", error->message); + g_error_free(error); + } + + g_object_unref(source); + g_object_unref(destination); + g_free(save_path); + } + g_free(source_path); + gtk_widget_destroy(GTK_WIDGET(dialog)); + }), + source_path, nullptr, G_CONNECT_AFTER); + + gtk_widget_show(dialog); } void DialogBase::OnCopyImage(DialogBase* self) { diff --git a/src/iptux/DialogBase.h b/src/iptux/DialogBase.h index e6a45142..ac71c8ab 100644 --- a/src/iptux/DialogBase.h +++ b/src/iptux/DialogBase.h @@ -15,6 +15,7 @@ #ifndef IPTUX_DIALOGBASE_H #define IPTUX_DIALOGBASE_H +#include #include #include "iptux-core/Models.h" @@ -52,7 +53,8 @@ class DialogBase : public SessionAbstract, public sigc::trackable { void MainWindowSignalSetup(GtkWindow* window); GtkTreeModel* CreateFileSendModel(); - GSList* PickEnclosure(FileAttr fileattr); + void PickEnclosureAsync(FileAttr fileattr, + std::function callback); GtkTextBuffer* getInputBuffer(); bool SendEnclosureMsg(); diff --git a/src/iptux/DialogPeer.cpp b/src/iptux/DialogPeer.cpp index 95ff247a..a3d4a203 100644 --- a/src/iptux/DialogPeer.cpp +++ b/src/iptux/DialogPeer.cpp @@ -447,34 +447,34 @@ void DialogPeer::onPaste(void*, void*, DialogPeer* self) { } void DialogPeer::insertImage() { - GtkWidget* widget; - GtkTextBuffer* buffer; - GtkTextIter iter; - GdkPixbuf* pixbuf; - gchar* filename; - gint position; - GError* error = nullptr; - - if (!(filename = choose_file_with_preview( - _("Please select a picture to insert the buffer"), - GTK_WIDGET(window)))) - return; - - if (!(pixbuf = gdk_pixbuf_new_from_file(filename, &error))) { - LOG_WARN("failed to load image: %s", error->message); - g_error_free(error); - error = nullptr; - g_free(filename); - return; - } - g_free(filename); - - widget = GTK_WIDGET(g_datalist_get_data(&widset, "input-textview-widget")); - buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); - g_object_get(buffer, "cursor-position", &position, NULL); - gtk_text_buffer_get_iter_at_offset(buffer, &iter, position); - gtk_text_buffer_insert_pixbuf(buffer, &iter, pixbuf); - g_object_unref(pixbuf); + choose_file_with_preview_async( + _("Please select a picture to insert the buffer"), + GTK_WIDGET(window), [this](gchar* filename) { + if (!filename) { + return; + } + + GdkPixbuf* pixbuf; + GError* error = nullptr; + if (!(pixbuf = gdk_pixbuf_new_from_file(filename, &error))) { + LOG_WARN("failed to load image: %s", error->message); + g_error_free(error); + g_free(filename); + return; + } + g_free(filename); + + GtkWidget* widget = GTK_WIDGET( + g_datalist_get_data(&widset, "input-textview-widget")); + GtkTextBuffer* buffer = + gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); + gint position; + g_object_get(buffer, "cursor-position", &position, NULL); + GtkTextIter iter; + gtk_text_buffer_get_iter_at_offset(buffer, &iter, position); + gtk_text_buffer_insert_pixbuf(buffer, &iter, pixbuf); + g_object_unref(pixbuf); + }); } void DialogPeer::populateInputPopup(GtkMenu* popup) { diff --git a/src/iptux/RevisePal.cpp b/src/iptux/RevisePal.cpp index 2b61e920..4548c6d0 100644 --- a/src/iptux/RevisePal.cpp +++ b/src/iptux/RevisePal.cpp @@ -403,21 +403,21 @@ gint RevisePal::IconfileGetItemPos(GtkTreeModel* model, const char* pathname) { * @param widset widget set */ void RevisePal::AddNewIcon(GtkWidget* button, GData** widset) { - GtkWidget *parent, *combo; - GtkTreeModel* model; - gchar* filename; - gint active; - - parent = GTK_WIDGET(g_datalist_get_data(widset, "dialog-widget")); - if (!(filename = choose_file_with_preview(_("Please select a face picture"), - parent))) - return; - - combo = GTK_WIDGET(g_object_get_data(G_OBJECT(button), "icon-combo-widget")); - model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); - active = IconfileGetItemPos(model, filename); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), active); - g_free(filename); + GtkWidget* parent = GTK_WIDGET(g_datalist_get_data(widset, "dialog-widget")); + + choose_file_with_preview_async( + _("Please select a face picture"), parent, [widset, button](gchar* filename) { + if (!filename) { + return; + } + + GtkWidget* combo = + GTK_WIDGET(g_object_get_data(G_OBJECT(button), "icon-combo-widget")); + GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); + gint active = IconfileGetItemPos(model, filename); + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), active); + g_free(filename); + }); } } // namespace iptux diff --git a/src/iptux/ShareFile.cpp b/src/iptux/ShareFile.cpp index 359f2070..dae4e202 100644 --- a/src/iptux/ShareFile.cpp +++ b/src/iptux/ShareFile.cpp @@ -12,6 +12,7 @@ #include "config.h" #include "ShareFile.h" +#include #include #include @@ -64,18 +65,30 @@ ShareFilePrivate* getPriv(ShareFile* window) { void shareFileRun(ShareFile* dialog, GtkWindow* parent) { gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - switch (gtk_dialog_run(GTK_DIALOG(dialog))) { - case GTK_RESPONSE_OK: - ApplySharedData(dialog); - break; - case GTK_RESPONSE_APPLY: - ApplySharedData(dialog); - shareFileRun(dialog, parent); - break; - default: - break; - } - gtk_widget_hide(GTK_WIDGET(dialog)); + + g_signal_connect( + dialog, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint response_id, gpointer user_data) { + ShareFile* self = IPTUX_SHARE_FILE(dialog); + GtkWindow* parent = GTK_WINDOW(user_data); + + switch (response_id) { + case GTK_RESPONSE_OK: + ApplySharedData(self); + gtk_widget_hide(GTK_WIDGET(dialog)); + break; + case GTK_RESPONSE_APPLY: + ApplySharedData(self); + // Keep dialog open for another round + return; + default: + gtk_widget_hide(GTK_WIDGET(dialog)); + break; + } + }), + parent); + + gtk_widget_show(GTK_WIDGET(dialog)); } /** @@ -395,13 +408,13 @@ void AttachSharedFiles(ShareFile* self, GSList* list) { /** * 选择新的共享文件. * @param fileattr 文件类型 - * @return 文件链表 + * @param callback callback function to handle the selected files */ -GSList* PickSharedFile(ShareFile* self, FileAttr fileattr) { +void PickSharedFileAsync(ShareFile* self, FileAttr fileattr, + std::function callback) { GtkWidget* dialog; GtkFileChooserAction action; const char* title; - GSList* list; g_assert(FileAttrIsValid(fileattr)); @@ -422,18 +435,27 @@ GSList* PickSharedFile(ShareFile* self, FileAttr fileattr) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), g_get_home_dir()); - switch (gtk_dialog_run(GTK_DIALOG(dialog))) { - case GTK_RESPONSE_ACCEPT: - list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - break; - case GTK_RESPONSE_CANCEL: - default: - list = NULL; - break; - } - gtk_widget_destroy(dialog); - - return list; + struct CallbackData { + std::function callback; + }; + + auto* data = new CallbackData{callback}; + + g_signal_connect_data( + dialog, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint response_id, gpointer user_data) { + auto* data = static_cast(user_data); + GSList* list = nullptr; + if (response_id == GTK_RESPONSE_ACCEPT) { + list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + } + data->callback(list); + gtk_widget_destroy(GTK_WIDGET(dialog)); + delete data; + }), + data, nullptr, G_CONNECT_AFTER); + + gtk_widget_show(dialog); } /** @@ -441,12 +463,11 @@ GSList* PickSharedFile(ShareFile* self, FileAttr fileattr) { * @param sfile 共享文件类 */ void AddRegular(ShareFile* sfile) { - GSList* list; - - list = PickSharedFile(sfile, FileAttr::REGULAR); - AttachSharedFiles(sfile, list); - g_slist_foreach(list, GFunc(g_free), NULL); - g_slist_free(list); + PickSharedFileAsync(sfile, FileAttr::REGULAR, [sfile](GSList* list) { + AttachSharedFiles(sfile, list); + g_slist_foreach(list, GFunc(g_free), NULL); + g_slist_free(list); + }); } /** @@ -454,12 +475,11 @@ void AddRegular(ShareFile* sfile) { * @param sfile 共享文件类 */ void AddFolder(ShareFile* sfile) { - GSList* list; - - list = PickSharedFile(sfile, FileAttr::DIRECTORY); - AttachSharedFiles(sfile, list); - g_slist_foreach(list, GFunc(g_free), NULL); - g_slist_free(list); + PickSharedFileAsync(sfile, FileAttr::DIRECTORY, [sfile](GSList* list) { + AttachSharedFiles(sfile, list); + g_slist_foreach(list, GFunc(g_free), NULL); + g_slist_free(list); + }); } /** diff --git a/src/iptux/TransWindow.cpp b/src/iptux/TransWindow.cpp index d6073ccf..b1b4ed61 100644 --- a/src/iptux/TransWindow.cpp +++ b/src/iptux/TransWindow.cpp @@ -330,8 +330,8 @@ void onOpenFolder(void*, void*, TransWindowPrivate* self) { NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", _("The path you want to open not exist!")); gtk_window_set_title(GTK_WINDOW(dialog), "Iptux Error"); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dialog); return; } iptux_open_url(filepath); @@ -404,8 +404,8 @@ void onOpenFile(void*, void*, TransWindowPrivate* self) { NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", _("The file you want to open not exist!")); gtk_window_set_title(GTK_WINDOW(dialog), _("iptux Error")); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dialog); return; } iptux_open_url(filename); diff --git a/src/iptux/UiHelper.cpp b/src/iptux/UiHelper.cpp index fbb341df..80d30be7 100644 --- a/src/iptux/UiHelper.cpp +++ b/src/iptux/UiHelper.cpp @@ -186,8 +186,8 @@ void pop_info(GtkWidget* parent, const gchar* format, ...) { gtk_message_dialog_set_markup(GTK_MESSAGE_DIALOG(dialog), msg); g_free(msg); gtk_window_set_title(GTK_WINDOW(dialog), _("Information")); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dialog); } /** @@ -216,8 +216,8 @@ void pop_warning(GtkWidget* parent, const gchar* format, ...) { gtk_message_dialog_set_markup(GTK_MESSAGE_DIALOG(dialog), msg); g_free(msg); gtk_window_set_title(GTK_WINDOW(dialog), _("Warning")); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dialog); } /** diff --git a/src/iptux/callback.cpp b/src/iptux/callback.cpp index 9c499e84..948ca6e0 100644 --- a/src/iptux/callback.cpp +++ b/src/iptux/callback.cpp @@ -12,6 +12,7 @@ #include "config.h" #include "callback.h" +#include #include #include @@ -76,11 +77,12 @@ void entry_insert_numeric(GtkWidget* entry, gchar* text, gint length) { * 以可预览的方式选择文件. * @param title file chooser dialog title * @param parent parent - * @return 文件名 + * @param callback callback function to handle the selected filename (or nullptr if cancelled) */ -gchar* choose_file_with_preview(const gchar* title, GtkWidget* parent) { +void choose_file_with_preview_async(const gchar* title, + GtkWidget* parent, + std::function callback) { GtkWidget *chooser, *preview; - gchar* filename; chooser = gtk_file_chooser_dialog_new( title, GTK_WINDOW(parent), GTK_FILE_CHOOSER_ACTION_OPEN, _("_Open"), @@ -100,18 +102,27 @@ gchar* choose_file_with_preview(const gchar* title, GtkWidget* parent) { g_signal_connect(chooser, "update-preview", G_CALLBACK(chooser_update_preview), preview); - gtk_widget_show_all(chooser); - filename = NULL; - switch (gtk_dialog_run(GTK_DIALOG(chooser))) { - case GTK_RESPONSE_ACCEPT: - filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser)); - break; - default: - break; - } - gtk_widget_destroy(chooser); + struct CallbackData { + std::function callback; + }; + + auto* data = new CallbackData{callback}; + + g_signal_connect_data( + chooser, "response", + G_CALLBACK(+[](GtkDialog* dialog, gint response_id, gpointer user_data) { + auto* data = static_cast(user_data); + gchar* filename = nullptr; + if (response_id == GTK_RESPONSE_ACCEPT) { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + } + data->callback(filename); + gtk_widget_destroy(GTK_WIDGET(dialog)); + delete data; + }), + data, nullptr, G_CONNECT_AFTER); - return filename; + gtk_widget_show_all(chooser); } /** diff --git a/src/iptux/callback.h b/src/iptux/callback.h index fdd6f11c..482c0401 100644 --- a/src/iptux/callback.h +++ b/src/iptux/callback.h @@ -12,6 +12,7 @@ #ifndef IPTUX_CALLBACK_H #define IPTUX_CALLBACK_H +#include #include #include "iptux-core/Models.h" @@ -28,7 +29,9 @@ gboolean entry_query_tooltip(GtkWidget* entry, void entry_insert_numeric(GtkWidget* entry, gchar* text, gint length); /* file-chooser */ -gchar* choose_file_with_preview(const gchar* title, GtkWidget* parent); +void choose_file_with_preview_async(const gchar* title, + GtkWidget* parent, + std::function callback); void chooser_update_preview(GtkFileChooser* chooser, GtkWidget* preview); /* model:0 G_TYPE_BOOLEAN */