llpreviewnotecard.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llpreviewnotecard.h"
00035 
00036 #include "llinventory.h"
00037 
00038 #include "llagent.h"
00039 #include "llassetuploadresponders.h"
00040 #include "llviewerwindow.h"
00041 #include "llbutton.h"
00042 #include "llinventorymodel.h"
00043 #include "lllineeditor.h"
00044 #include "llnotify.h"
00045 #include "llresmgr.h"
00046 #include "roles_constants.h"
00047 #include "llscrollbar.h"
00048 #include "llselectmgr.h"
00049 #include "llviewertexteditor.h"
00050 #include "llvfile.h"
00051 #include "llviewerinventory.h"
00052 #include "llviewerobject.h"
00053 #include "llviewerobjectlist.h"
00054 #include "llviewerregion.h"
00055 #include "lldir.h"
00056 //#include "llfloaterchat.h"
00057 #include "llviewerstats.h"
00058 #include "viewer.h"             // app_abort_quit()
00059 #include "lllineeditor.h"
00060 #include "llvieweruictrlfactory.h"
00061 
00065 
00066 const S32 PREVIEW_MIN_WIDTH =
00067         2 * PREVIEW_BORDER +
00068         2 * PREVIEW_BUTTON_WIDTH + 
00069         PREVIEW_PAD + RESIZE_HANDLE_WIDTH +
00070         PREVIEW_PAD;
00071 const S32 PREVIEW_MIN_HEIGHT = 
00072         2 * PREVIEW_BORDER +
00073         3*(20 + PREVIEW_PAD) +
00074         2 * SCROLLBAR_SIZE + 128;
00075 
00079 
00080 // Default constructor
00081 LLPreviewNotecard::LLPreviewNotecard(const std::string& name,
00082                                                                          const LLRect& rect,
00083                                                                          const std::string& title,
00084                                                                          const LLUUID& item_id, 
00085                                                                          const LLUUID& object_id,
00086                                                                          const LLUUID& asset_id,
00087                                                                          BOOL show_keep_discard,
00088                                                                          LLPointer<LLViewerInventoryItem> inv_item) :
00089         LLPreview(name, rect, title, item_id, object_id, TRUE,
00090                           PREVIEW_MIN_WIDTH,
00091                           PREVIEW_MIN_HEIGHT,
00092                           inv_item),
00093         mAssetID( asset_id ),
00094         mNotecardItemID(item_id),
00095         mObjectID(object_id)
00096 {
00097         LLRect curRect = rect;
00098 
00099         if (show_keep_discard)
00100         {
00101                 gUICtrlFactory->buildFloater(this,"floater_preview_notecard_keep_discard.xml");
00102                 childSetAction("Keep",onKeepBtn,this);
00103                 childSetAction("Discard",onDiscardBtn,this);
00104         }
00105         else
00106         {
00107                 gUICtrlFactory->buildFloater(this,"floater_preview_notecard.xml");
00108                 childSetAction("Save",onClickSave,this);
00109                 
00110                 if( mAssetID.isNull() )
00111                 {
00112                         const LLInventoryItem* item = getItem();
00113                         if( item )
00114                         {
00115                                 mAssetID = item->getAssetUUID();
00116                         }
00117                 }
00118         }       
00119 
00120         // only assert shape if not hosted in a multifloater
00121         if (!getHost())
00122         {
00123                 reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
00124                 setRect(curRect);
00125         }
00126                         
00127         childSetVisible("lock", FALSE); 
00128         
00129         const LLInventoryItem* item = getItem();
00130         
00131         childSetCommitCallback("desc", LLPreview::onText, this);
00132         if (item)
00133                 childSetText("desc", item->getDescription());
00134         childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
00135 
00136         setTitle(title);
00137         
00138         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Notecard Editor");
00139 
00140         if (editor)
00141         {
00142                 editor->setWordWrap(TRUE);
00143                 editor->setSourceID(item_id);
00144                 editor->setHandleEditKeysDirectly(TRUE);
00145         }
00146 
00147         gAgent.changeCameraToDefault();
00148 }
00149 
00150 BOOL LLPreviewNotecard::postBuild()
00151 {
00152         LLViewerTextEditor *ed = (LLViewerTextEditor *)gUICtrlFactory->getTextEditorByName(this, "Notecard Editor");
00153         if (ed)
00154         {
00155                 ed->setNotecardInfo(mNotecardItemID, mObjectID);
00156                 ed->makePristine();
00157         }
00158         return TRUE;
00159 }
00160 
00161 bool LLPreviewNotecard::saveItem(LLPointer<LLInventoryItem>* itemptr)
00162 {
00163         LLInventoryItem* item = NULL;
00164         if (itemptr && itemptr->notNull())
00165         {
00166                 item = (LLInventoryItem*)(*itemptr);
00167         }
00168         bool res = saveIfNeeded(item);
00169         if (res)
00170         {
00171                 delete itemptr;
00172         }
00173         return res;
00174 }
00175 
00176 void LLPreviewNotecard::setEnabled( BOOL enabled )
00177 {
00178 
00179         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Notecard Editor");
00180 
00181         childSetEnabled("Notecard Editor", enabled);
00182         childSetVisible("lock", !enabled);
00183         childSetEnabled("desc", enabled);
00184         childSetEnabled("Save", enabled && editor && (!editor->isPristine()));
00185 
00186 }
00187 
00188 
00189 void LLPreviewNotecard::draw()
00190 {
00191         
00192 
00193         //childSetFocus("Save", FALSE);
00194 
00195         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Notecard Editor");
00196         BOOL script_changed = !editor->isPristine();
00197         
00198         childSetEnabled("Save", script_changed && getEnabled());
00199         
00200         LLPreview::draw();
00201 }
00202 
00203 // virtual
00204 BOOL LLPreviewNotecard::handleKeyHere(KEY key, MASK mask,
00205                                                                           BOOL called_from_parent)
00206 {
00207         if(getVisible() && getEnabled())
00208         {
00209                 if(('S' == key) && (MASK_CONTROL == (mask & MASK_CONTROL)))
00210                 {
00211                         saveIfNeeded();
00212                         return TRUE;
00213                 }
00214         }
00215         return FALSE;
00216 }
00217 
00218 // virtual
00219 BOOL LLPreviewNotecard::canClose()
00220 {
00221         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Notecard Editor");
00222 
00223         if(mForceClose || editor->isPristine())
00224         {
00225                 return TRUE;
00226         }
00227         else
00228         {
00229                 // Bring up view-modal dialog: Save changes? Yes, No, Cancel
00230                 gViewerWindow->alertXml("SaveChanges",
00231                                                                   &LLPreviewNotecard::handleSaveChangesDialog,
00232                                                                   this);
00233                                                                   
00234                 return FALSE;
00235         }
00236 }
00237 
00238 const LLInventoryItem* LLPreviewNotecard::getDragItem()
00239 {
00240         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Notecard Editor");
00241 
00242         if(editor)
00243         {
00244                 return editor->getDragItem();
00245         }
00246         return NULL;
00247 }
00248 
00249 bool LLPreviewNotecard::hasEmbeddedInventory()
00250 {
00251         LLViewerTextEditor* editor = NULL;
00252         editor = LLViewerUICtrlFactory::getViewerTextEditorByName(
00253                 this,
00254                 "Notecard Editor");
00255         if (!editor) return false;
00256         return editor->hasEmbeddedInventory();
00257 }
00258 
00259 void LLPreviewNotecard::refreshFromInventory()
00260 {
00261         lldebugs << "LLPreviewNotecard::refreshFromInventory()" << llendl;
00262         loadAsset();
00263 }
00264 
00265 void LLPreviewNotecard::loadAsset()
00266 {
00267         // request the asset.
00268         const LLInventoryItem* item = getItem();
00269         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Notecard Editor");
00270 
00271         if (!editor)
00272                 return;
00273 
00274 
00275         if(item)
00276         {
00277                 if (gAgent.allowOperation(PERM_COPY, item->getPermissions(),
00278                                                                         GP_OBJECT_MANIPULATE)
00279                         || gAgent.isGodlike())
00280                 {
00281                         mAssetID = item->getAssetUUID();
00282                         if(mAssetID.isNull())
00283                         {
00284                                 editor->setText(LLString::null);
00285                                 editor->makePristine();
00286                                 editor->setEnabled(TRUE);
00287                                 mAssetStatus = PREVIEW_ASSET_LOADED;
00288                         }
00289                         else
00290                         {
00291                                 LLUUID* new_uuid = new LLUUID(mItemUUID);
00292                                 LLHost source_sim = LLHost::invalid;
00293                                 if (mObjectUUID.notNull())
00294                                 {
00295                                         LLViewerObject *objectp = gObjectList.findObject(mObjectUUID);
00296                                         if (objectp && objectp->getRegion())
00297                                         {
00298                                                 source_sim = objectp->getRegion()->getHost();
00299                                         }
00300                                         else
00301                                         {
00302                                                 // The object that we're trying to look at disappeared, bail.
00303                                                 llwarns << "Can't find object " << mObjectUUID << " associated with notecard." << llendl;
00304                                                 mAssetID.setNull();
00305                                                 editor->setText(childGetText("no_object"));
00306                                                 editor->makePristine();
00307                                                 editor->setEnabled(FALSE);
00308                                                 mAssetStatus = PREVIEW_ASSET_LOADED;
00309                                                 delete new_uuid;
00310                                                 return;
00311                                         }
00312                                 }
00313                                 gAssetStorage->getInvItemAsset(source_sim,
00314                                                                                                 gAgent.getID(),
00315                                                                                                 gAgent.getSessionID(),
00316                                                                                                 item->getPermissions().getOwner(),
00317                                                                                                 mObjectUUID,
00318                                                                                                 item->getUUID(),
00319                                                                                                 item->getAssetUUID(),
00320                                                                                                 item->getType(),
00321                                                                                                 &onLoadComplete,
00322                                                                                                 (void*)new_uuid,
00323                                                                                                 TRUE);
00324                                 mAssetStatus = PREVIEW_ASSET_LOADING;
00325                         }
00326                 }
00327                 else
00328                 {
00329                         mAssetID.setNull();
00330                         editor->setText(childGetText("not_allowed"));
00331                         editor->makePristine();
00332                         editor->setEnabled(FALSE);
00333                         mAssetStatus = PREVIEW_ASSET_LOADED;
00334                 }
00335                 if(!gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
00336                                                                 GP_OBJECT_MANIPULATE))
00337                 {
00338                         editor->setEnabled(FALSE);
00339                         childSetVisible("lock", TRUE);
00340                 }
00341         }
00342         else
00343         {
00344                 editor->setText(LLString::null);
00345                 editor->makePristine();
00346                 editor->setEnabled(TRUE);
00347                 mAssetStatus = PREVIEW_ASSET_LOADED;
00348         }
00349 }
00350 
00351 // static
00352 void LLPreviewNotecard::onLoadComplete(LLVFS *vfs,
00353                                                                            const LLUUID& asset_uuid,
00354                                                                            LLAssetType::EType type,
00355                                                                            void* user_data, S32 status, LLExtStat ext_status)
00356 {
00357         llinfos << "LLPreviewNotecard::onLoadComplete()" << llendl;
00358         LLUUID* item_id = (LLUUID*)user_data;
00359         LLPreviewNotecard* preview = LLPreviewNotecard::getInstance(*item_id);
00360         if( preview )
00361         {
00362                 if(0 == status)
00363                 {
00364                         LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
00365 
00366                         S32 file_length = file.getSize();
00367 
00368                         char* buffer = new char[file_length+1];
00369                         file.read((U8*)buffer, file_length);            /*Flawfinder: ignore*/
00370 
00371                         // put a EOS at the end
00372                         buffer[file_length] = 0;
00373 
00374                         
00375                         LLViewerTextEditor* previewEditor = LLViewerUICtrlFactory::getViewerTextEditorByName(preview, "Notecard Editor");
00376 
00377                         if( (file_length > 19) && !strncmp( buffer, "Linden text version", 19 ) )
00378                         {
00379                                 if( !previewEditor->importBuffer( buffer ) )
00380                                 {
00381                                         llwarns << "Problem importing notecard" << llendl;
00382                                 }
00383                         }
00384                         else
00385                         {
00386                                 // Version 0 (just text, doesn't include version number)
00387                                 previewEditor->setText(LLStringExplicit(buffer));
00388                         }
00389 
00390                         previewEditor->makePristine();
00391 
00392                         const LLInventoryItem* item = preview->getItem();
00393                         BOOL modifiable = item && gAgent.allowOperation(PERM_MODIFY,
00394                                                                 item->getPermissions(), GP_OBJECT_MANIPULATE);
00395                         preview->setEnabled(modifiable);
00396                         delete[] buffer;
00397                         preview->mAssetStatus = PREVIEW_ASSET_LOADED;
00398                 }
00399                 else
00400                 {
00401                         if( gViewerStats )
00402                         {
00403                                 gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
00404                         }
00405 
00406                         if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
00407                                 LL_ERR_FILE_EMPTY == status)
00408                         {
00409                                 LLNotifyBox::showXml("NotecardMissing");
00410                         }
00411                         else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
00412                         {
00413                                 LLNotifyBox::showXml("NotecardNoPermissions");
00414                         }
00415                         else
00416                         {
00417                                 LLNotifyBox::showXml("UnableToLoadNotecard");
00418                         }
00419 
00420                         llwarns << "Problem loading notecard: " << status << llendl;
00421                         preview->mAssetStatus = PREVIEW_ASSET_ERROR;
00422                 }
00423         }
00424         delete item_id;
00425 }
00426 
00427 // static
00428 LLPreviewNotecard* LLPreviewNotecard::getInstance(const LLUUID& item_id)
00429 {
00430         LLPreview* instance = NULL;
00431         preview_map_t::iterator found_it = LLPreview::sInstances.find(item_id);
00432         if(found_it != LLPreview::sInstances.end())
00433         {
00434                 instance = found_it->second;
00435         }
00436         return (LLPreviewNotecard*)instance;
00437 }
00438 
00439 // static
00440 void LLPreviewNotecard::onClickSave(void* user_data)
00441 {
00442         //llinfos << "LLPreviewNotecard::onBtnSave()" << llendl;
00443         LLPreviewNotecard* preview = (LLPreviewNotecard*)user_data;
00444         if(preview)
00445         {
00446                 preview->saveIfNeeded();
00447         }
00448 }
00449 
00450 struct LLSaveNotecardInfo
00451 {
00452         LLPreviewNotecard* mSelf;
00453         LLUUID mItemUUID;
00454         LLUUID mObjectUUID;
00455         LLTransactionID mTransactionID;
00456         LLPointer<LLInventoryItem> mCopyItem;
00457         LLSaveNotecardInfo(LLPreviewNotecard* self, const LLUUID& item_id, const LLUUID& object_id,
00458                                            const LLTransactionID& transaction_id, LLInventoryItem* copyitem) :
00459                 mSelf(self), mItemUUID(item_id), mObjectUUID(object_id), mTransactionID(transaction_id), mCopyItem(copyitem)
00460         {
00461         }
00462 };
00463 
00464 bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
00465 {
00466         if(!gAssetStorage)
00467         {
00468                 llwarns << "Not connected to an asset storage system." << llendl;
00469                 return false;
00470         }
00471 
00472         
00473         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Notecard Editor");
00474 
00475         if(!editor->isPristine())
00476         {
00477                 // We need to update the asset information
00478                 LLTransactionID tid;
00479                 LLAssetID asset_id;
00480                 tid.generate();
00481                 asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
00482 
00483                 LLVFile file(gVFS, asset_id, LLAssetType::AT_NOTECARD, LLVFile::APPEND);
00484 
00485                 LLString buffer;
00486                 if (!editor->exportBuffer(buffer))
00487                 {
00488                         return false;
00489                 }
00490 
00491                 editor->makePristine();
00492 
00493                 S32 size = buffer.length() + 1;
00494                 file.setMaxSize(size);
00495                 file.write((U8*)buffer.c_str(), size);
00496 
00497                 const LLInventoryItem* item = getItem();
00498                 // save it out to database
00499                 if (item)
00500                 {                       
00501                         std::string agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory");
00502                         std::string task_url = gAgent.getRegion()->getCapability("UpdateNotecardTaskInventory");
00503                         if (mObjectUUID.isNull() && !agent_url.empty())
00504                         {
00505                                 // Saving into agent inventory
00506                                 mAssetStatus = PREVIEW_ASSET_LOADING;
00507                                 setEnabled(FALSE);
00508                                 LLSD body;
00509                                 body["item_id"] = mItemUUID;
00510                                 llinfos << "Saving notecard " << mItemUUID
00511                                         << " into agent inventory via " << agent_url << llendl;
00512                                 LLHTTPClient::post(agent_url, body,
00513                                         new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD));
00514                         }
00515                         else if (!mObjectUUID.isNull() && !task_url.empty())
00516                         {
00517                                 // Saving into task inventory
00518                                 mAssetStatus = PREVIEW_ASSET_LOADING;
00519                                 setEnabled(FALSE);
00520                                 LLSD body;
00521                                 body["task_id"] = mObjectUUID;
00522                                 body["item_id"] = mItemUUID;
00523                                 llinfos << "Saving notecard " << mItemUUID << " into task "
00524                                         << mObjectUUID << " via " << task_url << llendl;
00525                                 LLHTTPClient::post(task_url, body,
00526                                         new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD));
00527                         }
00528                         else if (gAssetStorage)
00529                         {
00530                                 LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID,
00531                                                                                                                                 tid, copyitem);
00532                                 gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD,
00533                                                                                                 &onSaveComplete,
00534                                                                                                 (void*)info,
00535                                                                                                 FALSE);
00536                         }
00537                 }
00538         }
00539         return true;
00540 }
00541 
00542 // static
00543 void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
00544 {
00545         LLSaveNotecardInfo* info = (LLSaveNotecardInfo*)user_data;
00546         if(info && (0 == status))
00547         {
00548                 if(info->mObjectUUID.isNull())
00549                 {
00550                         LLViewerInventoryItem* item;
00551                         item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID);
00552                         if(item)
00553                         {
00554                                 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00555                                 new_item->setAssetUUID(asset_uuid);
00556                                 new_item->setTransactionID(info->mTransactionID);
00557                                 new_item->updateServer(FALSE);
00558                                 gInventory.updateItem(new_item);
00559                                 gInventory.notifyObservers();
00560                         }
00561                         else
00562                         {
00563                                 llwarns << "Inventory item for script " << info->mItemUUID
00564                                                 << " is no longer in agent inventory." << llendl;
00565                         }
00566                 }
00567                 else
00568                 {
00569                         LLViewerObject* object = gObjectList.findObject(info->mObjectUUID);
00570                         LLViewerInventoryItem* item = NULL;
00571                         if(object)
00572                         {
00573                                 item = (LLViewerInventoryItem*)object->getInventoryObject(info->mItemUUID);
00574                         }
00575                         if(object && item)
00576                         {
00577                                 item->setAssetUUID(asset_uuid);
00578                                 item->setTransactionID(info->mTransactionID);
00579                                 object->updateInventory(item, TASK_INVENTORY_ITEM_KEY, false);
00580                                 dialog_refresh_all();
00581                         }
00582                         else
00583                         {
00584                                 gViewerWindow->alertXml("SaveNotecardFailObjectNotFound");
00585                         }
00586                 }
00587                 // Perform item copy to inventory
00588                 if (info->mCopyItem.notNull())
00589                 {
00590                         LLViewerTextEditor* editor = LLViewerUICtrlFactory::getViewerTextEditorByName(info->mSelf, "Notecard Editor");
00591                         if (editor)
00592                         {
00593                                 editor->copyInventory(info->mCopyItem);
00594                         }
00595                 }
00596                 
00597                 // Find our window and close it if requested.
00598                 LLPreviewNotecard* previewp = (LLPreviewNotecard*)LLPreview::find(info->mItemUUID);
00599                 if (previewp && previewp->mCloseAfterSave)
00600                 {
00601                         previewp->close();
00602                 }
00603         }
00604         else
00605         {
00606                 llwarns << "Problem saving notecard: " << status << llendl;
00607                 LLStringBase<char>::format_map_t args;
00608                 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
00609                 gViewerWindow->alertXml("SaveNotecardFailReason",args);
00610         }
00611 
00612         char uuid_string[UUID_STR_LENGTH];              /*Flawfinder: ignore*/
00613         asset_uuid.toString(uuid_string);
00614         char filename[LL_MAX_PATH];             /*Flawfinder: ignore*/
00615         snprintf(filename, LL_MAX_PATH, "%s.tmp", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());                   /* Flawfinder: ignore */
00616         LLFile::remove(filename);
00617         delete info;
00618 }
00619 
00620 // static
00621 void LLPreviewNotecard::handleSaveChangesDialog(S32 option, void* userdata)
00622 {
00623         LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
00624         switch(option)
00625         {
00626         case 0:  // "Yes"
00627                 self->mCloseAfterSave = TRUE;
00628                 LLPreviewNotecard::onClickSave((void*)self);
00629                 break;
00630 
00631         case 1:  // "No"
00632                 self->mForceClose = TRUE;
00633                 self->close();
00634                 break;
00635 
00636         case 2: // "Cancel"
00637         default:
00638                 // If we were quitting, we didn't really mean it.
00639                 app_abort_quit();
00640                 break;
00641         }
00642 }
00643 
00644 void LLPreviewNotecard::reshape(S32 width, S32 height, BOOL called_from_parent)
00645 {
00646         LLPreview::reshape( width, height, called_from_parent );
00647 
00648         if( !isMinimized() )
00649         {
00650                 // So that next time you open a script it will have the same height and width 
00651                 // (although not the same position).
00652                 gSavedSettings.setRect("NotecardEditorRect", mRect);
00653         }
00654 }
00655 
00656 // EOF

Generated on Thu Jul 1 06:09:02 2010 for Second Life Viewer by  doxygen 1.4.7