diff options
author | maxim_productengine <mnikolenko@productengine.com> | 2018-06-12 17:45:55 +0300 |
---|---|---|
committer | maxim_productengine <mnikolenko@productengine.com> | 2018-06-12 17:45:55 +0300 |
commit | 1a014427a257ba9ba78ab173fc5f2f9621d768a1 (patch) | |
tree | e295ba43795c47b8a59fe5a2f22b2b2c86023146 /indra/newview | |
parent | 1d3266910c5fbcc3c811cf82e0ebfbc7234f8df0 (diff) |
MAINT-8727 FIXED Saving snapshot will cause disconnect if you do not choose path in File picker quickly
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llfloatersnapshot.cpp | 10 | ||||
-rw-r--r-- | indra/newview/llfloatersnapshot.h | 4 | ||||
-rw-r--r-- | indra/newview/lloutfitgallery.cpp | 114 | ||||
-rw-r--r-- | indra/newview/lloutfitgallery.h | 1 | ||||
-rw-r--r-- | indra/newview/llpanelsnapshotlocal.cpp | 28 | ||||
-rw-r--r-- | indra/newview/llsnapshotlivepreview.cpp | 46 | ||||
-rw-r--r-- | indra/newview/llsnapshotlivepreview.h | 9 | ||||
-rw-r--r-- | indra/newview/llviewermenufile.cpp | 34 | ||||
-rw-r--r-- | indra/newview/llviewermenufile.h | 5 | ||||
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 119 | ||||
-rw-r--r-- | indra/newview/llviewerwindow.h | 8 |
11 files changed, 206 insertions, 172 deletions
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 156b2ba7b1..c08aaf3f50 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1309,17 +1309,15 @@ void LLFloaterSnapshot::saveTexture() previewp->saveTexture(); } -BOOL LLFloaterSnapshot::saveLocal() +void LLFloaterSnapshot::saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { LL_DEBUGS() << "saveLocal" << LL_ENDL; LLSnapshotLivePreview* previewp = getPreviewView(); - if (!previewp) + llassert(previewp != NULL); + if (previewp) { - llassert(previewp != NULL); - return FALSE; + previewp->saveLocal(success_cb, failure_cb); } - - return previewp->saveLocal(); } void LLFloaterSnapshotBase::postSave() diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 698273ac90..bcba14d63d 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -156,7 +156,9 @@ public: static LLFloaterSnapshot* getInstance(); static LLFloaterSnapshot* findInstance(); /*virtual*/ void saveTexture(); - BOOL saveLocal(); + + typedef boost::signals2::signal<void(void)> snapshot_saved_signal_t; + void saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); static void setAgentEmail(const std::string& email); BOOL isWaitingState(); diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index dc3b153da2..a90a29a731 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1166,72 +1166,72 @@ void LLOutfitGallery::refreshTextures(const LLUUID& category_id) void LLOutfitGallery::uploadPhoto(LLUUID outfit_id) { - outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); - if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull()) - { - return; - } + outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); + if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull()) + { + return; + } + (new LLFilePickerReplyThread(boost::bind(&LLOutfitGallery::uploadOutfitImage, this, _1, outfit_id), LLFilePicker::FFLOAD_IMAGE, false))->getFile(); +} - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) +void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filenames, LLUUID outfit_id) +{ + std::string filename = filenames[0]; + LLLocalBitmap* unit = new LLLocalBitmap(filename); + if (unit->getValid()) { - std::string filename = picker.getFirstFile(); - LLLocalBitmap* unit = new LLLocalBitmap(filename); - if (unit->getValid()) + std::string exten = gDirUtilp->getExtension(filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); + + LLImageDimensionsInfo image_info; + std::string image_load_error; + if (!image_info.load(filename, codec)) { - std::string exten = gDirUtilp->getExtension(filename); - U32 codec = LLImageBase::getCodecFromExtension(exten); + image_load_error = image_info.getLastError(); + } - LLImageDimensionsInfo image_info; - std::string image_load_error; - if (!image_info.load(filename, codec)) - { - image_load_error = image_info.getLastError(); - } + S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; + S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; - S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; - S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) + { + LLStringUtil::format_map_t args; + args["WIDTH"] = llformat("%d", max_width); + args["HEIGHT"] = llformat("%d", max_height); - if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) - { - LLStringUtil::format_map_t args; - args["WIDTH"] = llformat("%d", max_width); - args["HEIGHT"] = llformat("%d", max_height); + image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args); + } - image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args); - } + if (!image_load_error.empty()) + { + LLSD subst; + subst["REASON"] = image_load_error; + LLNotificationsUtil::add("OutfitPhotoLoadError", subst); + return; + } - if (!image_load_error.empty()) - { - LLSD subst; - subst["REASON"] = image_load_error; - LLNotificationsUtil::add("OutfitPhotoLoadError", subst); - return; - } + S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). + void *nruserdata = NULL; + nruserdata = (void *)&outfit_id; - S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). - void *nruserdata = NULL; - nruserdata = (void *)&outfit_id; - - LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id); - if (!outfit_cat) return; - updateSnapshotFolderObserver(); - checkRemovePhoto(outfit_id); - std::string upload_pending_name = outfit_id.asString(); - std::string upload_pending_desc = ""; - LLAssetStorage::LLStoreAssetCallback callback = NULL; - LLUUID photo_id = upload_new_resource(filename, // file - upload_pending_name, - upload_pending_desc, - 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, - LLFloaterPerms::getNextOwnerPerms("Uploads"), - LLFloaterPerms::getGroupPerms("Uploads"), - LLFloaterPerms::getEveryonePerms("Uploads"), - upload_pending_name, callback, expected_upload_cost, nruserdata); - mOutfitLinkPending = outfit_id; - } - delete unit; - } + LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id); + if (!outfit_cat) return; + updateSnapshotFolderObserver(); + checkRemovePhoto(outfit_id); + std::string upload_pending_name = outfit_id.asString(); + std::string upload_pending_desc = ""; + LLAssetStorage::LLStoreAssetCallback callback = NULL; + LLUUID photo_id = upload_new_resource(filename, // file + upload_pending_name, + upload_pending_desc, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms("Uploads"), + LLFloaterPerms::getGroupPerms("Uploads"), + LLFloaterPerms::getEveryonePerms("Uploads"), + upload_pending_name, callback, expected_upload_cost, nruserdata); + mOutfitLinkPending = outfit_id; + } + delete unit; } void LLOutfitGallery::linkPhotoToOutfit(LLUUID photo_id, LLUUID outfit_id) diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h index 383924a7d6..6dd8a6298f 100644 --- a/indra/newview/lloutfitgallery.h +++ b/indra/newview/lloutfitgallery.h @@ -130,6 +130,7 @@ protected: private: void loadPhotos(); void uploadPhoto(LLUUID outfit_id); + void uploadOutfitImage(const std::vector<std::string>& filenames, LLUUID outfit_id); void updateSnapshotFolderObserver(); LLUUID getPhotoAssetId(const LLUUID& outfit_id); LLUUID getDefaultPhoto(); diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 77378f8092..57c5915da2 100644 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -65,6 +65,9 @@ private: void onFormatComboCommit(LLUICtrl* ctrl); void onQualitySliderCommit(LLUICtrl* ctrl); void onSaveFlyoutCommit(LLUICtrl* ctrl); + + void LLPanelSnapshotLocal::onLocalSaved(); + void LLPanelSnapshotLocal::onLocalCanceled(); }; static LLPanelInjector<LLPanelSnapshotLocal> panel_class("llpanelsnapshotlocal"); @@ -164,19 +167,22 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl) LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance(); floater->notify(LLSD().with("set-working", true)); - BOOL saved = floater->saveLocal(); - if (saved) - { - mSnapshotFloater->postSave(); - floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local"))); - } - else - { - cancel(); - floater->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "local"))); - } + floater->saveLocal((boost::bind(&LLPanelSnapshotLocal::onLocalSaved, this)), (boost::bind(&LLPanelSnapshotLocal::onLocalCanceled, this))); +} + +void LLPanelSnapshotLocal::onLocalSaved() +{ + mSnapshotFloater->postSave(); + LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local"))); +} + +void LLPanelSnapshotLocal::onLocalCanceled() +{ + cancel(); + LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "local"))); } + LLSnapshotModel::ESnapshotType LLPanelSnapshotLocal::getSnapshotType() { return LLSnapshotModel::SNAPSHOT_LOCAL; diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index ee8b2d79c0..d0cff1464b 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -70,6 +70,7 @@ S32 BORDER_WIDTH = 6; const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512 std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList; +LLPointer<LLImageFormatted> LLSnapshotLivePreview::sSaveLocalImage = NULL; LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p) : LLView(p), @@ -131,6 +132,7 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview() // gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); sList.erase(this); + sSaveLocalImage = NULL; } void LLSnapshotLivePreview::setMaxImageSize(S32 size) @@ -1065,53 +1067,19 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) mDataSize = 0; } -BOOL LLSnapshotLivePreview::saveLocal() +void LLSnapshotLivePreview::saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { // Update mFormattedImage if necessary getFormattedImage(); // Save the formatted image - BOOL success = saveLocal(mFormattedImage); - - if(success) - { - gViewerWindow->playSnapshotAnimAndSound(); - } - return success; + saveLocal(mFormattedImage, success_cb, failure_cb); } //Check if failed due to insufficient memory -BOOL LLSnapshotLivePreview::saveLocal(LLPointer<LLImageFormatted> mFormattedImage) +void LLSnapshotLivePreview::saveLocal(LLPointer<LLImageFormatted> image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - BOOL insufficient_memory; - BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage, FALSE, insufficient_memory); + sSaveLocalImage = image; - if (insufficient_memory) - { - std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); - -#ifdef LL_WINDOWS - boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); -#else - boost::filesystem::path b_path(lastSnapshotDir); -#endif - boost::filesystem::space_info b_space = boost::filesystem::space(b_path); - if (b_space.free < mFormattedImage->getDataSize()) - { - LLSD args; - args["PATH"] = lastSnapshotDir; - - std::string needM_bytes_string; - LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (mFormattedImage->getDataSize()) >> 10); - args["NEED_MEMORY"] = needM_bytes_string; - - std::string freeM_bytes_string; - LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10); - args["FREE_MEMORY"] = freeM_bytes_string; - - LLNotificationsUtil::add("SnapshotToComputerFailed", args); - return false; - } - } - return success; + gViewerWindow->saveImageNumbered(sSaveLocalImage, FALSE, success_cb, failure_cb); } diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 4ea8d25a5a..683cd016d8 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -40,8 +40,9 @@ class LLSnapshotLivePreview : public LLView { LOG_CLASS(LLSnapshotLivePreview); public: + typedef boost::signals2::signal<void(void)> snapshot_saved_signal_t; - static BOOL saveLocal(LLPointer<LLImageFormatted>); + static void saveLocal(LLPointer<LLImageFormatted> image, const snapshot_saved_signal_t::slot_type& success_cb = snapshot_saved_signal_t(), const snapshot_saved_signal_t::slot_type& failure_cb = snapshot_saved_signal_t()); struct Params : public LLInitParam::Block<Params, LLView::Params> { Params() @@ -101,7 +102,7 @@ public: std::string getFilter() const { return mFilterName; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); void saveTexture(BOOL outfit_snapshot = FALSE, std::string name = ""); - BOOL saveLocal(); + void saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); LLPointer<LLImageFormatted> getFormattedImage(); LLPointer<LLImageRaw> getEncodedImage(); @@ -170,7 +171,9 @@ private: LLQuaternion mCameraRot; BOOL mSnapshotActive; LLSnapshotModel::ESnapshotLayerType mSnapshotBufferType; - std::string mFilterName; + std::string mFilterName; + + static LLPointer<LLImageFormatted> sSaveLocalImage; public: static std::set<LLSnapshotLivePreview*> sList; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index dc05d98228..cf1c442ce9 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -203,38 +203,55 @@ void LLFilePickerThread::clearDead() } } -LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple) +LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb) : LLFilePickerThread(filter, get_multiple), mLoadFilter(filter), mSaveFilter(LLFilePicker::FFSAVE_ALL), - mFilePickedSignal(NULL) + mFilePickedSignal(NULL), + mFailureSignal(NULL) { mFilePickedSignal = new file_picked_signal_t(); mFilePickedSignal->connect(cb); + + mFailureSignal = new file_picked_signal_t(); + mFailureSignal->connect(failure_cb); } -LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name) +LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb) : LLFilePickerThread(filter, proposed_name), mLoadFilter(LLFilePicker::FFLOAD_ALL), mSaveFilter(filter), - mFilePickedSignal(NULL) + mFilePickedSignal(NULL), + mFailureSignal(NULL) { mFilePickedSignal = new file_picked_signal_t(); mFilePickedSignal->connect(cb); + + mFailureSignal = new file_picked_signal_t(); + mFailureSignal->connect(failure_cb); } LLFilePickerReplyThread::~LLFilePickerReplyThread() { delete mFilePickedSignal; + delete mFailureSignal; } void LLFilePickerReplyThread::notify(const std::vector<std::string>& filenames) { - if (filenames.empty()) return; - - if (mFilePickedSignal) + if (filenames.empty()) + { + if (mFailureSignal) + { + (*mFailureSignal)(filenames, mLoadFilter, mSaveFilter); + } + } + else { - (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); + if (mFilePickedSignal) + { + (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); + } } } @@ -592,7 +609,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE)) { - gViewerWindow->playSnapshotAnimAndSound(); LLPointer<LLImageFormatted> formatted; LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); switch (fmt) diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 15bbdd1e2d..35f86f606b 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -113,8 +113,8 @@ public: typedef boost::signals2::signal<void(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)> file_picked_signal_t; - LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple); - LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name); + LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); + LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); ~LLFilePickerReplyThread(); virtual void notify(const std::vector<std::string>& filenames); @@ -123,6 +123,7 @@ private: LLFilePicker::ELoadFilter mLoadFilter; LLFilePicker::ESaveFilter mSaveFilter; file_picked_signal_t* mFilePickedSignal; + file_picked_signal_t* mFailureSignal; }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f394d6913f..846b902260 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -193,6 +193,7 @@ #include "llviewerdisplay.h" #include "llspatialpartition.h" #include "llviewerjoystick.h" +#include "llviewermenufile.h" // LLFilePickerReplyThread #include "llviewernetwork.h" #include "llpostprocess.h" #include "llfloaterimnearbychat.h" @@ -4365,77 +4366,101 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d } // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory) +void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - insufficient_memory = FALSE; - if (!image) { LL_WARNS() << "No image to save" << LL_ENDL; - return FALSE; + return; } - - LLFilePicker::ESaveFilter pick_type; std::string extension("." + image->getExtension()); - if (extension == ".j2c") - pick_type = LLFilePicker::FFSAVE_J2C; - else if (extension == ".bmp") - pick_type = LLFilePicker::FFSAVE_BMP; - else if (extension == ".jpg") - pick_type = LLFilePicker::FFSAVE_JPEG; - else if (extension == ".png") - pick_type = LLFilePicker::FFSAVE_PNG; - else if (extension == ".tga") - pick_type = LLFilePicker::FFSAVE_TGA; - else - pick_type = LLFilePicker::FFSAVE_ALL; // ??? - - BOOL is_snapshot_name_loc_set = isSnapshotLocSet(); - + LLImageFormatted* formatted_image = image; // Get a base file location if needed. if (force_picker || !isSnapshotLocSet()) { - std::string proposed_name( sSnapshotBaseName ); + std::string proposed_name(sSnapshotBaseName); // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. + LLFilePicker::ESaveFilter pick_type; + + if (extension == ".j2c") + pick_type = LLFilePicker::FFSAVE_J2C; + else if (extension == ".bmp") + pick_type = LLFilePicker::FFSAVE_BMP; + else if (extension == ".jpg") + pick_type = LLFilePicker::FFSAVE_JPEG; + else if (extension == ".png") + pick_type = LLFilePicker::FFSAVE_PNG; + else if (extension == ".tga") + pick_type = LLFilePicker::FFSAVE_TGA; + else + pick_type = LLFilePicker::FFSAVE_ALL; - // pick a directory in which to save - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getSaveFile(pick_type, proposed_name)) - { - // Clicked cancel - return FALSE; - } + (new LLFilePickerReplyThread(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, + boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)))->getFile(); + } + else + { + saveImageLocal(formatted_image, success_cb, failure_cb); + } +} - // Copy the directory + file name - std::string filepath = picker.getFirstFile(); +void LLViewerWindow::onDirectorySelected(const std::vector<std::string>& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) +{ + // Copy the directory + file name + std::string filepath = filenames[0]; - gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); - gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); - } + gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); + gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); + saveImageLocal(image, success_cb, failure_cb); +} - std::string snapshot_dir = sSnapshotDir; - if(snapshot_dir.empty()) +void LLViewerWindow::onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb) +{ + failure_cb(); +} + + +void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) +{ + std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); + if (lastSnapshotDir.empty()) { - return FALSE; + failure_cb(); + return; } // Check if there is enough free space to save snapshot #ifdef LL_WINDOWS - boost::filesystem::space_info b_space = boost::filesystem::space(utf8str_to_utf16str(snapshot_dir)); + boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); #else - boost::filesystem::space_info b_space = boost::filesystem::space(snapshot_dir); + boost::filesystem::path b_path(lastSnapshotDir); #endif + boost::filesystem::space_info b_space = boost::filesystem::space(b_path); if (b_space.free < image->getDataSize()) { - insufficient_memory = TRUE; - return FALSE; + LLSD args; + args["PATH"] = lastSnapshotDir; + + std::string needM_bytes_string; + LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (image->getDataSize()) >> 10); + args["NEED_MEMORY"] = needM_bytes_string; + + std::string freeM_bytes_string; + LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10); + args["FREE_MEMORY"] = freeM_bytes_string; + + LLNotificationsUtil::add("SnapshotToComputerFailed", args); + + failure_cb(); } + // Look for an unused file name + BOOL is_snapshot_name_loc_set = isSnapshotLocSet(); std::string filepath; S32 i = 1; S32 err = 0; - + std::string extension("." + image->getExtension()); do { filepath = sSnapshotDir; @@ -4457,7 +4482,15 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picke && is_snapshot_name_loc_set); // Or stop if we are rewriting. LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; - return image->save(filepath); + if (image->save(filepath)) + { + playSnapshotAnimAndSound(); + success_cb(); + } + else + { + failure_cb(); + } } void LLViewerWindow::resetSnapshotLoc() diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index c01921641c..d8d420e6be 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -352,7 +352,13 @@ public: BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type); BOOL isSnapshotLocSet() const; void resetSnapshotLoc() const; - BOOL saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory); + + typedef boost::signals2::signal<void(void)> snapshot_saved_signal_t; + + void saveImageNumbered(LLImageFormatted *image, BOOL force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void onDirectorySelected(const std::vector<std::string>& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb); // Reset the directory where snapshots are saved. // Client will open directory picker on next snapshot save. |