void Gobby::TitleBar::on_document_changed(SessionView* view) { if(m_current_view != NULL) { InfSession* session = m_current_view->get_session(); InfBuffer* buffer = inf_session_get_buffer(session); g_signal_handler_disconnect(G_OBJECT(session), m_notify_status_handler); g_signal_handler_disconnect(G_OBJECT(buffer), m_modified_changed_handler); } m_current_view = view; if(view != NULL) { InfSession* session = view->get_session(); InfBuffer* buffer = inf_session_get_buffer(session); m_notify_status_handler = g_signal_connect( G_OBJECT(session), "notify::status", G_CALLBACK(on_notify_status_static), this); m_modified_changed_handler = g_signal_connect( G_OBJECT(buffer), "notify::modified", G_CALLBACK(on_notify_modified_static), this); } update_title(); }
static void infinoted_plugin_autosave_session_added(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginAutosaveSessionInfo* info; InfSession* session; InfBuffer* buffer; info = (InfinotedPluginAutosaveSessionInfo*)session_info; info->plugin = (InfinotedPluginAutosave*)plugin_info; info->iter = *iter; info->proxy = proxy; info->timeout = NULL; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); g_signal_connect( G_OBJECT(buffer), "notify::modified", G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); if(inf_buffer_get_modified(buffer) == TRUE) infinoted_plugin_autosave_start(info); g_object_unref(session); }
void Gobby::TitleBar::update_title() { // TODO: Show path, as gedit does. This requires change notification // for document info storage. if(m_current_view != NULL) { InfSession* session = m_current_view->get_session(); InfBuffer* buffer = inf_session_get_buffer(session); InfSessionStatus status = inf_session_get_status(session); if(status == INF_SESSION_SYNCHRONIZING || !inf_buffer_get_modified(buffer)) { m_window.set_title( m_current_view->get_title() + " - Gobby"); } else { m_window.set_title( "*" + m_current_view->get_title() + " - Gobby"); } } else { m_window.set_title("Gobby"); } }
static void infinoted_plugin_autosave_buffer_notify_modified_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfinotedPluginAutosaveSessionInfo* info; InfSession* session; InfBuffer* buffer; info = (InfinotedPluginAutosaveSessionInfo*)user_data; g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); if(inf_buffer_get_modified(buffer) == TRUE) { if(info->timeout == NULL) infinoted_plugin_autosave_start(info); } else { if(info->timeout != NULL) infinoted_plugin_autosave_stop(info); } g_object_unref(session); }
static void infinoted_plugin_autosave_session_removed(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginAutosaveSessionInfo* info; InfSession* session; InfBuffer* buffer; info = (InfinotedPluginAutosaveSessionInfo*)session_info; /* Cancel autosave timeout even if session is modified. If the directory * removed the session, then it has already saved it anyway. */ if(info->timeout != NULL) infinoted_plugin_autosave_stop(info); g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); g_object_unref(session); g_object_unref(info->proxy); }
static void infinoted_autosave_add_session(InfinotedAutosave* autosave, InfdDirectoryIter* iter) { InfinotedAutosaveSession* session; InfdSessionProxy* proxy; InfBuffer* buffer; g_assert(infinoted_autosave_find_session(autosave, iter) == NULL); session = g_slice_new(InfinotedAutosaveSession); session->autosave = autosave; session->iter = *iter; proxy = infd_directory_iter_peek_session(autosave->directory, iter); g_assert(proxy != NULL); session->proxy = proxy; session->timeout_handle = NULL; autosave->sessions = g_slist_prepend(autosave->sessions, session); buffer = inf_session_get_buffer(infd_session_proxy_get_session(proxy)); g_signal_connect( G_OBJECT(buffer), "notify::modified", G_CALLBACK(infinoted_autosave_buffer_notify_modified_cb), session ); if(inf_buffer_get_modified(buffer) == TRUE) { infinoted_autosave_session_start(autosave, session); } }
static void inf_adopted_session_create_algorithm(InfAdoptedSession* session) { InfAdoptedSessionPrivate* priv; priv = INF_ADOPTED_SESSION_PRIVATE(session); g_assert(priv->algorithm == NULL); g_assert( inf_session_get_status(INF_SESSION(session)) == INF_SESSION_RUNNING ); priv->algorithm = inf_adopted_algorithm_new_full( inf_session_get_user_table(INF_SESSION(session)), inf_session_get_buffer(INF_SESSION(session)), priv->max_total_log_size ); g_signal_connect( G_OBJECT(priv->algorithm), "execute-request", G_CALLBACK(inf_adopted_session_execute_request_cb), session ); g_object_notify(G_OBJECT(session), "algorithm"); }
static void infinoted_directory_sync_remove_session(InfinotedDirectorySync* dsync, InfinotedDirectorySyncSession* sess) { InfTextBuffer* buffer; if(sess->timeout != NULL) { infinoted_directory_sync_session_save(dsync, sess); infinoted_directory_sync_session_stop(dsync, sess); } buffer = INF_TEXT_BUFFER( inf_session_get_buffer(infd_session_proxy_get_session(sess->proxy)) ); inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_directory_sync_buffer_text_inserted_cb), sess ); inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_directory_sync_buffer_text_erased_cb), sess ); dsync->sessions = g_slist_remove(dsync->sessions, sess); g_free(sess->path); g_slice_free(InfinotedDirectorySyncSession, sess); }
virtual void deactivate() { DocInfo::deactivate(); InfTextGtkBuffer* buffer = INF_TEXT_GTK_BUFFER( inf_session_get_buffer(m_view.get_session())); inf_text_gtk_buffer_set_wake_on_cursor_movement( buffer, FALSE); }
static gboolean infinoted_plugin_note_chat_session_write(InfdStorage* storage, InfSession* session, const gchar* path, gpointer user_data, GError** error) { return infd_chat_filesystem_format_write( INFD_FILESYSTEM_STORAGE(storage), path, INF_CHAT_BUFFER(inf_session_get_buffer(session)), error ); }
Gobby::TextTabLabel::~TextTabLabel() { TextSessionView& text_view = dynamic_cast<TextSessionView&>(m_view); g_signal_handler_disconnect(text_view.get_text_buffer(), m_modified_changed_handle); InfTextBuffer* buffer = INF_TEXT_BUFFER( inf_session_get_buffer( INF_SESSION(m_view.get_session()))); g_signal_handler_disconnect(buffer, m_erase_text_handle); g_signal_handler_disconnect(buffer, m_insert_text_handle); }
void Gobby::TitleBar::on_document_changed(SessionView* view) { if(m_current_view != NULL) { InfSession* session = m_current_view->get_session(); InfBuffer* buffer = inf_session_get_buffer(session); g_signal_handler_disconnect(G_OBJECT(session), m_notify_status_handler); g_signal_handler_disconnect(G_OBJECT(buffer), m_notify_modified_handler); m_rename_handler.disconnect(); } m_current_view = view; if(view != NULL) { InfSession* session = view->get_session(); InfBuffer* buffer = inf_session_get_buffer(session); m_notify_status_handler = g_signal_connect( G_OBJECT(session), "notify::status", G_CALLBACK(on_notify_status_static), this); m_notify_modified_handler = g_signal_connect( G_OBJECT(buffer), "notify::modified", G_CALLBACK(on_notify_modified_static), this); // We are subscribing to the view's signal to avoid a race condition, // since we can't otherwise guarantee that the view's new name has already been set m_rename_handler = m_current_view->signal_session_name_changed().connect( sigc::mem_fun(*this, &TitleBar::on_session_name_changed)); } update_title(); }
static void inf_chat_test_subscribe_finished_cb(InfcNodeRequest* request, const InfcBrowserIter* iter, gpointer user_data) { InfTestChat* test; InfSession* session; test = (InfTestChat*)user_data; printf("Subscription successful, waiting for synchronization...\n"); session = infc_session_proxy_get_session( infc_browser_get_chat_session(test->browser)); test->buffer = INF_CHAT_BUFFER(inf_session_get_buffer(session)); /* TODO: Show backlog after during/after synchronization */ g_signal_connect_after( G_OBJECT(session), "receive-message", G_CALLBACK(inf_chat_test_buffer_receive_message_cb), test ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(inf_chat_test_session_synchronization_complete_cb), test ); g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(inf_chat_test_session_synchronization_failed_cb), test ); /* This can happen when the server disables the chat without being * shutdown. */ g_signal_connect_after( G_OBJECT(session), "close", G_CALLBACK(inf_chat_test_session_close_cb), test ); }
static void infinoted_plugin_linekeeper_session_added(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginLinekeeperSessionInfo* info; InfSession* session; InfUserTable* user_table; info = (InfinotedPluginLinekeeperSessionInfo*)session_info; info->plugin = (InfinotedPluginLinekeeper*)plugin_info; info->proxy = proxy; info->request = NULL; info->user = NULL; info->dispatch = NULL; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); g_assert(inf_session_get_status(session) == INF_SESSION_RUNNING); info->buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); g_object_ref(info->buffer); user_table = inf_session_get_user_table(session); g_signal_connect( G_OBJECT(user_table), "add-available-user", G_CALLBACK(infinoted_plugin_linekeeper_add_available_user_cb), info ); g_signal_connect( G_OBJECT(user_table), "remove-available-user", G_CALLBACK(infinoted_plugin_linekeeper_remove_available_user_cb), info ); /* Only join a user when there are other nonlocal users available, so that * we don't keep the session from going idle. */ if(infinoted_plugin_linekeeper_has_available_users(info) == TRUE) infinoted_plugin_linekeeper_join_user(info); g_object_unref(session); }
static void infinoted_plugin_document_stream_start( InfinotedPluginDocumentStreamStream* stream) { InfSession* session; InfBuffer* buffer; g_object_get(G_OBJECT(stream->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); stream->buffer = buffer; g_object_ref(buffer); if(INF_TEXT_IS_SESSION(session)) { infinoted_plugin_document_stream_sync_text(stream); g_signal_connect( G_OBJECT(buffer), "text-inserted", G_CALLBACK(infinoted_plugin_document_stream_text_inserted_cb), stream ); g_signal_connect( G_OBJECT(buffer), "text-erased", G_CALLBACK(infinoted_plugin_document_stream_text_erased_cb), stream ); } else if(INF_IS_CHAT_SESSION(session)) { infinoted_plugin_document_stream_sync_chat(stream); g_signal_connect_after( G_OBJECT(buffer), "add-message", G_CALLBACK(infinoted_plugin_document_stream_chat_add_message_cb), stream ); } g_object_unref(session); }
void Gobby::ViewCommands::on_hide_user_colors() { SessionView* view = m_text_folder.get_current_document(); TextSessionView* text_view = dynamic_cast<TextSessionView*>(view); g_assert(text_view != NULL); InfSession* session = INF_SESSION(text_view->get_session()); GtkTextBuffer* textbuffer = GTK_TEXT_BUFFER(text_view->get_text_buffer()); InfBuffer* buffer = inf_session_get_buffer(session); InfTextGtkBuffer* infbuffer = INF_TEXT_GTK_BUFFER(buffer); GtkTextIter start, end; gtk_text_buffer_get_start_iter(textbuffer, &start); gtk_text_buffer_get_end_iter(textbuffer, &end); inf_text_gtk_buffer_show_user_colors(infbuffer, FALSE, &start, &end); }
void Gobby::TextTabLabel::update_modified() { InfSession* session = INF_SESSION(m_view.get_session()); bool modified = inf_buffer_get_modified(inf_session_get_buffer(session)); InfSessionStatus status = inf_session_get_status(session); if(status == INF_SESSION_SYNCHRONIZING || status == INF_SESSION_PRESYNC) { modified = false; } if(modified) m_title.set_text("*" + m_view.get_title()); else m_title.set_text(m_view.get_title()); }
void Gobby::SynchronizationCommands:: on_synchronization_complete(InfSession* session, InfXmlConnection* c) { SyncMap::iterator iter = m_sync_map.find(session); g_assert(iter != m_sync_map.end()); // TODO: Actually we should always set the modified flag, except the // document is either empty, or known in the document info storage // and the version on disk is the same as the one we got // synchronized. We could store a hash and modification time in the // documentinfo storage for this. InfBuffer* buffer = inf_session_get_buffer(session); inf_buffer_set_modified(buffer, FALSE); delete iter->second; m_sync_map.erase(iter); }
void Gobby::SynchronizationCommands:: on_synchronization_failed(InfSession* session, InfXmlConnection* c, const GError* error) { SyncMap::iterator iter = m_sync_map.find(session); g_assert(iter != m_sync_map.end()); set_error_text(iter->second->get_session_view(), error->message); // The document will be of no use anyway, so consider it as not // being modified. InfBuffer* buffer = inf_session_get_buffer(session); inf_buffer_set_modified(buffer, FALSE); delete iter->second; m_sync_map.erase(iter); }
Gobby::TextTabLabel::TextTabLabel(Folder& folder, TextSessionView& view): TabLabel(folder, view, Gtk::Stock::EDIT), m_dot_char(0) { update_modified(); update_dots(); m_modified_changed_handle = g_signal_connect_after( G_OBJECT(view.get_text_buffer()), "modified-changed", G_CALLBACK(on_modified_changed_static), this); InfTextBuffer* buffer = INF_TEXT_BUFFER( inf_session_get_buffer( INF_SESSION(view.get_session()))); m_insert_text_handle = g_signal_connect_after( G_OBJECT(buffer), "text-inserted", G_CALLBACK(on_text_inserted_static), this); m_erase_text_handle = g_signal_connect_after( G_OBJECT(buffer), "text-erased", G_CALLBACK(on_text_erased_static), this); m_extra.pack_start(m_dots, Gtk::PACK_SHRINK); }
static void infinoted_autosave_buffer_notify_modified_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfinotedAutosaveSession* session; InfBuffer* buffer; session = (InfinotedAutosaveSession*)user_data; buffer = inf_session_get_buffer( infd_session_proxy_get_session(session->proxy) ); if(inf_buffer_get_modified(buffer) == TRUE) { if(session->timeout_handle == NULL) infinoted_autosave_session_start(session->autosave, session); } else { if(session->timeout_handle != NULL) infinoted_autosave_session_stop(session->autosave, session); } }
static void on_subscribe_session(InfcBrowser* browser, InfcBrowserIter* iter, InfcSessionProxy* proxy, gpointer user_data) { GtkWidget* window; GtkWidget* scroll; GtkWidget* textview; GtkWidget* vbox; GtkWidget* hbox; GtkWidget* undo_button; GtkWidget* redo_button; InfSession* session; InfTextGtkBuffer* buffer; GtkTextBuffer* textbuffer; InfTestGtkBrowserWindow* test; session = infc_session_proxy_get_session(proxy); buffer = INF_TEXT_GTK_BUFFER(inf_session_get_buffer(session)); textbuffer = inf_text_gtk_buffer_get_text_buffer(buffer); textview = gtk_text_view_new_with_buffer(textbuffer); gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE); gtk_widget_show(textview); scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); gtk_container_add(GTK_CONTAINER(scroll), textview); gtk_widget_show(scroll); undo_button = gtk_button_new_from_stock(GTK_STOCK_UNDO); redo_button = gtk_button_new_from_stock(GTK_STOCK_REDO); gtk_widget_set_sensitive(undo_button, FALSE); gtk_widget_set_sensitive(redo_button, FALSE); gtk_widget_show(undo_button); gtk_widget_show(redo_button); hbox = gtk_hbutton_box_new(); gtk_box_pack_start(GTK_BOX(hbox), undo_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), redo_button, FALSE, FALSE, 0); gtk_widget_show(hbox); vbox = gtk_vbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(vbox); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title( GTK_WINDOW(window), infc_browser_iter_get_name(browser, iter) ); gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); gtk_window_set_icon_name(GTK_WINDOW(window), "infinote"); gtk_container_set_border_width(GTK_CONTAINER(window), 6); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_widget_show(window); test = g_slice_new(InfTestGtkBrowserWindow); test->textview = textview; test->undo_button = undo_button; test->redo_button = redo_button; test->buffer = buffer; test->proxy = proxy; test->user = NULL; g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(on_synchronization_failed), test ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(on_synchronization_complete), test ); g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK(on_text_window_destroy), test ); g_signal_connect( G_OBJECT(undo_button), "clicked", G_CALLBACK(on_undo_button_clicked), test ); g_signal_connect( G_OBJECT(redo_button), "clicked", G_CALLBACK(on_redo_button_clicked), test ); }
static gboolean infinoted_directory_sync_add_session(InfinotedDirectorySync* dsync, InfdDirectoryIter* iter, GError** error) { InfinotedDirectorySyncSession* session; InfdSessionProxy* proxy; InfBuffer* buffer; gchar* iter_path; #ifdef G_OS_WIN32 gchar* pos; #endif gchar* full_path; gchar* converted; g_assert(infinoted_directory_sync_find_session(dsync, iter) == NULL); proxy = infd_directory_iter_peek_session(dsync->directory, iter); g_assert(proxy != NULL); /* Ignore if this is not a text session */ if(!INF_TEXT_IS_SESSION(infd_session_proxy_get_session(proxy))) return TRUE; iter_path = infd_directory_iter_get_path(dsync->directory, iter); #ifdef G_OS_WIN32 for(pos = iter_path; *pos != '\0'; ++pos) { if(*pos == '\\') { g_set_error( error, infinoted_directory_sync_error_quark(), INFINOTED_DIRECTORY_SYNC_ERROR_INVALID_PATH, _("Node \"%s\" contains invalid characters"), iter_path ); g_free(iter_path); return FALSE; } else if(*pos == '/') { *pos = '\\'; } } #endif full_path = g_build_filename(dsync->sync_directory, iter_path+1, NULL); g_free(iter_path); converted = g_filename_from_utf8(full_path, -1, NULL, NULL, error); g_free(full_path); if(!converted) return FALSE; session = g_slice_new(InfinotedDirectorySyncSession); session->dsync = dsync; session->iter = *iter; session->proxy = proxy; session->timeout = NULL; session->path = converted; dsync->sessions = g_slist_prepend(dsync->sessions, session); buffer = inf_session_get_buffer(infd_session_proxy_get_session(proxy)); g_signal_connect( G_OBJECT(buffer), "text-inserted", G_CALLBACK(infinoted_directory_sync_buffer_text_inserted_cb), session ); g_signal_connect( G_OBJECT(buffer), "text-erased", G_CALLBACK(infinoted_directory_sync_buffer_text_erased_cb), session ); infinoted_directory_sync_session_save(dsync, session); return TRUE; }
static void infinoted_directory_sync_session_save(InfinotedDirectorySync* dsync, InfinotedDirectorySyncSession* session) { InfdDirectoryIter* iter; GError* error; InfBuffer* buffer; InfTextChunk* chunk; gchar* content; gsize bytes; iter = &session->iter; error = NULL; if(session->timeout != NULL) { inf_io_remove_timeout( infd_directory_get_io(dsync->directory), session->timeout ); session->timeout = NULL; } buffer = inf_session_get_buffer( infd_session_proxy_get_session(session->proxy) ); error = NULL; if(!infinoted_util_create_dirname(session->path, &error)) { g_warning(_("Failed to create directory for path \"%s\": %s\n\n"), session->path, error->message); g_error_free(error); } else { /* TODO: Use the iterator API here, which should be less expensive */ chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(buffer), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(buffer)) ); content = inf_text_chunk_get_text(chunk, &bytes); inf_text_chunk_free(chunk); if(!g_file_set_contents(session->path, content, bytes, &error)) { g_warning( _("Failed to write session for path \"%s\": %s\n\n" "Will retry in %u seconds."), session->path, error->message, dsync->sync_interval ); g_error_free(error); infinoted_directory_sync_session_start(session->dsync, session); } g_free(content); } }
static GObject* inf_adopted_session_constructor(GType type, guint n_construct_properties, GObjectConstructParam* construct_properties) { GObject* object; InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; InfSessionStatus status; InfUserTable* user_table; object = G_OBJECT_CLASS(parent_class)->constructor( type, n_construct_properties, construct_properties ); session = INF_ADOPTED_SESSION(object); priv = INF_ADOPTED_SESSION_PRIVATE(session); g_assert(priv->io != NULL); g_object_get(G_OBJECT(session), "status", &status, NULL); user_table = inf_session_get_user_table(INF_SESSION(session)); g_signal_connect( G_OBJECT(user_table), "add-local-user", G_CALLBACK(inf_adopted_session_add_local_user_cb), session ); g_signal_connect( G_OBJECT(user_table), "remove-local-user", G_CALLBACK(inf_adopted_session_remove_local_user_cb), session ); switch(status) { case INF_SESSION_PRESYNC: case INF_SESSION_SYNCHRONIZING: /* algorithm is created during initial synchronization when parameters * like initial vector time, max total log size etc. are known. */ break; case INF_SESSION_RUNNING: g_assert(inf_session_get_buffer(INF_SESSION(session)) != NULL); inf_adopted_session_create_algorithm(session); break; case INF_SESSION_CLOSED: /* Session should not be initially closed */ default: g_assert_not_reached(); break; } /* Add initial local users. Note that this requires the algorithm to exist, * though in synchronizing state no local users can exist. */ inf_user_table_foreach_local_user( user_table, inf_adopted_session_constructor_foreach_local_user_func, session ); return object; }
static void infinoted_autosave_session_save(InfinotedAutosave* autosave, InfinotedAutosaveSession* session) { InfdDirectory* directory; InfdDirectoryIter* iter; GError* error; gchar* path; InfBuffer* buffer; directory = autosave->directory; iter = &session->iter; error = NULL; if(session->timeout_handle != NULL) { inf_io_remove_timeout( infd_directory_get_io(directory), session->timeout_handle ); session->timeout_handle = NULL; } buffer = inf_session_get_buffer( infd_session_proxy_get_session(session->proxy) ); g_signal_handlers_block_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_autosave_buffer_notify_modified_cb), session ); if(infd_directory_iter_save_session(directory, iter, &error) == FALSE) { path = infd_directory_iter_get_path(directory, iter); g_warning( _("Failed to auto-save session \"%s\": %s\n\n" "Will retry in %u seconds."), path, error->message, session->autosave->autosave_interval ); g_free(path); g_error_free(error); infinoted_autosave_session_start(session->autosave, session); } else { /* TODO: Remove this as soon as directory itself unsets modified flag * on session_write */ inf_buffer_set_modified(INF_BUFFER(buffer), FALSE); } g_signal_handlers_unblock_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_autosave_buffer_notify_modified_cb), session ); }
static gboolean infd_note_plugin_text_session_write(InfdStorage* storage, InfSession* session, const gchar* path, gpointer user_data, GError** error) { InfUserTable* table; InfTextBuffer* buffer; InfTextBufferIter* iter; xmlNodePtr root; xmlNodePtr buffer_node; xmlNodePtr segment_node; guint author; gchar* content; gsize bytes; FILE* stream; xmlDocPtr doc; xmlErrorPtr xmlerror; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); g_assert(INF_TEXT_IS_SESSION(session)); /* Open stream before exporting buffer to XML so possible errors are * catched earlier. */ stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfText", path, "w", error ); if(stream == NULL) return FALSE; root = xmlNewNode(NULL, (const xmlChar*)"inf-text-session"); buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); table = inf_session_get_user_table(session); inf_user_table_foreach_user( table, infd_note_plugin_text_session_write_foreach_user_func, root ); buffer_node = xmlNewChild(root, NULL, (const xmlChar*)"buffer", NULL); iter = inf_text_buffer_create_iter(buffer); if(iter != NULL) { do { author = inf_text_buffer_iter_get_author(buffer, iter); content = inf_text_buffer_iter_get_text(buffer, iter); bytes = inf_text_buffer_iter_get_bytes(buffer, iter); segment_node = xmlNewChild( buffer_node, NULL, (const xmlChar*)"segment", NULL ); inf_xml_util_set_attribute_uint(segment_node, "author", author); inf_xml_util_add_child_text(segment_node, content, bytes); g_free(content); } while(inf_text_buffer_iter_next(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); } doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, root); if(xmlDocFormatDump(stream, doc, 1) == -1) { xmlerror = xmlGetLastError(); fclose(stream); xmlFreeDoc(doc); g_set_error( error, g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"), xmlerror->code, "%s", xmlerror->message ); return FALSE; } fclose(stream); xmlFreeDoc(doc); return TRUE; }
int main(int argc, char* argv[]) { InfAdoptedSessionReplay* replay; InfAdoptedSession* session; GError* error; int i; int ret; InfBuffer* buffer; GSList* item; gint counter; if(argc < 2) { fprintf(stderr, "Usage: %s <record-file> [index]\n", argv[0]); return -1; } counter = 0; if(argc > 2) counter = atoi(argv[2]); error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return -1; } ret = 0; for(i = 1; i < 2; ++ i) { replay = inf_adopted_session_replay_new(); inf_adopted_session_replay_set_record( replay, argv[i], &INF_TEST_TEXT_RECOVER_TEXT_PLUGIN, &error ); if(error != NULL) { fprintf(stderr, "%s\n", error->message); g_error_free(error); error = NULL; ret = -1; } else { session = inf_adopted_session_replay_get_session(replay); buffer = inf_session_get_buffer(INF_SESSION(session)); g_signal_connect( buffer, "text-erased", G_CALLBACK(inf_test_text_recover_text_erased_cb), &counter ); if(!inf_adopted_session_replay_play_to_end(replay, &error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); error = NULL; ret = -1; } else if(counter == 0) { inf_test_util_print_buffer(INF_TEXT_BUFFER(buffer)); } } g_object_unref(replay); } return ret; }
static void infinoted_plugin_autosave_save(InfinotedPluginAutosaveSessionInfo* info) { InfdDirectory* directory; InfBrowserIter* iter; GError* error; gchar* path; InfSession* session; InfBuffer* buffer; gchar* root_directory; gchar* argv[4]; directory = infinoted_plugin_manager_get_directory(info->plugin->manager); iter = &info->iter; error = NULL; if(info->timeout != NULL) { inf_io_remove_timeout(infd_directory_get_io(directory), info->timeout); info->timeout = NULL; } g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); inf_signal_handlers_block_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); if(infd_directory_iter_save_session(directory, iter, &error) == FALSE) { path = inf_browser_get_path(INF_BROWSER(directory), iter); infinoted_log_warning( infinoted_plugin_manager_get_log(info->plugin->manager), _("Failed to auto-save session \"%s\": %s\n\n" "Will retry in %u seconds."), path, error->message, info->plugin->interval ); g_free(path); g_error_free(error); error = NULL; infinoted_plugin_autosave_start(info); } else { /* TODO: Remove this as soon as directory itself unsets modified flag * on session_write */ inf_buffer_set_modified(INF_BUFFER(buffer), FALSE); if(info->plugin->hook != NULL) { path = inf_browser_get_path(INF_BROWSER(directory), iter); g_object_get( G_OBJECT(infd_directory_get_storage(directory)), "root-directory", &root_directory, NULL ); argv[0] = info->plugin->hook; argv[1] = root_directory; argv[2] = path; argv[3] = NULL; if(!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error)) { infinoted_log_warning( infinoted_plugin_manager_get_log(info->plugin->manager), _("Could not execute autosave hook: \"%s\""), error->message ); g_error_free(error); error = NULL; } g_free(path); g_free(root_directory); } } inf_signal_handlers_unblock_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); g_object_unref(session); }