diff --git a/src/slic3r/GUI/ImageGrid.cpp b/src/slic3r/GUI/ImageGrid.cpp index 02cd827cc..65fc04e52 100644 --- a/src/slic3r/GUI/ImageGrid.cpp +++ b/src/slic3r/GUI/ImageGrid.cpp @@ -259,7 +259,7 @@ std::pair Slic3r::GUI::ImageGrid::HitTest(wxPoint const &pt) if (!m_selecting) { wxRect hover_rect{0, m_content_rect.GetHeight() - 40, m_content_rect.GetWidth(), 40}; auto & file = m_file_sys->GetFile(index); - int btn = file.IsDownload() && file.progress >= 0 ? 3 : 2; + int btn = file.IsDownload() && file.DownloadProgress() >= 0 ? 3 : 2; if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) { btn = 3; hover_rect.y -= 64; @@ -598,21 +598,22 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind int states = 0; // Draw download progress if (file.IsDownload()) { - if (file.progress == -1) { + int progress = file.DownloadProgress(); + if (progress == -1) { secondAction = _L("Cancel"); nonHoverText = _L("Download waiting..."); - } else if (file.progress < 0) { + } else if (progress < 0) { secondAction = _L("Retry"); nonHoverText = _L("Download failed"); states = StateColor::Checked; - } else if (file.progress >= 100) { + } else if (progress >= 100) { secondAction = _L("Play"); thirdAction = _L("Open Folder"); nonHoverText = _L("Download finished"); } else { secondAction = _L("Cancel"); - nonHoverText = wxString::Format(_L("Downloading %d%%..."), file.progress); - thirdAction = wxString::Format(L"%d%%...", file.progress); + nonHoverText = wxString::Format(_L("Downloading %d%%..."), progress); + thirdAction = wxString::Format(L"%d%%...", progress); } } if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) { diff --git a/src/slic3r/GUI/MediaFilePanel.cpp b/src/slic3r/GUI/MediaFilePanel.cpp index 4310a1b83..717d1a741 100644 --- a/src/slic3r/GUI/MediaFilePanel.cpp +++ b/src/slic3r/GUI/MediaFilePanel.cpp @@ -500,7 +500,8 @@ void MediaFilePanel::doAction(size_t index, int action) Slic3r::PlateDataPtrs plate_data_list; Slic3r::Semver file_version; std::istringstream is(data); - if (!Slic3r::load_gcode_3mf_from_stream(is, &config, &model, &plate_data_list, &file_version)) { + if (!Slic3r::load_gcode_3mf_from_stream(is, &config, &model, &plate_data_list, &file_version) + || plate_data_list.empty()) { MessageDialog(this, _L("Failed to parse model infomations."), _L("Error"), wxOK).ShowModal(); @@ -523,8 +524,8 @@ void MediaFilePanel::doAction(size_t index, int action) } if (index != -1) { auto &file = fs->GetFile(index); - if (file.IsDownload() && file.progress >= -1) { - if (file.progress >= 100) { + if (file.IsDownload() && file.DownloadProgress() >= -1) { + if (!file.local_path.empty()) { if (!fs->DownloadCheckFile(index)) { MessageDialog(this, wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)), @@ -549,8 +550,8 @@ void MediaFilePanel::doAction(size_t index, int action) } else if (action == 2) { if (index != -1) { auto &file = fs->GetFile(index); - if (file.IsDownload() && file.progress >= -1) { - if (file.progress >= 100) { + if (file.IsDownload() && file.DownloadProgress() >= -1) { + if (!file.local_path.empty()) { if (!fs->DownloadCheckFile(index)) { MessageDialog(this, wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)), @@ -558,12 +559,7 @@ void MediaFilePanel::doAction(size_t index, int action) Refresh(); return; } -#ifdef __WIN32__ - wxExecute(L"explorer.exe /select," + from_u8(file.local_path)); -#elif __APPLE__ - openFolderForFile(from_u8(file.local_path)); -#else -#endif + desktop_open_any_folder(file.local_path); } else if (fs->GetFileType() == PrinterFileSystem::F_MODEL) { fs->DownloadCancel(index); } diff --git a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp index 974d776ab..afee649c6 100644 --- a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp +++ b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp @@ -163,7 +163,7 @@ void PrinterFileSystem::ListAllFiles() iter1->flags = iter2->flags; if (!iter1->thumbnail.IsOk()) iter1->flags &= ~FF_THUMNAIL; - iter1->progress = iter2->progress; + iter1->download = iter2->download; iter1->local_path = iter2->local_path; iter1->metadata = iter2->metadata; } @@ -173,10 +173,11 @@ void PrinterFileSystem::ListAllFiles() } BuildGroups(); UpdateGroupSelect(); - m_task_flags = 0; m_status = Status::ListReady; SendChangedEvent(EVT_STATUS_CHANGED, m_status); SendChangedEvent(EVT_FILE_CHANGED); + if ((m_task_flags & FF_DOWNLOAD) == 0) + DownloadNextFile(); return 0; }); } @@ -205,6 +206,16 @@ void PrinterFileSystem::DeleteFiles(size_t index) DeleteFilesContinue(); } +struct PrinterFileSystem::Download : Progress +{ + size_t index; + std::string name; + std::string path; + std::string local_path; + boost::filesystem::ofstream ofs; + boost::uuids::detail::md5 boost_md5; +}; + void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path) { if (index == (size_t) -1) { @@ -212,10 +223,12 @@ void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path) for (size_t i = 0; i < m_file_list.size(); ++i) { auto &file = m_file_list[i]; if ((file.flags & FF_SELECT) == 0) continue; - if ((file.flags & FF_DOWNLOAD) != 0 && file.progress >= 0) continue; + if ((file.flags & FF_DOWNLOAD) != 0 && file.DownloadProgress() >= -1) continue; file.flags |= FF_DOWNLOAD; - file.progress = -1; - file.local_path = (boost::filesystem::path(path) / file.name).string(); + std::shared_ptr download(new Download); + download->progress = -1; + download->local_path = (boost::filesystem::path(path) / file.name).string(); + file.download = download; ++n; } if (n == 0) return; @@ -223,11 +236,13 @@ void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path) if (index >= m_file_list.size()) return; auto &file = m_file_list[index]; - if ((file.flags & FF_DOWNLOAD) != 0 && file.progress >= 0) + if ((file.flags & FF_DOWNLOAD) != 0 && file.DownloadProgress() >= -1) return; file.flags |= FF_DOWNLOAD; - file.progress = -1; - file.local_path = (boost::filesystem::path(path) / file.name).string(); + std::shared_ptr download(new Download); + download->progress = -1; + download->local_path = (boost::filesystem::path(path) / file.name).string(); + file.download = download; } if ((m_task_flags & FF_DOWNLOAD) == 0) DownloadNextFile(); @@ -237,12 +252,11 @@ void PrinterFileSystem::DownloadCheckFiles(std::string const &path) { for (size_t i = 0; i < m_file_list.size(); ++i) { auto &file = m_file_list[i]; - if ((file.flags & FF_DOWNLOAD) != 0 && file.progress >= 0) continue; + if ((file.flags & FF_DOWNLOAD) != 0 && file.download) continue; auto path2 = boost::filesystem::path(path) / file.name; boost::system::error_code ec; if (boost::filesystem::file_size(path2, ec) == file.size) { file.flags |= FF_DOWNLOAD; - file.progress = 100; file.local_path = path2.string(); } } @@ -252,10 +266,10 @@ bool PrinterFileSystem::DownloadCheckFile(size_t index) { if (index >= m_file_list.size()) return false; auto &file = m_file_list[index]; - if ((file.flags & FF_DOWNLOAD) == 0) return false; + if ((file.flags & FF_DOWNLOAD) == 0 || file.local_path.empty()) + return false; if (!boost::filesystem::exists(file.local_path)) { file.flags &= ~FF_DOWNLOAD; - file.progress = 0; file.local_path.clear(); SendChangedEvent(EVT_DOWNLOAD, index, file.local_path); return false; @@ -268,11 +282,11 @@ void PrinterFileSystem::DownloadCancel(size_t index) if (index == (size_t) -1) return; if (index >= m_file_list.size()) return; auto &file = m_file_list[index]; - if ((file.flags & FF_DOWNLOAD) == 0) return; - if (file.progress >= 0) + if ((file.flags & FF_DOWNLOAD) == 0 || !file.download) return; + if (file.DownloadProgress() >= 0) CancelRequest(m_download_seq); else - file.flags &= ~FF_DOWNLOAD; + file.flags &= ~FF_DOWNLOAD, file.download.reset(); } void PrinterFileSystem::FetchModel(size_t index, std::function callback) @@ -296,20 +310,22 @@ void PrinterFileSystem::FetchModel(size_t index, std::function( + std::shared_ptr file_data(new std::string()); + m_fetch_model_seq = SendRequest( SUB_FILE, req, - [](json const &resp, File &file, unsigned char const *data) -> int { + [file_data](json const &resp, Void &, unsigned char const *data) -> int { // in work thread, continue recv // receive data boost::uint32_t size = resp["size"]; if (size > 0) { - file.local_path = std::string((char *) data, size); + *file_data += std::string((char *) data, size); } return 0; }, - [this, callback](int result, File const &file) { + [this, file_data, callback](int result, Void const &) { + if (result == CONTINUE) return; m_task_flags &= ~FF_FETCH_MODEL; - callback(result, file.local_path); + callback(result, *file_data); }); } @@ -326,6 +342,8 @@ size_t PrinterFileSystem::GetCount() const return m_group_mode == G_YEAR ? m_group_year.size() : m_group_month.size(); } +int PrinterFileSystem::File::DownloadProgress() const { return download ? download->progress : !local_path.empty() ? 100 : -2; } + std::string PrinterFileSystem::File::Title() const { return Metadata("Title", name); } std::string PrinterFileSystem::File::Metadata(std::string const &key, std::string const &dflt) const @@ -558,12 +576,13 @@ void PrinterFileSystem::DeleteFilesContinue() req["paths"] = arr; } m_task_flags |= FF_DELETED; + auto type = std::make_pair(m_file_type, m_file_storage); SendRequest( FILE_DEL, req, nullptr, - [indexes, names = paths.empty() ? names : paths, bypath = !paths.empty(), this](int, Void const &) { + [indexes, type, names = paths.empty() ? names : paths, bypath = !paths.empty(), this](int, Void const &) { // TODO: for (size_t i = indexes.size() - 1; i != size_t(-1); --i) - FileRemoved(indexes[i], names[i], bypath); + FileRemoved(type, indexes[i], names[i], bypath); SendChangedEvent(EVT_FILE_CHANGED, indexes.size()); DeleteFilesContinue(); }); @@ -573,7 +592,7 @@ void PrinterFileSystem::DownloadNextFile() { size_t index = size_t(-1); for (size_t i = 0; i < m_file_list.size(); ++i) { - if ((m_file_list[i].flags & FF_DOWNLOAD) != 0 && m_file_list[i].progress == -1) { + if (m_file_list[i].IsDownload() && m_file_list[i].DownloadProgress() == -1) { index = i; break; } @@ -581,43 +600,38 @@ void PrinterFileSystem::DownloadNextFile() m_task_flags &= ~FF_DOWNLOAD; if (index >= m_file_list.size()) return; + auto &file = m_file_list[index]; json req; - if (m_file_list[index].path.empty()) - req["file"] = m_file_list[index].name; + if (file.path.empty()) + req["file"] = file.name; else - req["path"] = m_file_list[index].path; - m_file_list[index].progress = 0; + req["path"] = file.path; SendChangedEvent(EVT_DOWNLOAD, index, m_file_list[index].name); - struct Download - { - size_t index; - std::string name; - std::string path; - std::string local_path; - boost::filesystem::ofstream ofs; - boost::uuids::detail::md5 boost_md5; - }; - std::shared_ptr download(new Download); + std::shared_ptr download(m_file_list[index].download); download->index = index; - download->name = m_file_list[index].name; - download->path = m_file_list[index].path; - download->local_path = m_file_list[index].local_path; + download->name = file.name; + download->path = file.path; m_task_flags |= FF_DOWNLOAD; m_download_seq = SendRequest( FILE_DOWNLOAD, req, [download](json const &resp, Progress &prog, unsigned char const *data) -> int { // in work thread, continue recv - size_t size = resp["size"]; + size_t size = resp.value("size", 0); prog.size = resp["offset"]; prog.total = resp["total"]; if (prog.size == 0) { download->ofs.open(download->local_path, std::ios::binary); if (!download->ofs) return FILE_OPEN_ERR; } + if (download->total && (download->size != prog.size || download->total != prog.total)) { + wxLogWarning("PrinterFileSystem::DownloadNextFile data error: %d != %d\n", download->size, download->size); + } // receive data download->ofs.write((char const *) data, size); download->boost_md5.process_bytes(data, size); prog.size += size; + download->total = prog.total; + download->size = prog.size; if (prog.size < prog.total) { return 0; } download->ofs.close(); int result = 0; @@ -645,19 +659,28 @@ void PrinterFileSystem::DownloadNextFile() } return result; }, - [this, download](int result, Progress const &data) { - if (download->index != size_t(-1)) - download->index = FindFile(download->index, download->path.empty() ? download->name : download->path, !download->path.empty()); + [this, download, type = std::make_pair(m_file_type, m_file_storage)](int result, Progress const &data) { + int progress = data.total ? data.size * 100 / data.total : 0; + if (result == CONTINUE) { + if (download->progress == progress) + return; + } + download->progress = progress; if (download->index != size_t(-1)) { - int progress = data.size * 100 / data.total; - auto & file = m_file_list[download->index]; - if (result == ERROR_CANCEL) - progress = -1, file.flags &= ~FF_DOWNLOAD; - else if (result != CONTINUE && result != SUCCESS) - progress = -2; - if (file.progress != progress) { - file.progress = progress; - SendChangedEvent(EVT_DOWNLOAD, download->index, file.local_path, result); + auto file_index = FindFile(type, download->index, download->path.empty() ? download->name : download->path, !download->path.empty()); + download->index = file_index.second; + if (download->index != size_t(-1)) { + auto &file = file_index.first[download->index]; + if (result == CONTINUE) + ; + else if (result == SUCCESS) + file.download.reset(), file.local_path = download->local_path; + else if (result == ERROR_CANCEL) + file.download.reset(), file.flags &= ~FF_DOWNLOAD; + else // FAILED + file.download.reset(); + if (&file_index.first == &m_file_list) + SendChangedEvent(EVT_DOWNLOAD, download->index, file.local_path, result); } } if (result != CONTINUE) DownloadNextFile(); @@ -875,51 +898,56 @@ void PrinterFileSystem::UpdateFocusThumbnail2(std::shared_ptr> }); } -size_t PrinterFileSystem::FindFile(size_t index, std::string const &name, bool by_path) +std::pair PrinterFileSystem::FindFile(std::pair type, size_t index, std::string const &name, bool by_path) { - if (index >= m_file_list.size() || (by_path ? m_file_list[index].path : m_file_list[index].name) != name) { - auto iter = std::find_if(m_file_list.begin(), m_file_list.end(), + FileList & file_list = type == std::make_pair(m_file_type, m_file_storage) ? + m_file_list : + m_file_list_cache[type]; + if (index >= file_list.size() || (by_path ? file_list[index].path : file_list[index].name) != name) { + auto iter = std::find_if(m_file_list.begin(), file_list.end(), [name, by_path](File &f) { return (by_path ? f.path : f.name) == name; }); - if (iter == m_file_list.end()) return -1; + if (iter == m_file_list.end()) return {file_list, -1}; index = std::distance(m_file_list.begin(), iter); } - return index; + return {file_list, index}; } -void PrinterFileSystem::FileRemoved(size_t index, std::string const &name, bool by_path) +void PrinterFileSystem::FileRemoved(std::pair type, size_t index, std::string const &name, bool by_path) { - index = FindFile(index, name, by_path); - if (index == size_t(-1)) + auto file_index = FindFile(type, index, name, by_path); + if (file_index.second == size_t(-1)) return; - auto removeFromGroup = [](std::vector &group, size_t index, int total) { - for (auto iter = group.begin(); iter != group.end(); ++iter) { - size_t index2 = -1; - if (*iter < index) continue; - if (*iter == index) { - auto iter2 = iter + 1; - if (iter2 == group.end() ? index == total - 1 : *iter2 == index + 1) { - index2 = std::distance(group.begin(), iter); + if (&file_index.first == &m_file_list) { + auto removeFromGroup = [](std::vector &group, size_t index, int total) { + for (auto iter = group.begin(); iter != group.end(); ++iter) { + size_t index2 = -1; + if (*iter < index) continue; + if (*iter == index) { + auto iter2 = iter + 1; + if (iter2 == group.end() ? index == total - 1 : *iter2 == index + 1) { + index2 = std::distance(group.begin(), iter); + } + ++iter; } - ++iter; + for (; iter != group.end(); ++iter) { + --*iter; + } + return index2; } - for (; iter != group.end(); ++iter) { - --*iter; + return size_t(-1); + }; + size_t index2 = removeFromGroup(m_group_month, index, m_file_list.size()); + if (index2 < m_group_month.size()) { + int index3 = removeFromGroup(m_group_year, index, m_group_month.size()); + if (index3 < m_group_year.size()) { + m_group_year.erase(m_group_year.begin() + index3); + if (m_group_mode == G_YEAR) + m_group_flags.erase(m_group_flags.begin() + index2); } - return index2; - } - return size_t(-1); - }; - size_t index2 = removeFromGroup(m_group_month, index, m_file_list.size()); - if (index2 < m_group_month.size()) { - int index3 = removeFromGroup(m_group_year, index, m_group_month.size()); - if (index3 < m_group_year.size()) { - m_group_year.erase(m_group_year.begin() + index3); - if (m_group_mode == G_YEAR) + m_group_month.erase(m_group_month.begin() + index2); + if (m_group_mode == G_MONTH) m_group_flags.erase(m_group_flags.begin() + index2); } - m_group_month.erase(m_group_month.begin() + index2); - if (m_group_mode == G_MONTH) - m_group_flags.erase(m_group_flags.begin() + index2); } m_file_list.erase(m_file_list.begin() + index); } @@ -996,12 +1024,13 @@ void PrinterFileSystem::CancelRequests(std::vector const &seqs) for (auto seq : seqs) arr.push_back(seq); req["tasks"] = arr; - SendRequest(TASK_CANCEL, req, [this](int result, json const &resp, unsigned char const *) { - if (result != 0) return; + SendRequest(TASK_CANCEL, req, [this](int result, json const &resp, unsigned char const *) -> int { + if (result != 0) return result; json tasks = resp["tasks"]; std::vector seqs; for (auto &f : tasks) seqs.push_back(f); CancelRequests2(seqs); + return 0; }); } @@ -1118,7 +1147,12 @@ void PrinterFileSystem::HandleResponse(boost::unique_lock &l, Bamb if (size_t(seq) >= m_callbacks.size()) return; auto c = m_callbacks[seq]; if (c == nullptr) return; + seq += m_sequence; + l.unlock(); + result = c(result, resp, json_end); + l.lock(); if (result != CONTINUE) { + seq -= m_sequence; m_callbacks[seq] = callback_t2(); if (seq == 0) { while (!m_callbacks.empty() && m_callbacks.front() == nullptr) { @@ -1127,9 +1161,6 @@ void PrinterFileSystem::HandleResponse(boost::unique_lock &l, Bamb } } } - l.unlock(); - c(result, resp, json_end); - l.lock(); } } diff --git a/src/slic3r/GUI/Printer/PrinterFileSystem.h b/src/slic3r/GUI/Printer/PrinterFileSystem.h index 30c2ae73e..592cfc5b7 100644 --- a/src/slic3r/GUI/Printer/PrinterFileSystem.h +++ b/src/slic3r/GUI/Printer/PrinterFileSystem.h @@ -94,6 +94,15 @@ public: FF_THUMNAIL_RETRY = 0x100, // Thumbnail need retry }; + struct Progress + { + wxInt64 size = 0; + wxInt64 total = 0; + int progress = 0; + }; + + struct Download; + struct File { std::string name; @@ -102,12 +111,13 @@ public: boost::uint64_t size = 0; int flags = 0; wxBitmap thumbnail; - int progress = -1; // -1: waiting + std::shared_ptr download; std::string local_path; std::map metadata; bool IsSelect() const { return flags & FF_SELECT; } bool IsDownload() const { return flags & FF_DOWNLOAD; } + int DownloadProgress() const; std::string Title() const; std::string Metadata(std::string const &key, std::string const &dflt) const; @@ -118,12 +128,6 @@ public: typedef std::vector FileList; - struct Progress - { - wxInt64 size; - wxInt64 total; - }; - void ListAllFiles(); void DeleteFiles(size_t index); @@ -194,9 +198,9 @@ private: void UpdateFocusThumbnail2(std::shared_ptr> files, int type); - void FileRemoved(size_t index, std::string const &name, bool by_path); + void FileRemoved(std::pair type, size_t index, std::string const &name, bool by_path); - size_t FindFile(size_t index, std::string const &name, bool by_path); + std::pair FindFile(std::pair type, size_t index, std::string const &name, bool by_path); void SendChangedEvent(wxEventType type, size_t index = (size_t)-1, std::string const &str = {}, long extra = 0); @@ -207,12 +211,12 @@ private: typedef std::function callback_t; - typedef std::function callback_t2; + typedef std::function callback_t2; template boost::uint32_t SendRequest(int type, json const& req, Translator const& translator, Callback const& callback) { - auto c = [translator, callback, this](int result, json const &resp, unsigned char const *data) + auto c = [translator, callback, this](int result, json const &resp, unsigned char const *data) -> int { T t; if (result == 0 || result == CONTINUE) { @@ -225,6 +229,7 @@ private: } } PostCallback(callback, result, t); + return result; }; return SendRequest(type, req, c); } @@ -234,7 +239,7 @@ private: template void InstallNotify(int type, Translator const& translator, Applier const& applier) { - auto c = [translator, applier, this](int result, json const &resp, unsigned char const *data) + auto c = [translator, applier, this](int result, json const &resp, unsigned char const *data) -> int { T t; if (result == 0 || result == CONTINUE) { @@ -251,6 +256,7 @@ private: applier(t); }, 0, t); } + return result; }; InstallNotify(type, c); }