123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296 |
- /**
- * @file llpreviewnotecard.cpp
- * @brief Implementation of the notecard editor
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llpreviewnotecard.h"
- #include "llassetstorage.h"
- #include "llbutton.h"
- #include "lldir.h"
- #include "hbexternaleditor.h"
- #include "llfilesystem.h"
- #include "llfontgl.h"
- #include "lliconctrl.h"
- #include "llinventory.h"
- #include "lllineeditor.h"
- #include "llmenugl.h"
- #include "llnotifications.h"
- #include "llscrollbar.h"
- #include "llspellcheck.h"
- #include "lluictrlfactory.h"
- #include "roles_constants.h"
- #include "llagent.h"
- #include "llappviewer.h" // For abortQuit()
- #include "llfloatersearchreplace.h"
- #include "llinventorymodel.h"
- #include "llselectmgr.h"
- #include "llviewerassetupload.h"
- #include "llviewercontrol.h"
- #include "llviewerinventory.h"
- #include "llviewerobjectlist.h"
- #include "llviewerregion.h"
- #include "llviewerstats.h"
- #include "llviewertexteditor.h"
- constexpr S32 PREVIEW_MIN_WIDTH = 2 * PREVIEW_BORDER +
- 2 * PREVIEW_BUTTON_WIDTH +
- 2 * PREVIEW_PAD + RESIZE_HANDLE_WIDTH;
- constexpr S32 PREVIEW_MIN_HEIGHT = 2 * PREVIEW_BORDER +
- 3 * (20 + PREVIEW_PAD) +
- 2 * SCROLLBAR_SIZE + 128;
- std::set<LLPreviewNotecard*> LLPreviewNotecard::sInstances;
- LLFontGL* LLPreviewNotecard::sCustomFont = NULL;
- LLPreviewNotecard::LLPreviewNotecard(const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const LLUUID& item_id,
- const LLUUID& object_id,
- const LLUUID& asset_id,
- bool show_keep_discard,
- LLPointer<LLViewerInventoryItem> inv_item)
- : LLPreview(name, rect, title, item_id, object_id, true, PREVIEW_MIN_WIDTH,
- PREVIEW_MIN_HEIGHT, inv_item),
- mExternalEditor(NULL),
- mAssetID(asset_id),
- mNotecardItemID(item_id),
- mObjectID(object_id),
- mShowKeepDiscard(show_keep_discard)
- {
- sInstances.insert(this);
- LLRect curRect = rect;
- std::string file;
- if (!show_keep_discard && mAssetID.isNull())
- {
- const LLInventoryItem* item = getItem();
- if (item)
- {
- mAssetID = item->getAssetUUID();
- }
- }
- LLUICtrlFactory::getInstance()->buildFloater(this,
- "floater_preview_notecard.xml");
- // Only assert shape if not hosted in a multifloater
- if (!getHost())
- {
- reshape(curRect.getWidth(), curRect.getHeight());
- setRect(curRect);
- }
- setTitle(title);
- setNoteName(title);
- }
- //virtual
- LLPreviewNotecard::~LLPreviewNotecard()
- {
- sInstances.erase(this);
- if (mExternalEditor)
- {
- delete mExternalEditor;
- }
- if (!mTempFilename.empty())
- {
- LLFile::remove(mTempFilename);
- }
- }
- //virtual
- bool LLPreviewNotecard::postBuild()
- {
- mEditor = getChild<LLViewerTextEditor>("text_edit");
- mEditor->setWordWrap(true);
- mEditor->setSourceID(mNotecardItemID);
- mEditor->setHandleEditKeysDirectly(true);
- mEditor->setNotecardInfo(mNotecardItemID, mObjectID);
- mEditor->makePristine();
- // Use separate and possibly different colors for the note card editor. HB
- LLColor4 color = gColors.getColor("TextFgNotecardColor");
- mEditor->setFgColor(color);
- mEditor->setTextDefaultColor(color);
- mEditor->setReadOnlyFgColor(gColors.getColor("TextFgNotecardReadOnlyColor"));
- mEditor->setWriteableBgColor(gColors.getColor("TextBgNotecardColor"));
- mEditor->setReadOnlyBgColor(gColors.getColor("TextBgNotecardReadOnlyColor"));
- if (sCustomFont)
- {
- mEditor->setFont(sCustomFont);
- }
- mDescription = getChild<LLLineEditor>("desc");
- mDescription->setCommitCallback(LLPreview::onText);
- mDescription->setCallbackUserData(this);
- mDescription->setPrevalidate(LLLineEditor::prevalidatePrintableNotPipe);
- const LLInventoryItem* inv_item = getItem();
- if (inv_item)
- {
- mDescription->setText(inv_item->getDescription());
- }
- mSaveButton = getChild<LLButton>("save_btn");
- mSaveButton->setClickedCallback(onClickSave, this);
- if (mShowKeepDiscard)
- {
- childSetAction("keep_btn", onKeepBtn, this);
- childSetAction("discard_btn", onDiscardBtn, this);
- }
- else
- {
- childSetVisible("keep_btn", false);
- childSetVisible("discard_btn", false);
- }
- mLockIcon = getChild<LLIconCtrl>("lock");
- mLockIcon->setVisible(false);
- LLMenuItemCallGL* itemp = getChild<LLMenuItemCallGL>("load");
- itemp->setMenuCallback(onLoadFromFile, this);
- itemp->setEnabledCallback(enableSaveLoadFile);
- itemp = getChild<LLMenuItemCallGL>("save");
- itemp->setMenuCallback(onSaveToFile, this);
- itemp->setEnabledCallback(enableSaveLoadFile);
- itemp = getChild<LLMenuItemCallGL>("external");
- itemp->setMenuCallback(onEditExternal, this);
- itemp->setEnabledCallback(enableSaveLoadFile);
- itemp = getChild<LLMenuItemCallGL>("undo");
- itemp->setMenuCallback(onUndoMenu, this);
- itemp->setEnabledCallback(enableUndoMenu);
- itemp = getChild<LLMenuItemCallGL>("redo");
- itemp->setMenuCallback(onRedoMenu, this);
- itemp->setEnabledCallback(enableRedoMenu);
- itemp = getChild<LLMenuItemCallGL>("cut");
- itemp->setMenuCallback(onCutMenu, this);
- itemp->setEnabledCallback(enableCutMenu);
- itemp = getChild<LLMenuItemCallGL>("copy");
- itemp->setMenuCallback(onCopyMenu, this);
- itemp->setEnabledCallback(enableCopyMenu);
- itemp = getChild<LLMenuItemCallGL>("paste");
- itemp->setMenuCallback(onPasteMenu, this);
- itemp->setEnabledCallback(enablePasteMenu);
- itemp = getChild<LLMenuItemCallGL>("select_all");
- itemp->setMenuCallback(onSelectAllMenu, this);
- itemp->setEnabledCallback(enableSelectAllMenu);
- itemp = getChild<LLMenuItemCallGL>("deselect");
- itemp->setMenuCallback(onDeselectMenu, this);
- itemp->setEnabledCallback(enableDeselectMenu);
- itemp = getChild<LLMenuItemCallGL>("search");
- itemp->setMenuCallback(onSearchMenu, this);
- itemp->setEnabledCallback(NULL);
- LLMenuItemCheckGL* citemp = getChild<LLMenuItemCheckGL>("spelling");
- citemp->setMenuCallback(onSpellCheckMenu, this);
- citemp->setEnabledCallback(enableSpellCheckMenu);
- citemp->setCheckCallback(checkSpellCheckMenu);
- citemp->setValue(false);
- // Make sure the std::vector will not move in memory while we fill it up,
- // since we use pointers to its entries in our callbacks ! HB
- mCallbackData.reserve(16); // Using a power of two, but 10 should be fine.
- citemp = getChild<LLMenuItemCheckGL>("SansSerif");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontName, &mCallbackData.back());
- citemp->setCheckCallback(checkFontName);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Helvetica");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontName, &mCallbackData.back());
- citemp->setCheckCallback(checkFontName);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Courrier");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontName, &mCallbackData.back());
- citemp->setCheckCallback(checkFontName);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Monospace");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontName, &mCallbackData.back());
- citemp->setCheckCallback(checkFontName);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Tiny");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontSize, &mCallbackData.back());
- citemp->setCheckCallback(checkFontSize);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Little");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontSize, &mCallbackData.back());
- citemp->setCheckCallback(checkFontSize);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Small");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontSize, &mCallbackData.back());
- citemp->setCheckCallback(checkFontSize);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Medium");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontSize, &mCallbackData.back());
- citemp->setCheckCallback(checkFontSize);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Large");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontSize, &mCallbackData.back());
- citemp->setCheckCallback(checkFontSize);
- citemp->setValue(false);
- citemp = getChild<LLMenuItemCheckGL>("Huge");
- mCallbackData.emplace_back(this, citemp);
- citemp->setMenuCallback(onSetFontSize, &mCallbackData.back());
- citemp->setCheckCallback(checkFontSize);
- citemp->setValue(false);
- // Tell LLEditMenuHandler about our editor type: this will trigger a Lua
- // callback if one is configured for context menus. HB
- mEditor->setCustomMenuType("notecard");
- return true;
- }
- //static
- void LLPreviewNotecard::refreshCachedSettings()
- {
- std::string font_name = gSavedSettings.getString("NotecardEditorFont");
- if (font_name.empty())
- {
- sCustomFont = NULL;
- }
- else
- {
- sCustomFont = LLFontGL::getFont(font_name.c_str());
- }
- }
- //virtual
- void LLPreviewNotecard::draw()
- {
- mSaveButton->setEnabled(getEnabled() && !mEditor->isPristine());
- LLPreview::draw();
- }
- void LLPreviewNotecard::setNoteName(std::string name)
- {
- if (name.find("Note: ") == 0)
- {
- name = name.substr(6);
- }
- if (name.empty())
- {
- name = "untitled";
- }
- mNoteName = name;
- }
- //virtual
- void LLPreviewNotecard::setObjectID(const LLUUID& object_id)
- {
- LLPreview::setObjectID(object_id);
- mEditor->setNotecardObjectID(mObjectUUID);
- mEditor->makePristine();
- }
- bool LLPreviewNotecard::saveItem(LLPointer<LLInventoryItem>* itemptr)
- {
- LLInventoryItem* item = NULL;
- if (itemptr && itemptr->notNull())
- {
- item = (LLInventoryItem*)(*itemptr);
- }
- bool res = saveIfNeeded(item);
- if (res)
- {
- delete itemptr;
- }
- return res;
- }
- void LLPreviewNotecard::setEnabled(bool enabled)
- {
- mEditor->setEnabled(enabled);
- mLockIcon->setVisible(!enabled);
- mDescription->setEnabled(enabled);
- mSaveButton->setEnabled(enabled && !mEditor->isPristine());
- }
- //virtual
- bool LLPreviewNotecard::handleKeyHere(KEY key, MASK mask)
- {
- if (mask == MASK_CONTROL)
- {
- if (key == 'S')
- {
- saveIfNeeded();
- return true;
- }
- if (key == 'F')
- {
- LLFloaterSearchReplace::show(mEditor);
- return true;
- }
- }
- return LLPreview::handleKeyHere(key, mask);
- }
- //virtual
- bool LLPreviewNotecard::canClose()
- {
- if (mForceClose || mEditor->isPristine())
- {
- return true;
- }
- if (!mSaveDialogShown)
- {
- mSaveDialogShown = true;
- // Bring up view-modal dialog: Save changes ? Yes, No, Cancel
- gNotifications.add("SaveChanges", LLSD(), LLSD(),
- boost::bind(&LLPreviewNotecard::handleSaveChangesDialog,
- this, _1, _2));
- }
- return false;
- }
- //virtual
- void LLPreviewNotecard::inventoryChanged(LLViewerObject*,
- LLInventoryObject::object_list_t*,
- S32, void*)
- {
- removeVOInventoryListener();
- loadAsset();
- }
- const LLInventoryItem* LLPreviewNotecard::getDragItem()
- {
- return mEditor->getDragItem();
- }
- bool LLPreviewNotecard::hasEmbeddedInventory()
- {
- return mEditor->hasEmbeddedInventory();
- }
- void LLPreviewNotecard::refreshFromInventory()
- {
- LL_DEBUGS("Notecard") << "Refreshing from inventory" << LL_ENDL;
- loadAsset();
- }
- void LLPreviewNotecard::loadAsset()
- {
- // Request the asset.
- const LLInventoryItem* item = getItem();
- if (!item)
- {
- if (mObjectUUID.notNull() && mItemUUID.notNull())
- {
- LLViewerObject* objectp = gObjectList.findObject(mObjectUUID);
- if (objectp &&
- (objectp->isInventoryPending() || objectp->isInventoryDirty()))
- {
- // It is a notecard in an object inventory and we failed to get
- // it because inventory is not up to date. Subscribe for
- // callback and retry at inventoryChanged().
- // This also removes any previous listener:
- registerVOInventoryListener(objectp, NULL);
- if (objectp->isInventoryDirty())
- {
- objectp->requestInventory();
- }
- return;
- }
- }
- mEditor->setText(LLStringUtil::null);
- mEditor->makePristine();
- mEditor->setEnabled(true);
- #if 0 // Do not set the asset status here: we may not have set the item Id
- // yet (e.g. when this gets called initially)
- mAssetStatus = PREVIEW_ASSET_LOADED;
- #endif
- return;
- }
- if (gAgent.isGodlike() ||
- gAgent.allowOperation(PERM_COPY, item->getPermissions(),
- GP_OBJECT_MANIPULATE))
- {
- mAssetID = item->getAssetUUID();
- if (mAssetID.isNull())
- {
- mEditor->setText(LLStringUtil::null);
- mEditor->makePristine();
- mEditor->setEnabled(true);
- mAssetStatus = PREVIEW_ASSET_LOADED;
- }
- else if (gAssetStoragep)
- {
- LLHost source_sim = LLHost();
- if (mObjectUUID.notNull())
- {
- LLViewerObject* objectp = gObjectList.findObject(mObjectUUID);
- if (objectp && objectp->getRegion())
- {
- source_sim = objectp->getRegion()->getHost();
- }
- else
- {
- // The object that we are trying to look at
- // disappeared: bail out.
- llwarns << "Cannot find object " << mObjectUUID
- << " associated with notecard." << llendl;
- mAssetID.setNull();
- mEditor->setText(getString("no_object"));
- mEditor->makePristine();
- mEditor->setEnabled(false);
- mAssetStatus = PREVIEW_ASSET_LOADED;
- return;
- }
- }
- gAssetStoragep->getInvItemAsset(source_sim,
- gAgentID, gAgentSessionID,
- item->getPermissions().getOwner(),
- mObjectUUID, item->getUUID(),
- item->getAssetUUID(),
- item->getType(), onLoadComplete,
- (void*)new LLUUID(mItemUUID),
- true);
- mAssetStatus = PREVIEW_ASSET_LOADING;
- }
- }
- else
- {
- mAssetID.setNull();
- mEditor->setText(getString("not_allowed"));
- mEditor->makePristine();
- mEditor->setEnabled(false);
- mAssetStatus = PREVIEW_ASSET_LOADED;
- }
- if (!canModify(mObjectUUID, item))
- {
- mEditor->setEnabled(false);
- mLockIcon->setVisible(true);
- }
- }
- bool LLPreviewNotecard::loadFile(const std::string& filename)
- {
- if (filename.empty())
- {
- return false;
- }
- std::ifstream file(filename.c_str());
- if (file.fail())
- {
- return false;
- }
- mEditor->clear();
- std::string line, text;
- while (!file.eof())
- {
- std::getline(file, line);
- text += line + "\n";
- }
- file.close();
- LLWString wtext = utf8str_to_wstring(text);
- LLWStringUtil::replaceTabsWithSpaces(wtext, 4);
- text = wstring_to_utf8str(wtext);
- mEditor->setText(text);
- return true;
- }
- bool LLPreviewNotecard::saveFile(std::string& filename)
- {
- if (filename.empty())
- {
- return false;
- }
- std::string lcname = filename;
- LLStringUtil::toLower(lcname);
- if (lcname.find(".txt") != lcname.length() - 4)
- {
- filename += ".txt";
- }
- std::ofstream file(filename.c_str());
- if (file.fail())
- {
- LLSD args;
- args["FILE"] = filename;
- gNotifications.add("CannotWriteFile", args);
- return false;
- }
- file << mEditor->getText();
- file.close();
- return true;
- }
- //static
- void LLPreviewNotecard::onLoadComplete(const LLUUID& asset_id,
- LLAssetType::EType type, void* userdata,
- S32 status, LLExtStat)
- {
- LLUUID* item_id = (LLUUID*)userdata;
- LLPreviewNotecard* self = LLPreviewNotecard::getInstance(*item_id);
- delete item_id;
- if (!self)
- {
- return;
- }
- if (status)
- {
- gViewerStats.incStat(LLViewerStats::ST_DOWNLOAD_FAILED);
- if (status == LL_ERR_FILE_EMPTY ||
- status == LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE)
- {
- gNotifications.add("NotecardMissing");
- }
- else if (status == LL_ERR_INSUFFICIENT_PERMISSIONS)
- {
- gNotifications.add("NotecardNoPermissions");
- }
- else
- {
- gNotifications.add("UnableToLoadNotecard");
- }
- self->mAssetStatus = PREVIEW_ASSET_ERROR;
- return;
- }
- S32 pos = 0;
- if (self->mEditor->getLength() > 0)
- {
- pos = self->mEditor->getCursorPos();
- }
- LLFileSystem file(asset_id);
- S32 file_length = file.getSize();
- char* bufferp = new char[file_length + 1];
- file.read((U8*)bufferp, file_length);
- // Put a EOS at the end
- bufferp[file_length] = 0;
- if (file_length > 19 && !strncmp(bufferp, "Linden text version", 19))
- {
- if (!self->mEditor->importBuffer(bufferp, file_length + 1))
- {
- llwarns << "Problem importing notecard" << llendl;
- }
- }
- else
- {
- // Version 0 (just text, does not include version number)
- self->mEditor->setText(std::string(bufferp));
- }
- delete[] bufferp;
- self->mEditor->makePristine();
- if (pos > 0)
- {
- self->mEditor->setCursorPos(pos);
- self->mEditor->scrollToPos(pos);
- }
- bool modifiable = canModify(self->mObjectUUID, self->getItem());
- self->setEnabled(modifiable);
- self->mAssetStatus = PREVIEW_ASSET_LOADED;
- }
- //static
- LLPreviewNotecard* LLPreviewNotecard::getInstance(const LLUUID& item_id)
- {
- preview_map_t::iterator it = LLPreview::sInstances.find(item_id);
- return it != LLPreview::sInstances.end() ? (LLPreviewNotecard*)it->second
- : NULL;
- }
- //static
- void LLPreviewNotecard::onClickSave(void* user_data)
- {
- LLPreviewNotecard* preview = (LLPreviewNotecard*)user_data;
- if (preview)
- {
- preview->saveIfNeeded();
- }
- }
- struct LLSaveNotecardInfo
- {
- LLSaveNotecardInfo(LLPreviewNotecard* self, const LLUUID& item_id,
- const LLUUID& object_id, const LLTransactionID& tid,
- LLInventoryItem* copyitem)
- : mSelf(self),
- mItemUUID(item_id),
- mObjectUUID(object_id),
- mTransactionID(tid),
- mCopyItem(copyitem)
- {
- }
- LLPreviewNotecard* mSelf;
- LLPointer<LLInventoryItem> mCopyItem;
- LLUUID mItemUUID;
- LLUUID mObjectUUID;
- LLTransactionID mTransactionID;
- };
- bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
- {
- if (mEditor->isPristine())
- {
- return true;
- }
- std::string buffer;
- if (!mEditor->exportBuffer(buffer))
- {
- return false;
- }
- mEditor->makePristine();
- if (mExternalEditor && mExternalEditor->running() && !mTempFilename.empty())
- {
- // Do not cause a file changed event for something we trigger ourselves
- // (the external editor will cause a file access read event, which is
- // considered a changed event, and would cause HBExternalEditor to call
- // our own changed file event, which we do not want to happen here).
- mExternalEditor->ignoreNextUpdate();
- saveFile(mTempFilename);
- }
- // Save it out to database
- const LLInventoryItem* item = getItem();
- if (!item)
- {
- return true;
- }
- // First try via HTTP capabilities.
- const std::string* urlp = NULL;
- LLResourceUploadInfo::ptr_t infop;
- if (mObjectUUID.isNull())
- {
- const std::string& inv_url =
- gAgent.getRegionCapability("UpdateNotecardAgentInventory");
- if (!inv_url.empty())
- {
- // Saving into agent inventory
- urlp = &inv_url;
- infop = std::make_shared<LLBufferedAssetUploadInfo>(
- mItemUUID, LLAssetType::AT_NOTECARD, buffer,
- boost::bind(&LLPreviewNotecard::finishInventoryUpload,
- _1, _2, _3));
- }
- }
- else
- {
- const std::string& task_url =
- gAgent.getRegionCapability("UpdateNotecardTaskInventory");
- if (!task_url.empty())
- {
- // Saving into task inventory
- urlp = &task_url;
- infop = std::make_shared<LLBufferedAssetUploadInfo>(
- mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD,
- buffer,
- boost::bind(&LLPreviewNotecard::finishTaskUpload,
- _1, _3));
- }
- }
- if (urlp && infop)
- {
- mAssetStatus = PREVIEW_ASSET_LOADING;
- setEnabled(false);
- LLViewerAssetUpload::enqueueInventoryUpload(*urlp, infop);
- return true;
- }
- // Legacy UDP upload path.
- if (gAssetStoragep)
- {
- // We need to update the asset information
- LLTransactionID tid;
- tid.generate();
- LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
- LLFileSystem file(asset_id, LLFileSystem::APPEND);
- S32 size = buffer.length() + 1;
- if (!file.write((U8*)buffer.c_str(), size))
- {
- llwarns << "Failure to write cache file for asset: " << mAssetID
- << llendl;
- return false;
- }
- LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID,
- mObjectUUID, tid,
- copyitem);
- gAssetStoragep->storeAssetData(tid, LLAssetType::AT_NOTECARD,
- onSaveComplete, (void*)info, false);
- return true;
- }
- llwarns << "No capability neither asset storage system. Could not save notecard: "
- << mAssetID << llendl;
- return false;
- }
- //static
- void LLPreviewNotecard::finishTaskUpload(LLUUID item_id, LLUUID new_asset_id)
- {
- LLPreviewNotecard* self = LLPreviewNotecard::getInstance(item_id);
- if (self)
- {
- if (self->hasEmbeddedInventory())
- {
- LLFileSystem::removeFile(new_asset_id);
- }
- self->setAssetId(new_asset_id);
- self->refreshFromInventory();
- }
- }
- //static
- void LLPreviewNotecard::finishInventoryUpload(LLUUID item_id,
- LLUUID new_asset_id,
- LLUUID new_item_id)
- {
- // Update the UI with the new asset.
- LLPreviewNotecard* self = LLPreviewNotecard::getInstance(item_id);
- if (self)
- {
- // *HACK: we have to delete the asset in the cache so that the viewer
- // will re-download it. This is only really necessary if the asset had
- // to be modified by the uploader, so this can be optimized away in
- // some cases. A better design is to have a new uuid if the notecard
- // actually changed the asset.
- if (self->hasEmbeddedInventory())
- {
- LLFileSystem::removeFile(new_asset_id);
- }
- if (new_item_id.isNull())
- {
- self->setAssetId(new_asset_id);
- self->refreshFromInventory();
- }
- else
- {
- self->setItemID(new_item_id);
- self->refreshFromInventory();
- }
- }
- }
- //static
- void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_id, void* user_data,
- S32 status, LLExtStat)
- {
- LLSaveNotecardInfo* info = (LLSaveNotecardInfo*)user_data;
- if (info && status == 0)
- {
- if (info->mObjectUUID.isNull())
- {
- LLViewerInventoryItem* item;
- item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID);
- if (item)
- {
- LLPointer<LLViewerInventoryItem> new_item =
- new LLViewerInventoryItem(item);
- new_item->setAssetUUID(asset_id);
- new_item->setTransactionID(info->mTransactionID);
- new_item->updateServer(false);
- gInventory.updateItem(new_item);
- gInventory.notifyObservers();
- }
- else
- {
- llwarns << "Inventory item for notecard " << info->mItemUUID
- << " is no longer in agent inventory." << llendl;
- }
- }
- else
- {
- LLViewerObject* object = gObjectList.findObject(info->mObjectUUID);
- LLViewerInventoryItem* item = NULL;
- if (object)
- {
- LLInventoryObject* inv_obj =
- object->getInventoryObject(info->mItemUUID);
- item = (LLViewerInventoryItem*)inv_obj;
- }
- if (item)
- {
- item->setAssetUUID(asset_id);
- item->setTransactionID(info->mTransactionID);
- object->updateInventory(item);
- dialog_refresh_all();
- }
- else
- {
- gNotifications.add("SaveNotecardFailObjectNotFound");
- }
- }
- // Perform item copy to inventory
- if (info->mCopyItem.notNull() && info->mSelf && info->mSelf->mEditor)
- {
- info->mSelf->mEditor->copyInventory(info->mCopyItem);
- }
- // Find our window and close it if requested.
- LLPreviewNotecard* previewp =
- (LLPreviewNotecard*)LLPreview::find(info->mItemUUID);
- if (previewp && previewp->mCloseAfterSave)
- {
- previewp->close();
- }
- }
- else
- {
- LLSD args;
- args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- gNotifications.add("SaveNotecardFailReason", args);
- }
- std::string filename = gDirUtil.getFullPath(LL_PATH_CACHE,
- asset_id.asString());
- LLFile::remove(filename + ".tmp");
- delete info;
- }
- bool LLPreviewNotecard::handleSaveChangesDialog(const LLSD& notification,
- const LLSD& response)
- {
- mSaveDialogShown = false;
- S32 option = LLNotification::getSelectedOption(notification, response);
- switch (option)
- {
- case 0: // "Yes"
- mCloseAfterSave = true;
- onClickSave((void*)this);
- break;
- case 1: // "No"
- mForceClose = true;
- close();
- break;
- case 2: // "Cancel"
- default:
- // If we were quitting, we did not really mean it.
- gAppViewerp->abortQuit();
- }
- return false;
- }
- void LLPreviewNotecard::reshape(S32 width, S32 height, bool called_from_parent)
- {
- LLPreview::reshape(width, height, called_from_parent);
- if (!isMinimized())
- {
- // So that next time you open a notecard it will have the same height
- // and width (although not the same position).
- gSavedSettings.setRect("NotecardEditorRect", getRect());
- }
- }
- //static
- bool LLPreviewNotecard::hasChanged(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->getEnabled() && !self->mEditor->isPristine();
- }
- //static
- bool LLPreviewNotecard::enableSaveLoadFile(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->getEnabled() && !HBFileSelector::isInUse();
- }
- //static
- void LLPreviewNotecard::loadFromFileCallback(HBFileSelector::ELoadFilter,
- std::string& filename,
- void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (!self || !sInstances.count(self))
- {
- gNotifications.add("LoadNoteAborted");
- return;
- }
- if (!self->loadFile(filename))
- {
- LLSD args;
- args["FILE"] = filename;
- gNotifications.add("CannotReadFile", args);
- }
- }
- //static
- void LLPreviewNotecard::onLoadFromFile(void* userdata)
- {
- HBFileSelector::loadFile(HBFileSelector::FFLOAD_TEXT, loadFromFileCallback,
- userdata);
- }
- //static
- void LLPreviewNotecard::saveToFileCallback(HBFileSelector::ESaveFilter,
- std::string& filename,
- void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self && sInstances.count(self))
- {
- self->saveFile(filename);
- }
- else
- {
- gNotifications.add("SaveNoteAborted");
- }
- }
- //static
- void LLPreviewNotecard::onSaveToFile(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self && sInstances.count(self))
- {
- std::string suggestion = self->mNoteName + ".txt";
- HBFileSelector::saveFile(HBFileSelector::FFSAVE_TXT, suggestion,
- saveToFileCallback, userdata);
- }
- }
- //static
- void LLPreviewNotecard::onEditedFileChanged(const std::string& filename,
- void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self && sInstances.count(self))
- {
- if (filename == self->mTempFilename)
- {
- self->loadFile(filename);
- }
- else
- {
- llwarns << "Watched file (" << filename
- << ") and auto-saved file (" << self->mTempFilename
- << ") do not match !" << llendl;
- }
- }
- }
- //static
- void LLPreviewNotecard::onEditExternal(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self && sInstances.count(self))
- {
- if (self->mTempFilename.empty())
- {
- self->mTempFilename = gDirUtil.getTempFilename(false) + ".txt";
- }
- if (!self->saveFile(self->mTempFilename))
- {
- return;
- }
- if (self->mExternalEditor)
- {
- self->mExternalEditor->kill();
- }
- else
- {
- self->mExternalEditor = new HBExternalEditor(onEditedFileChanged,
- self);
- }
- if (!self->mExternalEditor->open(self->mTempFilename))
- {
- LLSD args;
- args["MESSAGE"] = self->mExternalEditor->getErrorMessage();
- gNotifications.add("GenericAlert", args);
- }
- }
- }
- //static
- void LLPreviewNotecard::onSearchMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- LLFloaterSearchReplace::show(self->mEditor);
- }
- }
- //static
- void LLPreviewNotecard::onUndoMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->undo();
- }
- }
- //static
- void LLPreviewNotecard::onRedoMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->redo();
- }
- }
- //static
- void LLPreviewNotecard::onCutMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->cut();
- }
- }
- //static
- void LLPreviewNotecard::onCopyMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->copy();
- }
- }
- //static
- void LLPreviewNotecard::onPasteMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->paste();
- }
- }
- //static
- void LLPreviewNotecard::onSelectAllMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->selectAll();
- }
- }
- //static
- void LLPreviewNotecard::onDeselectMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->deselect();
- }
- }
- //static
- void LLPreviewNotecard::onSpellCheckMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- if (self)
- {
- self->mEditor->setSpellCheck(!self->mEditor->getSpellCheck());
- }
- }
- //static
- bool LLPreviewNotecard::enableUndoMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->canUndo();
- }
- //static
- bool LLPreviewNotecard::enableRedoMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->canRedo();
- }
- //static
- bool LLPreviewNotecard::enableCutMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->canCut();
- }
- //static
- bool LLPreviewNotecard::enableCopyMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->canCopy();
- }
- //static
- bool LLPreviewNotecard::enablePasteMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->canPaste();
- }
- //static
- bool LLPreviewNotecard::enableSelectAllMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->canSelectAll();
- }
- //static
- bool LLPreviewNotecard::enableDeselectMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->canDeselect();
- }
- //static
- bool LLPreviewNotecard::enableSpellCheckMenu(void* userdata)
- {
- return LLSpellCheck::getInstance()->getSpellCheck();
- }
- //static
- bool LLPreviewNotecard::checkSpellCheckMenu(void* userdata)
- {
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
- return self && self->mEditor->getSpellCheck() &&
- LLSpellCheck::getInstance()->getSpellCheck();
- }
- //static
- void LLPreviewNotecard::onSetFontName(void* userdata)
- {
- CallbackData* datap = (CallbackData*)userdata;
- LLPreviewNotecard* self = datap->mFloater;
- LLFontGL* fontp = self->mEditor->getFont();
- if (!fontp) // Paranoia
- {
- return;
- }
- std::string font_name = datap->mCheck->getName() +
- fontp->getFontDesc().getSize();
- fontp = LLFontGL::getFont(font_name.c_str());
- if (fontp)
- {
- self->mEditor->setFont(fontp);
- }
- }
- //static
- bool LLPreviewNotecard::checkFontName(void* userdata)
- {
- CallbackData* datap = (CallbackData*)userdata;
- LLPreviewNotecard* self = datap->mFloater;
- LLFontGL* fontp = self->mEditor->getFont();
- #if LL_WINDOWS
- std::string font_name = datap->mCheck->getName();
- // Under Windows, font names are lower-cased because they are compared with
- // file names which are case-insensitive...
- LLStringUtil::toLower(font_name);
- return fontp && fontp->getFontDesc().getName() == font_name;
- #else
- return fontp && fontp->getFontDesc().getName() == datap->mCheck->getName();
- #endif
- }
- //static
- void LLPreviewNotecard::onSetFontSize(void* userdata)
- {
- CallbackData* datap = (CallbackData*)userdata;
- LLPreviewNotecard* self = datap->mFloater;
- LLFontGL* fontp = self->mEditor->getFont();
- if (!fontp) // Paranoia
- {
- return;
- }
- std::string font_name = fontp->getFontDesc().getName() +
- datap->mCheck->getName();
- fontp = LLFontGL::getFont(font_name.c_str());
- if (fontp)
- {
- self->mEditor->setFont(fontp);
- }
- }
- //static
- bool LLPreviewNotecard::checkFontSize(void* userdata)
- {
- CallbackData* datap = (CallbackData*)userdata;
- LLPreviewNotecard* self = datap->mFloater;
- LLFontGL* fontp = self->mEditor->getFont();
- return fontp && fontp->getFontDesc().getSize() == datap->mCheck->getName();
- }
|