1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
10 # include "glib-all.h"
14 #include "liblj/sync.h"
17 #include "journalstore.h"
21 static const char *status_stages
[] = {
24 //N_("Comment metadata..."),
39 GtkWidget
*progresswin
;
40 GtkWidget
*label
, *progress
;
43 JamAccountLJ
*account
;
48 gboolean sync_complete
;
53 static gboolean
sync_run_internal (SyncStatus
*status
, LJRunVerbCallback sync_run_verb
, LJSyncProgressCallback sync_progress
, gpointer parent
, GSList
**warnings
, GError
**err
);
56 /*** gtk-specific functions. ***/
58 static void show_status_stage (SyncStatus
*status
) {
59 GString
*str
= g_string_sized_new(20*STAGE_COUNT
);
60 for (int i
= 0; i
< STAGE_COUNT
; i
++) {
61 if (i
== status
->stage
) g_string_append(str
, "\342\226\266 "); /* U+25B6: black arrow */
62 g_string_append(str
, _(status_stages
[i
]));
63 g_string_append_c(str
, '\n');
65 gtk_label_set_label(GTK_LABEL(status
->label
), str
->str
);
66 g_string_free(str
, TRUE
);
70 static void sync_init_gtk (SyncStatus
*status
, gpointer parent
) {
71 status
->progresswin
= progress_window_new(GTK_WINDOW(parent
), _("Synchronizing Journal"));
72 status
->label
= gtk_label_new("");
73 gtk_misc_set_alignment(GTK_MISC(status
->label
), 0, 0);
75 show_status_stage(status
);
76 status
->progress
= gtk_progress_bar_new();
77 gtk_widget_show(status
->label
);
78 gtk_widget_show(status
->progress
);
79 progress_window_pack(PROGRESS_WINDOW(status
->progresswin
), status
->label
);
80 progress_window_pack(PROGRESS_WINDOW(status
->progresswin
), status
->progress
);
81 gtk_widget_show(status
->progresswin
);
85 static gboolean
sync_run_verb_gtk (gpointer data
, LJVerb
*verb
, GError
**err
) {
86 SyncStatus
*status
= data
;
87 return net_window_run_verb(PROGRESS_WINDOW(status
->progresswin
), verb
);
91 static void sync_progress_gtk (gpointer data
, LJSyncProgress progress
, int cur
, int max
, const char *date
) {
92 SyncStatus
*status
= data
;
93 double fraction
= 0.0;
96 case LJ_SYNC_PROGRESS_ITEMS
: stage
= STAGE_ENTRYMETA
; break;
97 case LJ_SYNC_PROGRESS_ENTRIES
: stage
= STAGE_ENTRY
; break;
98 default: stage
= STAGE_ENTRY
; break; /*k8: just in case*/
100 if (stage
!= status
->stage
) {
101 status
->stage
= stage
;
102 show_status_stage(status
);
104 if (max
> 0) fraction
= cur
/(double)max
;
105 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(status
->progress
), fraction
);
109 static void sync_show_warnings_gtk (SyncStatus
*status
, GSList
*warnings
) {
110 GtkWidget
*dlg
, *hbox
, *image
, *label
, *scroll
;
113 /* we create our own version of GtkMessageDialog so we can add the scroll bar */
114 dlg
= gtk_dialog_new_with_buttons(_("Warnings"), GTK_WINDOW(status
->progresswin
), GTK_DIALOG_MODAL
, GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
, NULL
);
116 image
= gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING
, GTK_ICON_SIZE_DIALOG
);
117 gtk_misc_set_alignment(GTK_MISC(image
), 0.5, 0.0);
119 warnstr
= g_string_new(warnings
->data
);
120 for (l
= warnings
->next
; l
; l
= l
->next
) {
121 g_string_append_c(warnstr
, '\n');
122 g_string_append(warnstr
, l
->data
);
125 label
= gtk_label_new(warnstr
->str
);
126 g_string_free(warnstr
, TRUE
);
127 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
128 gtk_label_set_selectable(GTK_LABEL(label
), TRUE
);
130 scroll
= gtk_scrolled_window_new (NULL
, NULL
);
131 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll
), GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
132 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll
), GTK_SHADOW_NONE
);
133 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll
), label
);
135 hbox
= gtk_hbox_new(FALSE
, 6);
136 gtk_box_pack_start(GTK_BOX(hbox
), image
, FALSE
, FALSE
, 0);
137 gtk_box_pack_start(GTK_BOX(hbox
), scroll
, TRUE
, TRUE
, 0);
138 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg
)->vbox
), hbox
, TRUE
, TRUE
, 0);
139 gtk_widget_show_all(hbox
);
141 gtk_dialog_run(GTK_DIALOG(dlg
));
142 gtk_widget_destroy(dlg
);
146 gboolean
sync_run_gtk (JamAccountLJ
*acc
, gpointer parent
) {
147 SyncStatus st
= {0}, *status
= &st
;
148 GSList
*warnings
= NULL
;
152 status
->account
= acc
;
154 sync_init_gtk(status
, parent
);
155 success
= sync_run_internal(status
, sync_run_verb_gtk
, sync_progress_gtk
,
156 parent
, &warnings
, &err
);
159 sync_show_warnings_gtk(status
, warnings
);
160 g_slist_foreach(warnings
, (GFunc
)g_free
, NULL
);
161 g_slist_free(warnings
);
165 progress_window_show_error(PROGRESS_WINDOW(status
->progresswin
), err
->message
);
170 if (status
->progresswin
) gtk_widget_destroy(status
->progresswin
);
174 #endif /* HAVE_GTK */
177 /*** console-specific functions. ***/
178 static gboolean
sync_run_verb_cli (gpointer data
, LJVerb
*verb
, GError
**err
) {
179 return net_run_verb_ctx(verb
, network_ctx_silent
, err
);
183 static void sync_progress_cli (gpointer data
, LJSyncProgress progress
, int cur
, int max
, const char *date
) {
185 if (cur
== 0 && progress
== LJ_SYNC_PROGRESS_ITEMS
) g_print(_("Up-to-date.\n"));
190 case LJ_SYNC_PROGRESS_ITEMS
: g_print(_("Downloading %d sync items: "), max
); break;
191 case LJ_SYNC_PROGRESS_ENTRIES
: g_print(_("Downloading %d entries: "), max
); break;
194 g_print("%.1f%% ", (cur
*100.0)/(double)max
);
195 if (cur
== max
) g_print(_("done.\n"));
200 gboolean
sync_run_cli (JamAccountLJ
*acc
) {
201 SyncStatus st
= {0}, *status
= &st
;
202 GSList
*warnings
= NULL
, *l
;
207 status
->account
= acc
;
208 id
= jam_account_id_strdup(JAM_ACCOUNT(status
->account
));
209 g_print(_("Synchronizing '%s'..."), id
);
213 success
= sync_run_internal(status
, sync_run_verb_cli
, sync_progress_cli
, NULL
, &warnings
, &err
);
216 g_print(_("Warnings:\n"));
217 for (l
= warnings
; l
; l
= l
->next
) g_print("\t%s\n", (char*)l
->data
);
218 g_slist_foreach(warnings
, (GFunc
)g_free
, NULL
);
219 g_slist_free(warnings
);
222 g_print(_("Error: %s\n"), err
->message
);
230 static gboolean
put_lastsync (gpointer data
, const char *lastsync
, GError
**err
) {
231 SyncStatus
*status
= data
;
232 return journal_store_put_lastsync(status
->js
, lastsync
, err
);
236 static gboolean
put_entries (gpointer data
, LJEntry
**entries
, int count
, GError
**err
) {
237 SyncStatus
*status
= data
;
238 if (!journal_store_put_group(status
->js
, entries
, count
, err
)) return FALSE
;
243 /* through callbacks, this function manages to drive both
244 * the gtk and the cli sync. */
245 static gboolean
sync_run_internal (SyncStatus
*status
,
246 LJRunVerbCallback sync_run_verb
,
247 LJSyncProgressCallback sync_progress
,
249 GSList
**warnings
, GError
**err
)
251 GError
*tmperr
= NULL
;
252 gboolean success
= FALSE
;
253 char *lastsync
= NULL
;
255 status
->js
= journal_store_open(JAM_ACCOUNT(status
->account
), TRUE
, &tmperr
);
256 if (!status
->js
) goto err
;
258 lastsync
= journal_store_get_lastsync(status
->js
);
260 if (!lj_sync_run(jam_account_lj_get_user(status
->account
), NULL
/*usejournal*/,
262 put_lastsync
, sync_run_verb
, put_entries
, sync_progress
,
263 status
, warnings
, &tmperr
))
269 if (tmperr
) g_propagate_error(err
, tmperr
);
272 if (status
->js
) journal_store_free(status
->js
);
278 gboolean
sync_run (JamAccountLJ
*acc
, gpointer parent
) {
280 if (!app
.cli
) return sync_run_gtk(acc
, parent
);
281 else return sync_run_cli(acc
);
283 return sync_run_cli(acc
);