| | 44 | |
|---|
| | 45 | |
|---|
| | 46 | static void |
|---|
| | 47 | notify_folder_observers_about (TnyFolder *self, TnyFolderChange *change) |
|---|
| | 48 | { |
|---|
| | 49 | TnyMergeFolderPriv *priv = TNY_MERGE_FOLDER_GET_PRIVATE (self); |
|---|
| | 50 | TnyIterator *iter; |
|---|
| | 51 | |
|---|
| | 52 | if (!priv->observers) |
|---|
| | 53 | return; |
|---|
| | 54 | |
|---|
| | 55 | g_static_rec_mutex_lock (priv->lock); |
|---|
| | 56 | |
|---|
| | 57 | iter = tny_list_create_iterator (priv->observers); |
|---|
| | 58 | while (!tny_iterator_is_done (iter)) |
|---|
| | 59 | { |
|---|
| | 60 | TnyFolderObserver *observer = TNY_FOLDER_OBSERVER (tny_iterator_get_current (iter)); |
|---|
| | 61 | tny_folder_observer_update (observer, change); |
|---|
| | 62 | g_object_unref (G_OBJECT (observer)); |
|---|
| | 63 | tny_iterator_next (iter); |
|---|
| | 64 | } |
|---|
| | 65 | g_object_unref (G_OBJECT (iter)); |
|---|
| | 66 | |
|---|
| | 67 | g_static_rec_mutex_unlock (priv->lock); |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| | 70 | |
|---|
| | 200 | /* get_msg & get_msg_async */ |
|---|
| | 201 | typedef struct |
|---|
| | 202 | { |
|---|
| | 203 | TnyFolder *self; |
|---|
| | 204 | TnyMsg *msg; |
|---|
| | 205 | TnyHeader *header; |
|---|
| | 206 | GError *err; |
|---|
| | 207 | gpointer user_data; |
|---|
| | 208 | guint depth; |
|---|
| | 209 | TnyGetMsgCallback callback; |
|---|
| | 210 | } GetMsgInfo; |
|---|
| | 211 | |
|---|
| | 212 | static void |
|---|
| | 213 | get_msg_async_destroyer (gpointer thr_user_data) |
|---|
| | 214 | { |
|---|
| | 215 | GetMsgInfo *info = (GetMsgInfo *) thr_user_data; |
|---|
| | 216 | |
|---|
| | 217 | /* thread reference */ |
|---|
| | 218 | g_object_unref (G_OBJECT (info->self)); |
|---|
| | 219 | if (info->msg) |
|---|
| | 220 | g_object_unref (G_OBJECT (info->msg)); |
|---|
| | 221 | |
|---|
| | 222 | if (info->err) |
|---|
| | 223 | g_error_free (info->err); |
|---|
| | 224 | |
|---|
| | 225 | g_slice_free (GetMsgInfo, info); |
|---|
| | 226 | } |
|---|
| | 227 | |
|---|
| | 228 | static gboolean |
|---|
| | 229 | get_msg_async_callback (gpointer thr_user_data) |
|---|
| | 230 | { |
|---|
| | 231 | GetMsgInfo *info = (GetMsgInfo *) thr_user_data; |
|---|
| | 232 | |
|---|
| | 233 | if (info->callback) |
|---|
| | 234 | info->callback (info->self, info->msg, &info->err, info->user_data); |
|---|
| | 235 | |
|---|
| | 236 | return FALSE; |
|---|
| | 237 | } |
|---|
| | 238 | |
|---|
| | 239 | |
|---|
| | 240 | static gpointer |
|---|
| | 241 | get_msg_async_thread (gpointer thr_user_data) |
|---|
| | 242 | { |
|---|
| | 243 | GetMsgInfo *info = (GetMsgInfo *) thr_user_data; |
|---|
| | 244 | GError *err = NULL; |
|---|
| | 245 | |
|---|
| | 246 | info->msg = tny_folder_get_msg (info->self, info->header, &err); |
|---|
| | 247 | |
|---|
| | 248 | if (err != NULL) |
|---|
| | 249 | { |
|---|
| | 250 | info->err = g_error_copy ((const GError *) err); |
|---|
| | 251 | if (info->msg && G_IS_OBJECT (info->msg)) |
|---|
| | 252 | g_object_unref (G_OBJECT (info->msg)); |
|---|
| | 253 | info->msg = NULL; |
|---|
| | 254 | } else |
|---|
| | 255 | info->err = NULL; |
|---|
| | 256 | |
|---|
| | 257 | g_object_unref (G_OBJECT (info->header)); |
|---|
| | 258 | |
|---|
| | 259 | if (info->callback) |
|---|
| | 260 | { |
|---|
| | 261 | if (info->depth > 0) |
|---|
| | 262 | { |
|---|
| | 263 | g_idle_add_full (G_PRIORITY_HIGH, |
|---|
| | 264 | get_msg_async_callback, |
|---|
| | 265 | info, get_msg_async_destroyer); |
|---|
| | 266 | } else { |
|---|
| | 267 | get_msg_async_callback (info); |
|---|
| | 268 | get_msg_async_destroyer (info); |
|---|
| | 269 | } |
|---|
| | 270 | } else /* thread reference */ |
|---|
| | 271 | g_object_unref (G_OBJECT (info->self)); |
|---|
| | 272 | |
|---|
| | 273 | g_thread_exit (NULL); |
|---|
| | 274 | |
|---|
| | 275 | return NULL; |
|---|
| | 276 | |
|---|
| | 277 | } |
|---|
| | 278 | |
|---|
| 177 | | TnyMsg *msg; |
|---|
| 178 | | |
|---|
| 179 | | /* TODO: do this is a thread */ |
|---|
| 180 | | msg = tny_merge_folder_get_msg (self, header, &err); |
|---|
| 181 | | |
|---|
| 182 | | if (callback) /* TODO: this is not always on the gmainloop */ |
|---|
| 183 | | callback (self, msg, &err, user_data); |
|---|
| | 285 | |
|---|
| | 286 | info = g_slice_new (GetMsgInfo); |
|---|
| | 287 | info->self = self; |
|---|
| | 288 | info->header = header; |
|---|
| | 289 | info->callback = callback; |
|---|
| | 290 | info->user_data = user_data; |
|---|
| | 291 | info->depth = g_main_depth (); |
|---|
| | 292 | |
|---|
| | 293 | /* thread reference */ |
|---|
| | 294 | g_object_ref (G_OBJECT (info->self)); |
|---|
| | 295 | g_object_ref (G_OBJECT (info->header)); |
|---|
| | 296 | |
|---|
| | 297 | thread = g_thread_create (get_msg_async_thread, info, FALSE, NULL); |
|---|
| | 298 | |
|---|
| | 299 | return; |
|---|
| | 491 | |
|---|
| | 492 | typedef struct |
|---|
| | 493 | { |
|---|
| | 494 | TnyFolder *self; |
|---|
| | 495 | TnyRefreshFolderCallback callback; |
|---|
| | 496 | TnyRefreshFolderStatusCallback status_callback; |
|---|
| | 497 | gpointer user_data; |
|---|
| | 498 | gboolean cancelled; |
|---|
| | 499 | guint depth; |
|---|
| | 500 | GError *err; |
|---|
| | 501 | } RefreshFolderInfo; |
|---|
| | 502 | |
|---|
| | 503 | |
|---|
| | 504 | static void |
|---|
| | 505 | refresh_async_destroyer (gpointer thr_user_data) |
|---|
| | 506 | { |
|---|
| | 507 | RefreshFolderInfo *info = thr_user_data; |
|---|
| | 508 | TnyFolder *self = info->self; |
|---|
| | 509 | |
|---|
| | 510 | /* thread reference */ |
|---|
| | 511 | g_object_unref (G_OBJECT (self)); |
|---|
| | 512 | if (info->err) |
|---|
| | 513 | g_error_free (info->err); |
|---|
| | 514 | |
|---|
| | 515 | g_slice_free (RefreshFolderInfo, thr_user_data); |
|---|
| | 516 | |
|---|
| | 517 | return; |
|---|
| | 518 | } |
|---|
| | 519 | |
|---|
| | 520 | static gboolean |
|---|
| | 521 | refresh_async_callback (gpointer thr_user_data) |
|---|
| | 522 | { |
|---|
| | 523 | RefreshFolderInfo *info = thr_user_data; |
|---|
| | 524 | TnyFolder *self = info->self; |
|---|
| | 525 | |
|---|
| | 526 | if (info->callback) |
|---|
| | 527 | info->callback (info->self, info->cancelled, &info->err, info->user_data); |
|---|
| | 528 | |
|---|
| | 529 | /* TODO: trigger this change notification |
|---|
| | 530 | if (info->oldlen != priv->cached_length || info->oldurlen != priv->unread_length) |
|---|
| | 531 | { |
|---|
| | 532 | TnyFolderChange *change = tny_folder_change_new (self); |
|---|
| | 533 | if (info->oldlen != priv->cached_length) |
|---|
| | 534 | tny_folder_change_set_new_all_count (change, priv->cached_length); |
|---|
| | 535 | if (info->oldurlen != priv->unread_length) |
|---|
| | 536 | tny_folder_change_set_new_unread_count (change, priv->unread_length); |
|---|
| | 537 | notify_folder_observers_about (self, change); |
|---|
| | 538 | g_object_unref (change); |
|---|
| | 539 | } */ |
|---|
| | 540 | |
|---|
| | 541 | return FALSE; |
|---|
| | 542 | } |
|---|
| | 543 | |
|---|
| | 544 | |
|---|
| | 545 | static gpointer |
|---|
| | 546 | refresh_async_thread (gpointer thr_user_data) |
|---|
| | 547 | { |
|---|
| | 548 | RefreshFolderInfo *info = thr_user_data; |
|---|
| | 549 | TnyFolder *self = info->self; |
|---|
| | 550 | TnyMergeFolderPriv *priv = TNY_MERGE_FOLDER_GET_PRIVATE (self); |
|---|
| | 551 | TnyIterator *iter; |
|---|
| | 552 | GError *err = NULL; |
|---|
| | 553 | |
|---|
| | 554 | g_static_rec_mutex_lock (priv->lock); |
|---|
| | 555 | |
|---|
| | 556 | info->cancelled = FALSE; |
|---|
| | 557 | |
|---|
| | 558 | iter = tny_list_create_iterator (priv->mothers); |
|---|
| | 559 | while (!tny_iterator_is_done (iter)) |
|---|
| | 560 | { |
|---|
| | 561 | TnyFolder *cur = TNY_FOLDER (tny_iterator_get_current (iter)); |
|---|
| | 562 | |
|---|
| | 563 | tny_folder_refresh (cur, &err); |
|---|
| | 564 | |
|---|
| | 565 | /* TODO: Handler err */ |
|---|
| | 566 | |
|---|
| | 567 | /* TODO: Handle progress status callbacks ( info->status_callback ) |
|---|
| | 568 | * you might have to start using refresh_async for that (in a |
|---|
| | 569 | * serialized way, else you'd launch a buch of concurrent threads |
|---|
| | 570 | * and ain't going to be nice, perhaps). */ |
|---|
| | 571 | |
|---|
| | 572 | g_object_unref (cur); |
|---|
| | 573 | tny_iterator_next (iter); |
|---|
| | 574 | } |
|---|
| | 575 | g_object_unref (iter); |
|---|
| | 576 | |
|---|
| | 577 | info->err = NULL; |
|---|
| | 578 | |
|---|
| | 579 | g_static_rec_mutex_unlock (priv->lock); |
|---|
| | 580 | |
|---|
| | 581 | if (info->callback) |
|---|
| | 582 | { |
|---|
| | 583 | if (info->depth > 0) |
|---|
| | 584 | { |
|---|
| | 585 | g_idle_add_full (G_PRIORITY_HIGH, |
|---|
| | 586 | refresh_async_callback, |
|---|
| | 587 | info, refresh_async_destroyer); |
|---|
| | 588 | } else { |
|---|
| | 589 | refresh_async_callback (info); |
|---|
| | 590 | refresh_async_destroyer (info); |
|---|
| | 591 | } |
|---|
| | 592 | } else /* Thread reference */ |
|---|
| | 593 | g_object_unref (G_OBJECT (self)); |
|---|
| | 594 | |
|---|
| | 595 | g_thread_exit (NULL); |
|---|
| | 596 | |
|---|
| | 597 | return NULL; |
|---|
| | 598 | } |
|---|
| | 599 | |
|---|
| | 600 | |
|---|
| 379 | | /* TODO: do this is a thread */ |
|---|
| 380 | | tny_merge_folder_refresh (self, &err); |
|---|
| 381 | | |
|---|
| 382 | | if (callback) /* TODO: this is not always on the gmainloop */ |
|---|
| 383 | | callback (self, FALSE, &err, user_data); |
|---|
| 384 | | } |
|---|
| 385 | | |
|---|
| | 608 | info = g_slice_new (RefreshFolderInfo); |
|---|
| | 609 | info->err = NULL; |
|---|
| | 610 | info->self = self; |
|---|
| | 611 | info->callback = callback; |
|---|
| | 612 | info->status_callback = status_callback; |
|---|
| | 613 | info->user_data = user_data; |
|---|
| | 614 | info->depth = g_main_depth (); |
|---|
| | 615 | |
|---|
| | 616 | /* thread reference */ |
|---|
| | 617 | g_object_ref (G_OBJECT (self)); |
|---|
| | 618 | |
|---|
| | 619 | thread = g_thread_create (refresh_async_thread, info, FALSE, NULL); |
|---|
| | 620 | |
|---|
| | 621 | return; |
|---|
| | 622 | } |
|---|
| | 623 | |
|---|
| | 624 | /* transfer_msgs & transfer_msgs_async */ |
|---|
| | 659 | typedef struct |
|---|
| | 660 | { |
|---|
| | 661 | TnyFolder *self; |
|---|
| | 662 | TnyList *header_list; |
|---|
| | 663 | TnyFolder *folder_dst; |
|---|
| | 664 | gboolean delete_originals; |
|---|
| | 665 | TnyTransferMsgsCallback callback; |
|---|
| | 666 | gpointer user_data; |
|---|
| | 667 | gint depth; |
|---|
| | 668 | GError *err; |
|---|
| | 669 | } TransferMsgsInfo; |
|---|
| | 670 | |
|---|
| | 671 | |
|---|
| | 672 | static void |
|---|
| | 673 | transfer_msgs_async_destroyer (gpointer thr_user_data) |
|---|
| | 674 | { |
|---|
| | 675 | TransferMsgsInfo *info = thr_user_data; |
|---|
| | 676 | |
|---|
| | 677 | /* thread reference */ |
|---|
| | 678 | g_object_unref (G_OBJECT (info->self)); |
|---|
| | 679 | g_object_unref (G_OBJECT (info->folder_dst)); |
|---|
| | 680 | g_object_unref (G_OBJECT (info->header_list)); |
|---|
| | 681 | |
|---|
| | 682 | if (info->err) |
|---|
| | 683 | g_error_free (info->err); |
|---|
| | 684 | |
|---|
| | 685 | g_slice_free (TransferMsgsInfo, thr_user_data); |
|---|
| | 686 | |
|---|
| | 687 | return; |
|---|
| | 688 | } |
|---|
| | 689 | |
|---|
| | 690 | static gboolean |
|---|
| | 691 | transfer_msgs_async_callback (gpointer thr_user_data) |
|---|
| | 692 | { |
|---|
| | 693 | TransferMsgsInfo *info = thr_user_data; |
|---|
| | 694 | TnyFolder *self = info->self; |
|---|
| | 695 | |
|---|
| | 696 | if (info->callback) |
|---|
| | 697 | info->callback (info->self, &info->err, info->user_data); |
|---|
| | 698 | |
|---|
| | 699 | return FALSE; |
|---|
| | 700 | } |
|---|
| | 701 | |
|---|
| | 702 | |
|---|
| | 703 | static gpointer |
|---|
| | 704 | transfer_msgs_async_thread (gpointer thr_user_data) |
|---|
| | 705 | { |
|---|
| | 706 | TransferMsgsInfo *info = thr_user_data; |
|---|
| | 707 | TnyFolder *self = info->self; |
|---|
| | 708 | TnyMergeFolderPriv *priv = TNY_MERGE_FOLDER_GET_PRIVATE (self); |
|---|
| | 709 | TnyIterator *iter; |
|---|
| | 710 | |
|---|
| | 711 | g_static_rec_mutex_lock (priv->lock); |
|---|
| | 712 | tny_merge_folder_transfer_msgs (info->self, info->header_list, info->folder_dst, info->delete_originals, &info->err); |
|---|
| | 713 | g_static_rec_mutex_unlock (priv->lock); |
|---|
| | 714 | |
|---|
| | 715 | if (info->callback) |
|---|
| | 716 | { |
|---|
| | 717 | if (info->depth > 0) |
|---|
| | 718 | { |
|---|
| | 719 | g_idle_add_full (G_PRIORITY_HIGH, |
|---|
| | 720 | transfer_msgs_async_callback, |
|---|
| | 721 | info, transfer_msgs_async_destroyer); |
|---|
| | 722 | } else { |
|---|
| | 723 | transfer_msgs_async_callback (info); |
|---|
| | 724 | transfer_msgs_async_destroyer (info); |
|---|
| | 725 | } |
|---|
| | 726 | } else { /* Thread reference */ |
|---|
| | 727 | g_object_unref (G_OBJECT (info->self)); |
|---|
| | 728 | g_object_unref (G_OBJECT (info->folder_dst)); |
|---|
| | 729 | g_object_unref (G_OBJECT (info->header_list)); |
|---|
| | 730 | } |
|---|
| | 731 | |
|---|
| | 732 | g_thread_exit (NULL); |
|---|
| | 733 | |
|---|
| | 734 | return NULL; |
|---|
| | 735 | } |
|---|
| | 736 | |
|---|
| 423 | | GError *err = NULL; |
|---|
| 424 | | |
|---|
| 425 | | /* TODO: do this is a thread */ |
|---|
| 426 | | tny_merge_folder_transfer_msgs (self, header_list, folder_dst, delete_originals, &err); |
|---|
| 427 | | |
|---|
| 428 | | if (callback) /* TODO call the callback in gmainloop */ |
|---|
| 429 | | callback (self, &err, user_data); |
|---|
| 430 | | |
|---|
| 431 | | } |
|---|
| 432 | | |
|---|
| | 740 | TransferMsgsInfo *info; |
|---|
| | 741 | GThread *thread; |
|---|
| | 742 | |
|---|
| | 743 | info = g_slice_new (TransferMsgsInfo); |
|---|
| | 744 | info->err = NULL; |
|---|
| | 745 | info->self = self; |
|---|
| | 746 | info->callback = callback; |
|---|
| | 747 | info->header_list = header_list; |
|---|
| | 748 | info->user_data = user_data; |
|---|
| | 749 | info->depth = g_main_depth (); |
|---|
| | 750 | info->delete_originals = delete_originals; |
|---|
| | 751 | info->folder_dst = folder_dst; |
|---|
| | 752 | info->err = NULL; |
|---|
| | 753 | |
|---|
| | 754 | /* thread reference */ |
|---|
| | 755 | g_object_ref (G_OBJECT (self)); |
|---|
| | 756 | g_object_ref (G_OBJECT (folder_dst)); |
|---|
| | 757 | g_object_ref (G_OBJECT (header_list)); |
|---|
| | 758 | |
|---|
| | 759 | thread = g_thread_create (transfer_msgs_async_thread, info, FALSE, NULL); |
|---|
| | 760 | |
|---|
| | 761 | return; |
|---|
| | 762 | } |
|---|
| | 763 | |
|---|
| | 764 | |
|---|
| | 765 | /* copy */ |
|---|
| 593 | | TnyMergeFolderPriv *priv = TNY_MERGE_FOLDER_GET_PRIVATE (self); |
|---|
| 594 | | |
|---|
| 595 | | g_static_rec_mutex_lock (priv->lock); |
|---|
| 596 | | |
|---|
| 597 | | if (priv->observers) |
|---|
| 598 | | { |
|---|
| 599 | | TnyIterator *iter = tny_list_create_iterator (priv->observers); |
|---|
| 600 | | while (!tny_iterator_is_done (iter)) |
|---|
| 601 | | { |
|---|
| 602 | | TnyFolderObserver *observer = TNY_FOLDER_OBSERVER (tny_iterator_get_current (iter)); |
|---|
| 603 | | tny_folder_observer_update (observer, change); |
|---|
| 604 | | g_object_unref (observer); |
|---|
| 605 | | tny_iterator_next (iter); |
|---|
| 606 | | } |
|---|
| 607 | | g_object_unref (iter); |
|---|
| 608 | | } |
|---|
| 609 | | |
|---|
| 610 | | g_static_rec_mutex_unlock (priv->lock); |
|---|
| | 926 | notify_folder_observers_about (TNY_FOLDER (self), change); |
|---|