692 UiString *label_top_right; |
693 UiString *label_top_right; |
693 UiString *label_bottom_left; |
694 UiString *label_bottom_left; |
694 UiString *label_bottom_right; |
695 UiString *label_bottom_right; |
695 } DavFileDownload; |
696 } DavFileDownload; |
696 |
697 |
|
698 |
|
699 static int uithr_download_update_progress(void *data) { |
|
700 DavFileDownload *download = data; |
|
701 |
|
702 char *sz_total = util_size_str(FALSE, download->total_bytes); |
|
703 char *sz_downloaded = util_size_str2(FALSE, download->downloaded_bytes, download->total_bytes, 2); |
|
704 char *sz_downloaded_end = strchr(sz_downloaded, ' '); |
|
705 if (sz_downloaded_end) { |
|
706 *sz_downloaded_end = 0; |
|
707 } |
|
708 |
|
709 double progress = (double)download->downloaded_bytes / (double)download->total_bytes; |
|
710 ui_set(download->progress, progress); |
|
711 |
|
712 cxmutstr label1; |
|
713 if (download->total_files + download->total_directories > 1) { |
|
714 label1 = cx_asprintf( |
|
715 "%s/%s %zu/%zu files", |
|
716 sz_downloaded, |
|
717 sz_total, |
|
718 download->downloaded_files+download->downloaded_directories, |
|
719 download->total_files+download->total_directories); |
|
720 } else { |
|
721 label1 = cx_asprintf( |
|
722 "%s/%s", |
|
723 sz_downloaded, |
|
724 sz_total); |
|
725 } |
|
726 ui_set(download->label_top_left, label1.ptr); |
|
727 |
|
728 free(sz_total); |
|
729 free(label1.ptr); |
|
730 |
|
731 |
|
732 return 0; |
|
733 } |
|
734 |
697 // dav download file |
735 // dav download file |
698 typedef struct DDFile { |
736 typedef struct DDFile { |
699 DavFileDownload *download; |
737 DavFileDownload *download; |
700 DavResource *res; |
738 char *path; |
701 char *to; |
739 char *to; |
702 } DDFile; |
740 } DDFile; |
703 |
741 |
704 static int qthr_download_resource(void *data) { |
742 static int qthr_download_resource(void *data) { |
705 DDFile *file = data; |
743 DDFile *file = data; |
707 FILE *f = fopen(file->to, "wb"); |
745 FILE *f = fopen(file->to, "wb"); |
708 if (!f) { |
746 if (!f) { |
709 return 0; |
747 return 0; |
710 } |
748 } |
711 |
749 |
712 dav_get_content(file->res, f, (dav_write_func)fwrite); |
750 DavResource *res = dav_resource_new(file->download->download_sn, file->path); |
|
751 dav_get_content(res, f, (dav_write_func)fwrite); |
|
752 |
|
753 file->download->downloaded_bytes += res->contentlength; |
|
754 file->download->downloaded_files++; |
|
755 |
|
756 dav_resource_free(res); |
713 |
757 |
714 fclose(f); |
758 fclose(f); |
715 } |
759 |
|
760 free(file->path); |
|
761 free(file->to); |
|
762 free(file); |
|
763 } |
|
764 |
|
765 |
|
766 typedef struct DlStackElm { |
|
767 DavResource *resource; |
|
768 char *sub_path; |
|
769 } DlStackElm; |
716 |
770 |
717 static int jobthr_download_scan(void *data) { |
771 static int jobthr_download_scan(void *data) { |
718 DavFileDownload *download = data; |
772 DavFileDownload *download = data; |
719 DavBrowser *browser = download->browser; |
773 DavBrowser *browser = download->browser; |
720 |
774 |
724 if (S_ISDIR(s.st_mode)) { |
778 if (S_ISDIR(s.st_mode)) { |
725 download->isdirectory = TRUE; |
779 download->isdirectory = TRUE; |
726 } |
780 } |
727 } |
781 } |
728 |
782 |
|
783 CxList *stack = cxLinkedListCreateSimple(sizeof(DlStackElm)); |
|
784 |
729 // add selected files to the download queue |
785 // add selected files to the download queue |
730 DavResource *res = download->reslist; |
786 DavResource *res = download->reslist; |
731 while (res) { |
787 while (res) { |
732 DDFile *file = malloc(sizeof(DDFile)); |
788 DlStackElm elm; |
733 file->download = download; |
789 elm.resource = res; |
734 file->res = res; |
790 elm.sub_path = strdup(res->name); |
735 if (download->isdirectory) { |
791 cxListAdd(stack, &elm); |
736 file->to = util_concat_path(download->local_path, res->name); |
792 |
|
793 res = res->next; |
|
794 } |
|
795 |
|
796 while (stack->size > 0) { |
|
797 DlStackElm *elm = cxListAt(stack, 0); |
|
798 DavResource *res = elm->resource; |
|
799 char *sub_path = elm->sub_path; |
|
800 cxListRemove(stack, 0); |
|
801 |
|
802 if (res->iscollection) { |
|
803 if (dav_load(res)) { |
|
804 // TODO: handle error |
|
805 continue; |
|
806 } |
|
807 |
|
808 download->total_directories++; |
|
809 |
|
810 // update ui |
|
811 //ui_call_mainthread(uithr_download_update_progress, download); |
|
812 |
|
813 char *path = util_concat_path(download->local_path, sub_path); |
|
814 int err = sys_mkdir(path); |
|
815 free(path); |
|
816 if (err) { |
|
817 // TODO: handle error |
|
818 } |
|
819 |
|
820 DavResource *child = res->children; |
|
821 while (child) { |
|
822 char *child_path = util_concat_path(sub_path, child->name); |
|
823 DlStackElm childelm; |
|
824 childelm.resource = child; |
|
825 childelm.sub_path = child_path; |
|
826 cxListAdd(stack, &childelm); |
|
827 |
|
828 child = child->next; |
|
829 } |
737 } else { |
830 } else { |
738 file->to = strdup(download->local_path); |
831 // add the file to the download queue |
739 } |
832 DDFile *file = malloc(sizeof(DDFile)); |
740 |
833 file->download = download; |
741 ui_threadpool_job(download->queue, download->ui, qthr_download_resource, file, NULL, NULL); |
834 file->path = strdup(res->path); |
742 |
835 if (download->isdirectory) { |
743 res = res->next; |
836 file->to = util_concat_path(download->local_path, sub_path); |
744 } |
837 } else { |
|
838 file->to = strdup(download->local_path); |
|
839 } |
|
840 |
|
841 // stats |
|
842 download->total_files++; |
|
843 download->total_bytes += res->contentlength; |
|
844 |
|
845 // update ui |
|
846 //ui_call_mainthread(uithr_download_update_progress, download); |
|
847 |
|
848 ui_threadpool_job(download->queue, download->ui, qthr_download_resource, file, NULL, NULL); |
|
849 } |
|
850 } |
|
851 |
|
852 cxListDestroy(stack); |
745 } |
853 } |
746 |
854 |
747 static void uithr_download_scan_finished(UiEvent *event, void *data) { |
855 static void uithr_download_scan_finished(UiEvent *event, void *data) { |
748 |
856 |
749 } |
857 } |
755 |
863 |
756 void davbrowser_download(UiObject *ui, DavBrowser *browser, DavResource *reslist, const char *local_path) { |
864 void davbrowser_download(UiObject *ui, DavBrowser *browser, DavResource *reslist, const char *local_path) { |
757 DavFileDownload *download = malloc(sizeof(DavFileDownload)); |
865 DavFileDownload *download = malloc(sizeof(DavFileDownload)); |
758 memset(download, 0, sizeof(DavFileDownload)); |
866 memset(download, 0, sizeof(DavFileDownload)); |
759 |
867 |
|
868 download->ui = ui; |
760 download->browser = browser; |
869 download->browser = browser; |
761 download->sn = reslist->session; |
870 download->sn = reslist->session; |
|
871 download->download_sn = dav_session_clone(download->sn); |
762 download->reslist = reslist; |
872 download->reslist = reslist; |
763 download->local_path = strdup(local_path); |
873 download->local_path = strdup(local_path); |
764 |
874 |
765 download->queue = ui_threadpool_create(1); |
875 download->queue = ui_threadpool_create(1); |
766 |
876 |