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 "llviewercontrol.h"            // gSavedSettings
00059 #include "llappviewer.h"                // app_abort_quit()
00060 #include "lllineeditor.h"
00061 #include "lluictrlfactory.h"
00062 
00066 
00067 const S32 PREVIEW_MIN_WIDTH =
00068         2 * PREVIEW_BORDER +
00069         2 * PREVIEW_BUTTON_WIDTH + 
00070         PREVIEW_PAD + RESIZE_HANDLE_WIDTH +
00071         PREVIEW_PAD;
00072 const S32 PREVIEW_MIN_HEIGHT = 
00073         2 * PREVIEW_BORDER +
00074         3*(20 + PREVIEW_PAD) +
00075         2 * SCROLLBAR_SIZE + 128;
00076 
00080 
00081 // Default constructor
00082 LLPreviewNotecard::LLPreviewNotecard(const std::string& name,
00083                                                                          const LLRect& rect,
00084                                                                          const std::string& title,
00085                                                                          const LLUUID& item_id, 
00086                                                                          const LLUUID& object_id,
00087                                                                          const LLUUID& asset_id,
00088                                                                          BOOL show_keep_discard,
00089                                                                          LLPointer<LLViewerInventoryItem> inv_item) :
00090         LLPreview(name, rect, title, item_id, object_id, TRUE,
00091                           PREVIEW_MIN_WIDTH,
00092                           PREVIEW_MIN_HEIGHT,
00093                           inv_item),
00094         mAssetID( asset_id ),
00095         mNotecardItemID(item_id),
00096         mObjectID(object_id)
00097 {
00098         LLRect curRect = rect;
00099 
00100         if (show_keep_discard)
00101         {
00102                 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_notecard_keep_discard.xml");
00103                 childSetAction("Keep",onKeepBtn,this);
00104                 childSetAction("Discard",onDiscardBtn,this);
00105         }
00106         else
00107         {
00108                 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_notecard.xml");
00109                 childSetAction("Save",onClickSave,this);
00110                 
00111                 if( mAssetID.isNull() )
00112                 {
00113                         const LLInventoryItem* item = getItem();
00114                         if( item )
00115                         {
00116                                 mAssetID = item->getAssetUUID();
00117                         }
00118                 }
00119         }       
00120 
00121         // only assert shape if not hosted in a multifloater
00122         if (!getHost())
00123         {
00124                 reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
00125                 setRect(curRect);
00126         }
00127                         
00128         childSetVisible("lock", FALSE); 
00129         
00130         const LLInventoryItem* item = getItem();
00131         
00132         childSetCommitCallback("desc", LLPreview::onText, this);
00133         if (item)
00134                 childSetText("desc", item->getDescription());
00135         childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
00136 
00137         setTitle(title);
00138         
00139         LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
00140 
00141         if (editor)
00142         {
00143                 editor->setWordWrap(TRUE);
00144                 editor->setSourceID(item_id);
00145                 editor->setHandleEditKeysDirectly(TRUE);
00146         }
00147 
00148         gAgent.changeCameraToDefault();
00149 }
00150 
00151 LLPreviewNotecard::~LLPreviewNotecard()
00152 {
00153 }
00154 
00155 BOOL LLPreviewNotecard::postBuild()
00156 {
00157         LLViewerTextEditor *ed = getChild<LLViewerTextEditor>("Notecard Editor");
00158         if (ed)
00159         {
00160                 ed->setNotecardInfo(mNotecardItemID, mObjectID);
00161                 ed->makePristine();
00162         }
00163         return TRUE;
00164 }
00165 
00166 bool LLPreviewNotecard::saveItem(LLPointer<LLInventoryItem>* itemptr)
00167 {
00168         LLInventoryItem* item = NULL;
00169         if (itemptr && itemptr->notNull())
00170         {
00171                 item = (LLInventoryItem*)(*itemptr);
00172         }
00173         bool res = saveIfNeeded(item);
00174         if (res)
00175         {
00176                 delete itemptr;
00177         }
00178         return res;
00179 }
00180 
00181 void LLPreviewNotecard::setEnabled( BOOL enabled )
00182 {
00183 
00184         LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
00185 
00186         childSetEnabled("Notecard Editor", enabled);
00187         childSetVisible("lock", !enabled);
00188         childSetEnabled("desc", enabled);
00189         childSetEnabled("Save", enabled && editor && (!editor->isPristine()));
00190 
00191 }
00192 
00193 
00194 void LLPreviewNotecard::draw()
00195 {
00196         
00197 
00198         //childSetFocus("Save", FALSE);
00199 
00200         LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
00201         BOOL script_changed = !editor->isPristine();
00202         
00203         childSetEnabled("Save", script_changed && getEnabled());
00204         
00205         LLPreview::draw();
00206 }
00207 
00208 // virtual
00209 BOOL LLPreviewNotecard::handleKeyHere(KEY key, MASK mask)
00210 {
00211         if(('S' == key) && (MASK_CONTROL == (mask & MASK_CONTROL)))
00212         {
00213                 saveIfNeeded();
00214                 return TRUE;
00215         }
00216 
00217         return LLPreview::handleKeyHere(key, mask);
00218 }
00219 
00220 // virtual
00221 BOOL LLPreviewNotecard::canClose()
00222 {
00223         LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
00224 
00225         if(mForceClose || editor->isPristine())
00226         {
00227                 return TRUE;
00228         }
00229         else
00230         {
00231                 // Bring up view-modal dialog: Save changes? Yes, No, Cancel
00232                 gViewerWindow->alertXml("SaveChanges",
00233                                                                   &LLPreviewNotecard::handleSaveChangesDialog,
00234                                                                   this);
00235                                                                   
00236                 return FALSE;
00237         }
00238 }
00239 
00240 const LLInventoryItem* LLPreviewNotecard::getDragItem()
00241 {
00242         LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
00243 
00244         if(editor)
00245         {
00246                 return editor->getDragItem();
00247         }
00248         return NULL;
00249 }
00250 
00251 bool LLPreviewNotecard::hasEmbeddedInventory()
00252 {
00253         LLViewerTextEditor* editor = NULL;
00254         editor = getChild<LLViewerTextEditor>("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 = getChild<LLViewerTextEditor>("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(getString("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(getString("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 = preview->getChild<LLViewerTextEditor>("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                         LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
00402 
00403                         if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
00404                                 LL_ERR_FILE_EMPTY == status)
00405                         {
00406                                 LLNotifyBox::showXml("NotecardMissing");
00407                         }
00408                         else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
00409                         {
00410                                 LLNotifyBox::showXml("NotecardNoPermissions");
00411                         }
00412                         else
00413                         {
00414                                 LLNotifyBox::showXml("UnableToLoadNotecard");
00415                         }
00416 
00417                         llwarns << "Problem loading notecard: " << status << llendl;
00418                         preview->mAssetStatus = PREVIEW_ASSET_ERROR;
00419                 }
00420         }
00421         delete item_id;
00422 }
00423 
00424 // static
00425 LLPreviewNotecard* LLPreviewNotecard::getInstance(const LLUUID& item_id)
00426 {
00427         LLPreview* instance = NULL;
00428         preview_map_t::iterator found_it = LLPreview::sInstances.find(item_id);
00429         if(found_it != LLPreview::sInstances.end())
00430         {
00431                 instance = found_it->second;
00432         }
00433         return (LLPreviewNotecard*)instance;
00434 }
00435 
00436 // static
00437 void LLPreviewNotecard::onClickSave(void* user_data)
00438 {
00439         //llinfos << "LLPreviewNotecard::onBtnSave()" << llendl;
00440         LLPreviewNotecard* preview = (LLPreviewNotecard*)user_data;
00441         if(preview)
00442         {
00443                 preview->saveIfNeeded();
00444         }
00445 }
00446 
00447 struct LLSaveNotecardInfo
00448 {
00449         LLPreviewNotecard* mSelf;
00450         LLUUID mItemUUID;
00451         LLUUID mObjectUUID;
00452         LLTransactionID mTransactionID;
00453         LLPointer<LLInventoryItem> mCopyItem;
00454         LLSaveNotecardInfo(LLPreviewNotecard* self, const LLUUID& item_id, const LLUUID& object_id,
00455                                            const LLTransactionID& transaction_id, LLInventoryItem* copyitem) :
00456                 mSelf(self), mItemUUID(item_id), mObjectUUID(object_id), mTransactionID(transaction_id), mCopyItem(copyitem)
00457         {
00458         }
00459 };
00460 
00461 bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
00462 {
00463         if(!gAssetStorage)
00464         {
00465                 llwarns << "Not connected to an asset storage system." << llendl;
00466                 return false;
00467         }
00468 
00469         
00470         LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
00471 
00472         if(!editor->isPristine())
00473         {
00474                 // We need to update the asset information
00475                 LLTransactionID tid;
00476                 LLAssetID asset_id;
00477                 tid.generate();
00478                 asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
00479 
00480                 LLVFile file(gVFS, asset_id, LLAssetType::AT_NOTECARD, LLVFile::APPEND);
00481 
00482                 LLString buffer;
00483                 if (!editor->exportBuffer(buffer))
00484                 {
00485                         return false;
00486                 }
00487 
00488                 editor->makePristine();
00489 
00490                 S32 size = buffer.length() + 1;
00491                 file.setMaxSize(size);
00492                 file.write((U8*)buffer.c_str(), size);
00493 
00494                 const LLInventoryItem* item = getItem();
00495                 // save it out to database
00496                 if (item)
00497                 {                       
00498                         std::string agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory");
00499                         std::string task_url = gAgent.getRegion()->getCapability("UpdateNotecardTaskInventory");
00500                         if (mObjectUUID.isNull() && !agent_url.empty())
00501                         {
00502                                 // Saving into agent inventory
00503                                 mAssetStatus = PREVIEW_ASSET_LOADING;
00504                                 setEnabled(FALSE);
00505                                 LLSD body;
00506                                 body["item_id"] = mItemUUID;
00507                                 llinfos << "Saving notecard " << mItemUUID
00508                                         << " into agent inventory via " << agent_url << llendl;
00509                                 LLHTTPClient::post(agent_url, body,
00510                                         new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD));
00511                         }
00512                         else if (!mObjectUUID.isNull() && !task_url.empty())
00513                         {
00514                                 // Saving into task inventory
00515                                 mAssetStatus = PREVIEW_ASSET_LOADING;
00516                                 setEnabled(FALSE);
00517                                 LLSD body;
00518                                 body["task_id"] = mObjectUUID;
00519                                 body["item_id"] = mItemUUID;
00520                                 llinfos << "Saving notecard " << mItemUUID << " into task "
00521                                         << mObjectUUID << " via " << task_url << llendl;
00522                                 LLHTTPClient::post(task_url, body,
00523                                         new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD));
00524                         }
00525                         else if (gAssetStorage)
00526                         {
00527                                 LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID,
00528                                                                                                                                 tid, copyitem);
00529                                 gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD,
00530                                                                                                 &onSaveComplete,
00531                                                                                                 (void*)info,
00532                                                                                                 FALSE);
00533                         }
00534                 }
00535         }
00536         return true;
00537 }
00538 
00539 // static
00540 void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
00541 {
00542         LLSaveNotecardInfo* info = (LLSaveNotecardInfo*)user_data;
00543         if(info && (0 == status))
00544         {
00545                 if(info->mObjectUUID.isNull())
00546                 {
00547                         LLViewerInventoryItem* item;
00548                         item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID);
00549                         if(item)
00550                         {
00551                                 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00552                                 new_item->setAssetUUID(asset_uuid);
00553                                 new_item->setTransactionID(info->mTransactionID);
00554                                 new_item->updateServer(FALSE);
00555                                 gInventory.updateItem(new_item);
00556                                 gInventory.notifyObservers();
00557                         }
00558                         else
00559                         {
00560                                 llwarns << "Inventory item for script " << info->mItemUUID
00561                                                 << " is no longer in agent inventory." << llendl;
00562                         }
00563                 }
00564                 else
00565                 {
00566                         LLViewerObject* object = gObjectList.findObject(info->mObjectUUID);
00567                         LLViewerInventoryItem* item = NULL;
00568                         if(object)
00569                         {
00570                                 item = (LLViewerInventoryItem*)object->getInventoryObject(info->mItemUUID);
00571                         }
00572                         if(object && item)
00573                         {
00574                                 item->setAssetUUID(asset_uuid);
00575                                 item->setTransactionID(info->mTransactionID);
00576                                 object->updateInventory(item, TASK_INVENTORY_ITEM_KEY, false);
00577                                 dialog_refresh_all();
00578                         }
00579                         else
00580                         {
00581                                 gViewerWindow->alertXml("SaveNotecardFailObjectNotFound");
00582                         }
00583                 }
00584                 // Perform item copy to inventory
00585                 if (info->mCopyItem.notNull())
00586                 {
00587                         LLViewerTextEditor* editor = info->mSelf->getChild<LLViewerTextEditor>("Notecard Editor");
00588                         if (editor)
00589                         {
00590                                 editor->copyInventory(info->mCopyItem);
00591                         }
00592                 }
00593                 
00594                 // Find our window and close it if requested.
00595                 LLPreviewNotecard* previewp = (LLPreviewNotecard*)LLPreview::find(info->mItemUUID);
00596                 if (previewp && previewp->mCloseAfterSave)
00597                 {
00598                         previewp->close();
00599                 }
00600         }
00601         else
00602         {
00603                 llwarns << "Problem saving notecard: " << status << llendl;
00604                 LLStringBase<char>::format_map_t args;
00605                 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
00606                 gViewerWindow->alertXml("SaveNotecardFailReason",args);
00607         }
00608 
00609         char uuid_string[UUID_STR_LENGTH];              /*Flawfinder: ignore*/
00610         asset_uuid.toString(uuid_string);
00611         char filename[LL_MAX_PATH];             /*Flawfinder: ignore*/
00612         snprintf(filename, LL_MAX_PATH, "%s.tmp", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());                   /* Flawfinder: ignore */
00613         LLFile::remove(filename);
00614         delete info;
00615 }
00616 
00617 // static
00618 void LLPreviewNotecard::handleSaveChangesDialog(S32 option, void* userdata)
00619 {
00620         LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
00621         switch(option)
00622         {
00623         case 0:  // "Yes"
00624                 self->mCloseAfterSave = TRUE;
00625                 LLPreviewNotecard::onClickSave((void*)self);
00626                 break;
00627 
00628         case 1:  // "No"
00629                 self->mForceClose = TRUE;
00630                 self->close();
00631                 break;
00632 
00633         case 2: // "Cancel"
00634         default:
00635                 // If we were quitting, we didn't really mean it.
00636                 LLAppViewer::instance()->abortQuit();
00637                 break;
00638         }
00639 }
00640 
00641 void LLPreviewNotecard::reshape(S32 width, S32 height, BOOL called_from_parent)
00642 {
00643         LLPreview::reshape( width, height, called_from_parent );
00644 
00645         if( !isMinimized() )
00646         {
00647                 // So that next time you open a script it will have the same height and width 
00648                 // (although not the same position).
00649                 gSavedSettings.setRect("NotecardEditorRect", getRect());
00650         }
00651 }
00652 
00653 // EOF

Generated on Fri May 16 08:33:57 2008 for SecondLife by  doxygen 1.5.5