From d90716cce41f6640725f5c175d68464c4c8ec156 Mon Sep 17 00:00:00 2001
From: cinder <cinder@cinderblocks.biz>
Date: Mon, 12 Dec 2022 11:08:18 -0600
Subject: [PATCH] Revive picks/classifieds in Legacy Profiles

---
 indra/llmessage/llclassifiedflags.h           |   1 +
 indra/newview/CMakeLists.txt                  |   8 +
 indra/newview/llclassifieditem.cpp            | 119 ++++
 indra/newview/llclassifieditem.h              |  83 +++
 indra/newview/llfloaterpublishclassified.cpp  |  63 ++
 indra/newview/llfloaterpublishclassified.h    |  48 ++
 indra/newview/llpanelclassified.cpp           | 596 ++++++++++++++++-
 indra/newview/llpanelclassified.h             | 118 +++-
 indra/newview/llpanelpick.cpp                 | 612 ++++++++++++++++++
 indra/newview/llpanelpick.h                   | 255 ++++++++
 indra/newview/llpanelprofileclassifieds.cpp   |  55 +-
 indra/newview/llpanelprofileclassifieds.h     |  24 +-
 indra/newview/llpanelprofilelegacy.cpp        |  23 +-
 indra/newview/llpanelprofilelegacy.h          |  11 +-
 indra/newview/llpickitem.cpp                  | 155 +++++
 indra/newview/llpickitem.h                    |  85 +++
 indra/newview/llviewerfloaterreg.cpp          |   4 +-
 .../default/xui/en/panel_classified_info.xml  |  37 +-
 .../skins/default/xui/en/panel_edit_pick.xml  | 237 +++++++
 .../skins/default/xui/en/panel_pick_info.xml  | 190 ++++++
 .../xui/en/panel_profile_legacy_sidetray.xml  |   4 +-
 21 files changed, 2610 insertions(+), 118 deletions(-)
 create mode 100644 indra/newview/llclassifieditem.cpp
 create mode 100644 indra/newview/llclassifieditem.h
 create mode 100644 indra/newview/llfloaterpublishclassified.cpp
 create mode 100644 indra/newview/llfloaterpublishclassified.h
 create mode 100644 indra/newview/llpanelpick.cpp
 create mode 100644 indra/newview/llpanelpick.h
 create mode 100644 indra/newview/llpickitem.cpp
 create mode 100644 indra/newview/llpickitem.h
 create mode 100644 indra/newview/skins/default/xui/en/panel_edit_pick.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_pick_info.xml

diff --git a/indra/llmessage/llclassifiedflags.h b/indra/llmessage/llclassifiedflags.h
index 17fc8674534..05a214f5cea 100644
--- a/indra/llmessage/llclassifiedflags.h
+++ b/indra/llmessage/llclassifiedflags.h
@@ -47,6 +47,7 @@ const U8 CLASSIFIED_QUERY_INC_ADULT			= 1 << 6;
 const U8 CLASSIFIED_QUERY_INC_NEW_VIEWER	= (CLASSIFIED_QUERY_INC_PG | CLASSIFIED_QUERY_INC_MATURE | CLASSIFIED_QUERY_INC_ADULT);
 
 const S32 MAX_CLASSIFIEDS = 100;
+const S32 MINIMUM_PRICE_FOR_LISTING = 50;  // L$
 
 // This function is used in AO viewers to pack old query flags into the request 
 // so that they can talk to old dataservers properly. When the AO servers are deployed on agni
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8f93a855a76..5c954f41f92 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -190,6 +190,7 @@ set(viewer_SOURCE_FILES
     llchiclet.cpp
     llchicletbar.cpp
     llclassifiedinfo.cpp
+    llclassifieditem.cpp
     llcofwearables.cpp
     llcolorswatch.cpp
     llcommanddispatcherlistener.cpp
@@ -350,6 +351,7 @@ set(viewer_SOURCE_FILES
     llfloaterprofiletexture.cpp
     llfloaterprogressview.cpp
     llfloaterproperties.cpp
+    llfloaterpublishclassified.cpp
     llfloaterregiondebugconsole.cpp
     llfloaterregioninfo.cpp
     llfloaterreporter.cpp
@@ -540,6 +542,7 @@ set(viewer_SOURCE_FILES
     llpanelpeople.cpp
     llpanelpeoplemenus.cpp
     llpanelpermissions.cpp
+    llpanelpick.cpp
     llpanelplaceinfo.cpp
     llpanelplaceprofile.cpp
     llpanelplaces.cpp
@@ -591,6 +594,7 @@ set(viewer_SOURCE_FILES
     llpersistentnotificationstorage.cpp
     llphysicsmotion.cpp
     llphysicsshapebuilderutil.cpp
+    llpickitem.cpp
     llpipelinelistener.cpp
     llplacesinventorybridge.cpp
     llplacesinventorypanel.cpp
@@ -892,6 +896,7 @@ set(viewer_HEADER_FILES
     llchiclet.h
     llchicletbar.h
     llclassifiedinfo.h
+    llclassifieditem.h
     llcofwearables.h
     llcolorswatch.h
     llcommanddispatcherlistener.h
@@ -1055,6 +1060,7 @@ set(viewer_HEADER_FILES
     llfloaterprofiletexture.h
     llfloaterprogressview.h
     llfloaterproperties.h
+    llfloaterpublishclassified.h
     llfloaterregiondebugconsole.h
     llfloaterregioninfo.h
     llfloaterreporter.h
@@ -1235,6 +1241,7 @@ set(viewer_HEADER_FILES
     llpanelpeople.h
     llpanelpeoplemenus.h
     llpanelpermissions.h
+    llpanelpick.h
     llpanelplaceinfo.h
     llpanelplaceprofile.h
     llpanelplaces.h
@@ -1281,6 +1288,7 @@ set(viewer_HEADER_FILES
     llpersistentnotificationstorage.h
     llphysicsmotion.h
     llphysicsshapebuilderutil.h
+    llpickitem.h
     llpipelinelistener.h
     llplacesinventorybridge.h
     llplacesinventorypanel.h
diff --git a/indra/newview/llclassifieditem.cpp b/indra/newview/llclassifieditem.cpp
new file mode 100644
index 00000000000..56edc65c8de
--- /dev/null
+++ b/indra/newview/llclassifieditem.cpp
@@ -0,0 +1,119 @@
+/**
+* @file llclassifieditem.cpp
+* @brief Widget
+*
+* $LicenseInfo:firstyear=2009&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llclassifieditem.h"
+
+#include "llpanelclassified.h"
+
+LLClassifiedItem::LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id)
+	: LLPanel()
+	, mAvatarId(avatar_id)
+	, mClassifiedId(classified_id)
+{
+	buildFromFile("panel_classifieds_list_item.xml");
+
+	LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this);
+	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId());
+}
+
+LLClassifiedItem::~LLClassifiedItem()
+{
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+void LLClassifiedItem::processProperties(void* data, EAvatarProcessorType type)
+{
+	if (APT_CLASSIFIED_INFO != type)
+	{
+		return;
+	}
+
+	LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+	if (!c_info || c_info->classified_id != getClassifiedId())
+	{
+		return;
+	}
+
+	setClassifiedName(c_info->name);
+	setDescription(c_info->description);
+	setSnapshotId(c_info->snapshot_id);
+	setPosGlobal(c_info->pos_global);
+
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+BOOL LLClassifiedItem::postBuild()
+{
+	setMouseEnterCallback(std::bind(&set_child_visible, this, "hovered_icon", true));
+	setMouseLeaveCallback(std::bind(&set_child_visible, this, "hovered_icon", false));
+	return TRUE;
+}
+
+void LLClassifiedItem::setValue(const LLSD& value)
+{
+	if (!value.isMap()) return;;
+	if (!value.has("selected")) return;
+	getChildView("selected_icon")->setVisible(value["selected"]);
+}
+
+void LLClassifiedItem::fillIn(LLPanelClassifiedEdit* panel)
+{
+	if (!panel)
+	{
+		return;
+	}
+
+	setClassifiedName(panel->getClassifiedName());
+	setDescription(panel->getDescription());
+	setSnapshotId(panel->getSnapshotId());
+	setCategory(panel->getCategory());
+	setContentType(panel->getContentType());
+	setAutoRenew(panel->getAutoRenew());
+	setPriceForListing(panel->getPriceForListing());
+	setPosGlobal(panel->getPosGlobal());
+	setLocationText(panel->getClassifiedLocation());
+}
+
+void LLClassifiedItem::setClassifiedName(const std::string& name)
+{
+	getChild<LLUICtrl>("name")->setValue(name);
+}
+
+void LLClassifiedItem::setDescription(const std::string& desc)
+{
+	getChild<LLUICtrl>("description")->setValue(desc);
+}
+
+void LLClassifiedItem::setSnapshotId(const LLUUID& snapshot_id)
+{
+	getChild<LLUICtrl>("picture")->setValue(snapshot_id);
+}
+
+LLUUID LLClassifiedItem::getSnapshotId() const
+{
+	return getChild<LLUICtrl>("picture")->getValue();
+}
diff --git a/indra/newview/llclassifieditem.h b/indra/newview/llclassifieditem.h
new file mode 100644
index 00000000000..627632efa92
--- /dev/null
+++ b/indra/newview/llclassifieditem.h
@@ -0,0 +1,83 @@
+/**
+* @file llclassifieditem.h
+* @brief Widget
+*
+* $LicenseInfo:firstyear=2009&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_CLASSIFIEDITEM_H
+#define LL_CLASSIFIEDITEM_H
+
+#include "llavatarpropertiesprocessor.h"
+#include "llpanel.h"
+
+class LLPanelClassifiedEdit;
+
+static const std::string CLASSIFIED_ID("classified_id");
+static const std::string CLASSIFIED_NAME("classified_name");
+
+class LLClassifiedItem final : public LLPanel, public LLAvatarPropertiesObserver
+{
+public:
+
+	LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id);
+	virtual ~LLClassifiedItem();
+
+	void processProperties(void* data, EAvatarProcessorType type) override;
+	BOOL postBuild() override;
+	void setValue(const LLSD& value) override;
+	void fillIn(LLPanelClassifiedEdit* panel);
+	LLUUID getAvatarId() const { return mAvatarId; }
+	void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+	LLUUID getClassifiedId() const { return mClassifiedId; }
+	void setClassifiedId(const LLUUID& classified_id) { mClassifiedId = classified_id; }
+	void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
+	const LLVector3d getPosGlobal() const { return mPosGlobal; }
+	void setLocationText(const std::string location) { mLocationText = std::move(location); }
+	std::string getLocationText() const { return mLocationText; }
+	void setClassifiedName(const std::string& name);
+	std::string getClassifiedName() const { return getChild<LLUICtrl>("name")->getValue().asString(); }
+	void setDescription(const std::string& desc);
+	std::string getDescription() const { return getChild<LLUICtrl>("description")->getValue().asString(); }
+	void setSnapshotId(const LLUUID& snapshot_id);
+	LLUUID getSnapshotId() const;
+	void setCategory(U32 cat) { mCategory = cat; }
+	U32 getCategory() const { return mCategory; }
+	void setContentType(U32 ct) { mContentType = ct; }
+	U32 getContentType() const { return mContentType; }
+	void setAutoRenew(U32 renew) { mAutoRenew = renew; }
+	bool getAutoRenew() const { return mAutoRenew; }
+	void setPriceForListing(S32 price) { mPriceForListing = price; }
+	S32 getPriceForListing() const { return mPriceForListing; }
+
+private:
+	LLUUID mAvatarId;
+	LLUUID mClassifiedId;
+	LLVector3d mPosGlobal;
+	std::string mLocationText;
+	U32 mCategory;
+	U32 mContentType;
+	bool mAutoRenew;
+	S32 mPriceForListing;
+};
+
+#endif // LL_CLASSIFIEDITEM_H
diff --git a/indra/newview/llfloaterpublishclassified.cpp b/indra/newview/llfloaterpublishclassified.cpp
new file mode 100644
index 00000000000..b19cc8f97e2
--- /dev/null
+++ b/indra/newview/llfloaterpublishclassified.cpp
@@ -0,0 +1,63 @@
+/**
+ * @file llfloaterpublishclassified.cpp
+ * @brief Publish classified floater
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaterpublishclassified.h"
+
+LLFloaterPublishClassified::LLFloaterPublishClassified(const LLSD& key)
+    : LLFloater(key)
+{
+}
+
+BOOL LLFloaterPublishClassified::postBuild()
+{
+    LLFloater::postBuild();
+
+    childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false));
+    childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false));
+
+    return TRUE;
+}
+
+void LLFloaterPublishClassified::setPrice(S32 price)
+{
+    getChild<LLUICtrl>("price_for_listing")->setValue(price);
+}
+
+S32 LLFloaterPublishClassified::getPrice()
+{
+    return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger();
+}
+
+void LLFloaterPublishClassified::setPublishClickedCallback(const commit_signal_t::slot_type& cb)
+{
+    getChild<LLButton>("publish_btn")->setClickedCallback(cb);
+}
+
+void LLFloaterPublishClassified::setCancelClickedCallback(const commit_signal_t::slot_type& cb)
+{
+    getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
+}
diff --git a/indra/newview/llfloaterpublishclassified.h b/indra/newview/llfloaterpublishclassified.h
new file mode 100644
index 00000000000..f5d79656119
--- /dev/null
+++ b/indra/newview/llfloaterpublishclassified.h
@@ -0,0 +1,48 @@
+/**
+ * @file llfloaterpublishclassified.h
+ * @brief Publish classified floater
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_PUBLISHCLASSIFIEDFLOATER_H
+#define LL_PUBLISHCLASSIFIEDFLOATER_H
+
+#include "llfloater.h"
+
+class LLFloaterPublishClassified final : public LLFloater
+{
+public:
+    LLFloaterPublishClassified(const LLSD& key);
+    ~LLFloaterPublishClassified() override = default;
+
+    BOOL postBuild() override;
+
+    void setPrice(S32 price);
+    S32 getPrice();
+
+    void setPublishClickedCallback(const commit_signal_t::slot_type& cb);
+    void setCancelClickedCallback(const commit_signal_t::slot_type& cb);
+};
+
+#endif // LL_PUBLISHCLASSIFIEDFLOATER_H
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index b0a26cf9be8..a629d2b00a7 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -34,16 +34,27 @@
 
 #include "lldispatcher.h"
 #include "llfloaterreg.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
 #include "llparcel.h"
 
 #include "llagent.h"
 #include "llclassifiedflags.h"
+#include "llclassifiedinfo.h"
 #include "lliconctrl.h"
+#include "lllineeditor.h"
+#include "llcombobox.h"
+#include "lllogininstance.h"
 #include "lltexturectrl.h"
+#include "lltexteditor.h"
+#include "llviewerparcelmgr.h"
 #include "llfloaterworldmap.h"
 #include "llviewergenericmessage.h"	// send_generic_message
 #include "llviewerregion.h"
+#include "llviewertexture.h"
+#include "lltrans.h"
 #include "llscrollcontainer.h"
+#include "llstatusbar.h"
 #include "llcorehttputil.h"
 
 //static
@@ -82,6 +93,8 @@ static LLDispatchClassifiedClickThrough sClassifiedClickThrough;
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
+static LLPanelInjector<LLPanelClassifiedInfo> t_classified_info("panel_classified_info");
+
 LLPanelClassifiedInfo::LLPanelClassifiedInfo()
  : LLPanel()
  , mInfoLoaded(false)
@@ -106,8 +119,17 @@ LLPanelClassifiedInfo::~LLPanelClassifiedInfo()
 	sAllPanels.remove(this);
 }
 
+// static
+LLPanelClassifiedInfo* LLPanelClassifiedInfo::create()
+{
+	LLPanelClassifiedInfo* panel = new LLPanelClassifiedInfo();
+	panel->buildFromFile("panel_classified_info.xml");
+	return panel;
+}
+
 BOOL LLPanelClassifiedInfo::postBuild()
 {
+	childSetAction("back_btn", boost::bind(&LLPanelClassifiedInfo::onExit, this));
 	childSetAction("show_on_map_btn", boost::bind(&LLPanelClassifiedInfo::onMapClick, this));
 	childSetAction("teleport_btn", boost::bind(&LLPanelClassifiedInfo::onTeleportClick, this));
 
@@ -123,6 +145,16 @@ BOOL LLPanelClassifiedInfo::postBuild()
 	return TRUE;
 }
 
+void LLPanelClassifiedInfo::setExitCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("back_btn")->setClickedCallback(cb);
+}
+
+void LLPanelClassifiedInfo::setEditClassifiedCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("edit_btn")->setClickedCallback(cb);
+}
+
 void LLPanelClassifiedInfo::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
 {
 	LLPanel::reshape(width, height, called_from_parent);
@@ -151,7 +183,7 @@ void LLPanelClassifiedInfo::onOpen(const LLSD& key)
 	LLUUID avatar_id = key["classified_creator_id"];
 	if(avatar_id.isNull())
 	{
-		return;
+		//return;
 	}
 
 	if(getAvatarId().notNull())
@@ -254,9 +286,11 @@ void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType t
 			LLStringUtil::format(date_str, LLSD().with("datetime", (S32) c_info->creation_date));
 			getChild<LLUICtrl>("creation_date")->setValue(date_str);
 
-			setInfoLoaded(true);
+			date_str = date_fmt;
+			LLStringUtil::format(date_str, LLSD().with("datetime", (S32) c_info->expiration_date));
+			getChild<LLUICtrl>("expiration_date")->setValue(date_str);
 
-			LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+			setInfoLoaded(true);
 		}
 	}
 }
@@ -367,10 +401,9 @@ void LLPanelClassifiedInfo::setClickThrough(
 			<< teleport << ", " << map << ", " << profile << "] ("
 			<< (from_new_table ? "new" : "old") << ")" << LL_ENDL;
 
-	for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
-	{
-		LLPanelClassifiedInfo* self = *iter;
-		if (self->getClassifiedId() != classified_id)
+	for (auto self : sAllPanels)
+    {
+        if (self->getClassifiedId() != classified_id)
 		{
 			continue;
 		}
@@ -561,4 +594,551 @@ void LLPanelClassifiedInfo::onTeleportClick()
 	}
 }
 
-//EOF
+void LLPanelClassifiedInfo::onExit()
+{
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+	gGenericDispatcher.addHandler("classifiedclickthrough", nullptr); // deregister our handler
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+static const S32 CB_ITEM_MATURE = 0;
+static const S32 CB_ITEM_PG	   = 1;
+
+LLPanelClassifiedEdit::LLPanelClassifiedEdit()
+ : LLPanelClassifiedInfo()
+ , mIsNew(false)
+ , mIsNewWithErrors(false)
+ , mCanClose(false)
+ , mPublishFloater(nullptr)
+{
+}
+
+LLPanelClassifiedEdit::~LLPanelClassifiedEdit()
+{
+}
+
+//static
+LLPanelClassifiedEdit* LLPanelClassifiedEdit::create()
+{
+	LLPanelClassifiedEdit* panel = new LLPanelClassifiedEdit();
+	panel->buildFromFile("panel_edit_classified.xml");
+	return panel;
+}
+
+BOOL LLPanelClassifiedEdit::postBuild()
+{
+	LLPanelClassifiedInfo::postBuild();
+
+	LLUICtrl* edit_icon = getChild<LLUICtrl>("edit_icon");
+	mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseEnter, this, edit_icon));
+	mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseLeave, this, edit_icon));
+	edit_icon->setVisible(false);
+
+	LLLineEditor* line_edit = getChild<LLLineEditor>("classified_name");
+	line_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this), nullptr);
+
+	LLTextEditor* text_edit = getChild<LLTextEditor>("classified_desc");
+	text_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this));
+
+	LLComboBox* combobox = getChild<LLComboBox>( "category");
+	LLClassifiedInfo::cat_map::iterator iter;
+	for (iter = LLClassifiedInfo::sCategories.begin();
+		iter != LLClassifiedInfo::sCategories.end();
+		iter++)
+	{
+		combobox->add(LLTrans::getString(iter->second));
+	}
+
+	combobox->setCommitCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this));
+
+	childSetCommitCallback("content_type", boost::bind(&LLPanelClassifiedEdit::onChange, this), nullptr);
+	childSetCommitCallback("price_for_listing", boost::bind(&LLPanelClassifiedEdit::onChange, this), nullptr);
+	childSetCommitCallback("auto_renew", boost::bind(&LLPanelClassifiedEdit::onChange, this), nullptr);
+
+	childSetAction("save_changes_btn", boost::bind(&LLPanelClassifiedEdit::onSaveClick, this));
+	childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelClassifiedEdit::onSetLocationClick, this));
+
+	mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onTextureSelected, this));
+
+	return TRUE;
+}
+
+void LLPanelClassifiedEdit::fillIn(const LLSD& key)
+{
+	setAvatarId(gAgent.getID());
+
+	if(key.isUndefined())
+	{
+		setPosGlobal(gAgent.getPositionGlobal());
+
+		LLUUID snapshot_id = LLUUID::null;
+		std::string desc;
+		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+		if(parcel)
+		{
+			desc = parcel->getDesc();
+			snapshot_id = parcel->getSnapshotID();
+		}
+
+		std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish");
+		LLViewerRegion* region = gAgent.getRegion();
+		if (region)
+		{
+			region_name = region->getName();
+		}
+
+		getChild<LLUICtrl>("classified_name")->setValue(makeClassifiedName());
+		getChild<LLUICtrl>("classified_desc")->setValue(desc);
+		setSnapshotId(snapshot_id);
+		setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal()));
+		// server will set valid parcel id
+		setParcelId(LLUUID::null);
+	}
+	else
+	{
+		setClassifiedId(key["classified_id"]);
+		setClassifiedName(key["name"]);
+		setDescription(key["desc"]);
+		setSnapshotId(key["snapshot_id"]);
+		setCategory((U32)key["category"].asInteger());
+		setContentType((U32)key["content_type"].asInteger());
+		setClassifiedLocation(key["location_text"]);
+		getChild<LLUICtrl>("auto_renew")->setValue(key["auto_renew"]);
+		getChild<LLUICtrl>("price_for_listing")->setValue(key["price_for_listing"].asInteger());
+	}
+}
+
+void LLPanelClassifiedEdit::onOpen(const LLSD& key)
+{
+	mIsNew = key.isUndefined();
+	
+	scrollToTop();
+
+	// classified is not created yet
+	bool is_new = isNew() || isNewWithErrors();
+
+	if(is_new)
+	{
+		resetData();
+		resetControls();
+
+		fillIn(key);
+
+		if(isNew())
+		{
+			LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this);
+		}
+	}
+	else
+	{
+		LLPanelClassifiedInfo::onOpen(key);
+	}
+
+	std::string save_btn_label = is_new ? getString("publish_label") : getString("save_label");
+	getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", save_btn_label);
+
+	enableVerbs(is_new);
+	enableEditing(is_new);
+	showEditing(!is_new);
+	resetDirty();
+	setInfoLoaded(false);
+}
+
+void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType type)
+{
+	if(APT_CLASSIFIED_INFO == type)
+	{
+		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+		if(c_info && getClassifiedId() == c_info->classified_id)
+		{
+			// see LLPanelClassifiedEdit::sendUpdate() for notes
+			mIsNewWithErrors = false;
+			// for just created classified - panel will probably be closed when we get here.
+			if(!getVisible())
+			{
+				return;
+			}
+
+			enableEditing(true);
+
+			setClassifiedName(c_info->name);
+			setDescription(c_info->description);
+			setSnapshotId(c_info->snapshot_id);
+			setParcelId(c_info->parcel_id);
+			setPosGlobal(c_info->pos_global);
+
+			setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global));
+			// *HACK see LLPanelClassifiedEdit::sendUpdate()
+			setCategory(c_info->category - 1);
+
+			bool mature = is_cf_mature(c_info->flags);
+			bool auto_renew = is_cf_auto_renew(c_info->flags);
+
+			setContentType(mature ? CB_ITEM_MATURE : CB_ITEM_PG);
+			getChild<LLUICtrl>("auto_renew")->setValue(auto_renew);
+			getChild<LLUICtrl>("price_for_listing")->setValue(c_info->price_for_listing);
+			getChildView("price_for_listing")->setEnabled(isNew());
+
+			resetDirty();
+			setInfoLoaded(true);
+			enableVerbs(false);
+
+			// for just created classified - in case user opened edit panel before processProperties() callback 
+			getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", getString("save_label"));
+		}
+	}
+}
+
+BOOL LLPanelClassifiedEdit::isDirty() const
+{
+	if(mIsNew) 
+	{
+		return TRUE;
+	}
+
+	BOOL dirty = false;
+
+	dirty |= LLPanelClassifiedInfo::isDirty();
+	dirty |= getChild<LLUICtrl>("classified_snapshot")->isDirty();
+	dirty |= getChild<LLUICtrl>("classified_name")->isDirty();
+	dirty |= getChild<LLUICtrl>("classified_desc")->isDirty();
+	dirty |= getChild<LLUICtrl>("category")->isDirty();
+	dirty |= getChild<LLUICtrl>("content_type")->isDirty();
+	dirty |= getChild<LLUICtrl>("auto_renew")->isDirty();
+	dirty |= getChild<LLUICtrl>("price_for_listing")->isDirty();
+
+	return dirty;
+}
+
+void LLPanelClassifiedEdit::resetDirty()
+{
+	LLPanelClassifiedInfo::resetDirty();
+	getChild<LLUICtrl>("classified_snapshot")->resetDirty();
+	getChild<LLUICtrl>("classified_name")->resetDirty();
+
+	LLTextEditor* desc = getChild<LLTextEditor>("classified_desc");
+	// call blockUndo() to really reset dirty(and make isDirty work as intended)
+	desc->blockUndo();
+	desc->resetDirty();
+
+	getChild<LLUICtrl>("category")->resetDirty();
+	getChild<LLUICtrl>("content_type")->resetDirty();
+	getChild<LLUICtrl>("auto_renew")->resetDirty();
+	getChild<LLUICtrl>("price_for_listing")->resetDirty();
+}
+
+void LLPanelClassifiedEdit::setSaveCallback(const commit_signal_t::slot_type& cb)
+{
+	mSaveButtonClickedSignal.connect(cb);
+}
+
+void LLPanelClassifiedEdit::setCancelCallback(const commit_signal_t::slot_type& cb)
+{
+	getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
+}
+
+void LLPanelClassifiedEdit::resetControls()
+{
+	LLPanelClassifiedInfo::resetControls();
+
+	getChild<LLComboBox>("category")->setCurrentByIndex(0);
+	getChild<LLComboBox>("content_type")->setCurrentByIndex(0);
+	getChild<LLUICtrl>("auto_renew")->setValue(false);
+	if (LLLoginInstance::getInstance()->hasResponse("classified_fee"))
+	{
+		getChild<LLUICtrl>("price_for_listing")->setValue(LLLoginInstance::getInstance()->
+														  getResponse("classified_fee").asInteger());
+	}
+	else
+	{
+		getChild<LLUICtrl>("price_for_listing")->setValue(MINIMUM_PRICE_FOR_LISTING);
+	}
+	getChildView("price_for_listing")->setEnabled(TRUE);
+}
+
+bool LLPanelClassifiedEdit::canClose()
+{
+	return mCanClose;
+}
+
+void LLPanelClassifiedEdit::draw()
+{
+	LLPanel::draw();
+
+	// Need to re-stretch on every draw because LLTextureCtrl::onSelectCallback
+	// does not trigger callbacks when user navigates through images.
+	stretchSnapshot();
+}
+
+void LLPanelClassifiedEdit::stretchSnapshot()
+{
+	LLPanelClassifiedInfo::stretchSnapshot();
+
+	getChild<LLUICtrl>("edit_icon")->setShape(mSnapshotCtrl->getRect());
+}
+
+U32 LLPanelClassifiedEdit::getContentType()
+{
+	LLComboBox* ct_cb = getChild<LLComboBox>("content_type");
+	return ct_cb->getCurrentIndex();
+}
+
+void LLPanelClassifiedEdit::setContentType(U32 content_type)
+{
+	LLComboBox* ct_cb = getChild<LLComboBox>("content_type");
+	ct_cb->setCurrentByIndex(content_type);
+	ct_cb->resetDirty();
+}
+
+bool LLPanelClassifiedEdit::getAutoRenew()
+{
+	return getChild<LLUICtrl>("auto_renew")->getValue().asBoolean();
+}
+
+void LLPanelClassifiedEdit::sendUpdate()
+{
+	LLAvatarClassifiedInfo c_data;
+
+	if(getClassifiedId().isNull())
+	{
+		setClassifiedId(LLUUID::generateNewID());
+	}
+
+	c_data.agent_id = gAgent.getID();
+	c_data.classified_id = getClassifiedId();
+	// *HACK 
+	// Categories on server start with 1 while combo-box index starts with 0
+	c_data.category = getCategory() + 1;
+	c_data.name = getClassifiedName();
+	c_data.description = getDescription();
+	c_data.parcel_id = getParcelId();
+	c_data.snapshot_id = getSnapshotId();
+	c_data.pos_global = getPosGlobal();
+	c_data.flags = getFlags();
+	c_data.price_for_listing = getPriceForListing();
+
+	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data);
+	
+	if(isNew())
+	{
+		// Lets assume there will be some error.
+		// Successful sendClassifiedInfoUpdate will trigger processProperties and
+		// let us know there was no error.
+		mIsNewWithErrors = true;
+	}
+}
+
+U32 LLPanelClassifiedEdit::getCategory()
+{
+	LLComboBox* cat_cb = getChild<LLComboBox>("category");
+	return cat_cb->getCurrentIndex();
+}
+
+void LLPanelClassifiedEdit::setCategory(U32 category)
+{
+	LLComboBox* cat_cb = getChild<LLComboBox>("category");
+	cat_cb->setCurrentByIndex(category);
+	cat_cb->resetDirty();
+}
+
+U8 LLPanelClassifiedEdit::getFlags()
+{
+	bool auto_renew = getChild<LLUICtrl>("auto_renew")->getValue().asBoolean();
+
+	LLComboBox* content_cb = getChild<LLComboBox>("content_type");
+	bool mature = content_cb->getCurrentIndex() == CB_ITEM_MATURE;
+	
+	return pack_classified_flags_request(auto_renew, false, mature, false);
+}
+
+void LLPanelClassifiedEdit::enableVerbs(bool enable)
+{
+	getChildView("save_changes_btn")->setEnabled(enable);
+}
+
+void LLPanelClassifiedEdit::enableEditing(bool enable)
+{
+	getChildView("classified_snapshot")->setEnabled(enable);
+	getChildView("classified_name")->setEnabled(enable);
+	getChildView("classified_desc")->setEnabled(enable);
+	getChildView("set_to_curr_location_btn")->setEnabled(enable);
+	getChildView("category")->setEnabled(enable);
+	getChildView("content_type")->setEnabled(enable);
+	getChildView("price_for_listing")->setEnabled(enable);
+	getChildView("auto_renew")->setEnabled(enable);
+}
+
+void LLPanelClassifiedEdit::showEditing(bool show)
+{
+	getChildView("price_for_listing_label")->setVisible( show);
+	getChildView("price_for_listing")->setVisible( show);
+}
+
+std::string LLPanelClassifiedEdit::makeClassifiedName()
+{
+	std::string name;
+
+	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if(parcel)
+	{
+		name = parcel->getName();
+	}
+
+	if(!name.empty())
+	{
+		return name;
+	}
+
+	LLViewerRegion* region = gAgent.getRegion();
+	if(region)
+	{
+		name = region->getName();
+	}
+
+	return name;
+}
+
+S32 LLPanelClassifiedEdit::getPriceForListing()
+{
+	return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger();
+}
+
+void LLPanelClassifiedEdit::setPriceForListing(S32 price)
+{
+	getChild<LLUICtrl>("price_for_listing")->setValue(price);
+}
+
+void LLPanelClassifiedEdit::onSetLocationClick()
+{
+	setPosGlobal(gAgent.getPositionGlobal());
+	setParcelId(LLUUID::null);
+
+	std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish");
+	LLViewerRegion* region = gAgent.getRegion();
+	if (region)
+	{
+		region_name = region->getName();
+	}
+
+	setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal()));
+
+	// mark classified as dirty
+	setValue(LLSD());
+
+	onChange();
+}
+
+void LLPanelClassifiedEdit::onChange()
+{
+	enableVerbs(isDirty());
+}
+
+void LLPanelClassifiedEdit::onSaveClick()
+{
+	mCanClose = false;
+
+	if(!isValidName())
+	{
+		notifyInvalidName();
+		return;
+	}
+	if(isNew() || isNewWithErrors())
+	{
+		if(gStatusBar->getBalance() < getPriceForListing())
+		{
+			LLNotificationsUtil::add("ClassifiedInsufficientFunds");
+			return;
+		}
+
+		mPublishFloater = LLFloaterReg::findTypedInstance<LLFloaterPublishClassified>(
+			"publish_classified", LLSD());
+
+		if(!mPublishFloater)
+		{
+			mPublishFloater = LLFloaterReg::getTypedInstance<LLFloaterPublishClassified>(
+				"publish_classified", LLSD());
+
+			mPublishFloater->setPublishClickedCallback(boost::bind
+				(&LLPanelClassifiedEdit::onPublishFloaterPublishClicked, this));
+		}
+
+		// set spinner value before it has focus or value wont be set
+		mPublishFloater->setPrice(getPriceForListing());
+		mPublishFloater->openFloater(mPublishFloater->getKey());
+		mPublishFloater->center();
+	}
+	else
+	{
+		doSave();
+	}
+}
+
+void LLPanelClassifiedEdit::doSave()
+{
+	mCanClose = true;
+	sendUpdate();
+	resetDirty();
+
+	mSaveButtonClickedSignal(this, LLSD());
+}
+
+void LLPanelClassifiedEdit::onPublishFloaterPublishClicked()
+{
+	setPriceForListing(mPublishFloater->getPrice());
+
+	doSave();
+}
+
+std::string LLPanelClassifiedEdit::getLocationNotice()
+{
+	static std::string location_notice = getString("location_notice");
+	return location_notice;
+}
+
+bool LLPanelClassifiedEdit::isValidName()
+{
+	std::string name = getClassifiedName();
+	if (name.empty())
+	{
+		return false;
+	}
+	if (!isalnum(name[0]))
+	{
+		return false;
+	}
+
+	return true;
+}
+
+void LLPanelClassifiedEdit::notifyInvalidName()
+{
+	std::string name = getClassifiedName();
+	if (name.empty())
+	{
+		LLNotificationsUtil::add("BlankClassifiedName");
+	}
+	else if (!isalnum(name[0]))
+	{
+		LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric");
+	}
+}
+
+void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
+{
+	ctrl->setVisible(TRUE);
+}
+
+void LLPanelClassifiedEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
+{
+	ctrl->setVisible(FALSE);
+}
+
+void LLPanelClassifiedEdit::onTextureSelected()
+{
+	setSnapshotId(mSnapshotCtrl->getValue().asUUID());
+	onChange();
+}
diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h
index 471becd0f7f..6949f536a4f 100644
--- a/indra/newview/llpanelclassified.h
+++ b/indra/newview/llpanelclassified.h
@@ -1,10 +1,10 @@
 /** 
  * @file llpanelclassified.h
- * @brief LLPanelClassifiedInfo class definition
+ * @brief LLPanelClassified class definition
  *
- * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2021, Linden Research, Inc.
+ * Copyright (C) 2010, Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -27,23 +27,26 @@
 // Display of a classified used both for the global view in the
 // Find directory, and also for each individual user's classified in their
 // profile.
+
 #ifndef LL_LLPANELCLASSIFIED_H
 #define LL_LLPANELCLASSIFIED_H
 
 #include "llavatarpropertiesprocessor.h"
-#include "llclassifiedinfo.h"
-#include "llfloater.h"
+#include "llfloaterpublishclassified.h"
 #include "llpanel.h"
 #include "llrect.h"
 
 class LLScrollContainer;
 class LLTextureCtrl;
+class LLUICtrl;
 
 class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
 {
 	LOG_CLASS(LLPanelClassifiedInfo);
 public:
 
+	static LLPanelClassifiedInfo* create();
+
 	LLPanelClassifiedInfo();
 	virtual ~LLPanelClassifiedInfo();
 
@@ -112,9 +115,13 @@ class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
 			const LLVector3d& global_pos,
 			const std::string& sim_name);
 
-	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+	void setExitCallback(const commit_callback_t& cb);
+
+	void setEditClassifiedCallback(const commit_callback_t& cb);
+
+	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
 
-	/*virtual*/ void draw();
+	/*virtual*/ void draw() override;
 
 protected:
 
@@ -136,6 +143,7 @@ class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
 
 	void onMapClick();
 	void onTeleportClick();
+	void onExit();
 
 	bool mSnapshotStreched;
 	LLRect mSnapshotRect;
@@ -172,4 +180,100 @@ class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
 	static panel_list_t sAllPanels;
 };
 
+class LLPanelClassifiedEdit : public LLPanelClassifiedInfo
+{
+	LOG_CLASS(LLPanelClassifiedEdit);
+public:
+
+	static LLPanelClassifiedEdit* create();
+
+	virtual ~LLPanelClassifiedEdit();
+
+	/*virtual*/ BOOL postBuild() override;
+
+	void fillIn(const LLSD& key);
+
+	/*virtual*/ void onOpen(const LLSD& key) override;
+
+	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type) override;
+
+	/*virtual*/ BOOL isDirty() const override;
+
+	/*virtual*/ void resetDirty() override;
+
+	void setSaveCallback(const commit_signal_t::slot_type& cb);
+
+	void setCancelCallback(const commit_signal_t::slot_type& cb);
+
+	/*virtual*/ void resetControls() override;
+
+	bool isNew() { return mIsNew; }
+
+	bool isNewWithErrors() { return mIsNewWithErrors; }
+
+	bool canClose();
+
+	void draw() override;
+
+	void stretchSnapshot();
+
+	U32 getCategory();
+
+	void setCategory(U32 category);
+
+	U32 getContentType();
+
+	void setContentType(U32 content_type);
+
+	bool getAutoRenew();
+
+	S32 getPriceForListing();
+
+protected:
+
+	LLPanelClassifiedEdit();
+
+	void sendUpdate();
+
+	void enableVerbs(bool enable);
+
+	void enableEditing(bool enable);
+
+	void showEditing(bool show);
+
+	std::string makeClassifiedName();
+
+	void setPriceForListing(S32 price);
+
+	U8 getFlags();
+
+	std::string getLocationNotice();
+
+	bool isValidName();
+
+	void notifyInvalidName();
+
+	void onSetLocationClick();
+	void onChange();
+	void onSaveClick();
+
+	void doSave();
+
+	void onPublishFloaterPublishClicked();
+
+	void onTexturePickerMouseEnter(LLUICtrl* ctrl);
+	void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+
+	void onTextureSelected();
+
+private:
+	bool mIsNew;
+	bool mIsNewWithErrors;
+	bool mCanClose;
+
+	LLFloaterPublishClassified* mPublishFloater;
+
+	commit_signal_t mSaveButtonClickedSignal;
+};
+
 #endif // LL_LLPANELCLASSIFIED_H
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
new file mode 100644
index 00000000000..1df13d083f8
--- /dev/null
+++ b/indra/newview/llpanelpick.cpp
@@ -0,0 +1,612 @@
+/** 
+ * @file llpanelpick.cpp
+ * @brief LLPanelPick class implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+// Display of a "Top Pick" used both for the global top picks in the 
+// Find directory, and also for each individual user's picks in their
+// profile.
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelpick.h"
+
+#include "message.h"
+
+#include "llparcel.h"
+
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "lliconctrl.h"
+#include "lllineeditor.h"
+#include "llpanel.h"
+#include "llscrollcontainer.h"
+#include "lltexteditor.h"
+
+#include "llagent.h"
+#include "llagentpicksinfo.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llfloaterworldmap.h"
+#include "lltexturectrl.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+
+static const std::string XML_PANEL_EDIT_PICK("panel_edit_pick.xml");
+static const std::string XML_PANEL_PICK_INFO("panel_pick_info.xml");
+
+static const std::string XML_NAME("pick_name");
+static const std::string XML_DESC("pick_desc");
+static const std::string XML_SNAPSHOT("pick_snapshot");
+static const std::string XML_LOCATION("pick_location");
+
+static const std::string XML_BTN_ON_TXTR("edit_icon");
+static const std::string XML_BTN_SAVE("save_changes_btn");
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+//static
+LLPanelPickInfo* LLPanelPickInfo::create()
+{
+	LLPanelPickInfo* panel = new LLPanelPickInfo();
+	panel->buildFromFile(XML_PANEL_PICK_INFO);
+	return panel;
+}
+
+LLPanelPickInfo::LLPanelPickInfo()
+ : LLPanel()
+ , LLAvatarPropertiesObserver()
+ , LLRemoteParcelInfoObserver()
+ , mScrollingPanelMinHeight(0)
+ , mScrollingPanelWidth(0)
+ , mScrollContainer(nullptr)
+ , mScrollingPanel(nullptr)
+ , mSnapshotCtrl(nullptr)
+ , mAvatarId(LLUUID::null)
+ , mParcelId(LLUUID::null)
+ , mPickId(LLUUID::null)
+ , mRequestedId(LLUUID::null)
+{
+}
+
+LLPanelPickInfo::~LLPanelPickInfo()
+{
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLPanelPickInfo::getAvatarId(), this);
+
+	if (mParcelId.notNull())
+	{
+		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
+	}
+}
+
+void LLPanelPickInfo::onOpen(const LLSD& key)
+{
+	LLUUID avatar_id = key["avatar_id"];
+	if(avatar_id.isNull())
+	{
+		return;
+	}
+
+	if(getAvatarId().notNull())
+	{
+		LLAvatarPropertiesProcessor::getInstance()->removeObserver(
+			getAvatarId(), this);
+	}
+
+	setAvatarId(avatar_id);
+
+	resetData();
+	resetControls();
+
+	setPickId(key["pick_id"]);
+	setPickName(key["pick_name"]);
+	setPickDesc(key["pick_desc"]);
+	setSnapshotId(key["snapshot_id"]);
+
+	LLAvatarPropertiesProcessor::getInstance()->addObserver(
+		getAvatarId(), this);
+	LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(
+		getAvatarId(), getPickId());
+}
+
+BOOL LLPanelPickInfo::postBuild()
+{
+	mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
+
+	childSetAction("teleport_btn", boost::bind(&LLPanelPickInfo::onClickTeleport, this));
+	childSetAction("show_on_map_btn", boost::bind(&LLPanelPickInfo::onClickMap, this));
+	childSetAction("back_btn", boost::bind(&LLPanelPickInfo::onClickBack, this));
+
+	mScrollingPanel = getChild<LLPanel>("scroll_content_panel");
+	mScrollContainer = getChild<LLScrollContainer>("profile_scroll");
+
+	mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight();
+	mScrollingPanelWidth = mScrollingPanel->getRect().getWidth();
+
+	LLTextEditor* text_desc = getChild<LLTextEditor>(XML_DESC);
+	text_desc->setContentTrusted(false);
+
+	return TRUE;
+}
+
+void LLPanelPickInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+	LLPanel::reshape(width, height, called_from_parent);
+
+	if (!mScrollContainer || !mScrollingPanel)
+		return;
+
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+	S32 scroll_height = mScrollContainer->getRect().getHeight();
+	if (mScrollingPanelMinHeight >= scroll_height)
+	{
+		mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight);
+	}
+	else
+	{
+		mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height);
+	}
+}
+
+void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type)
+{
+	if(APT_PICK_INFO != type)
+	{
+		return;
+	}
+	LLPickData* pick_info = static_cast<LLPickData*>(data);
+	if(!pick_info 
+		|| pick_info->creator_id != getAvatarId() 
+		|| pick_info->pick_id != getPickId())
+	{
+		return;
+	}
+
+	mParcelId = pick_info->parcel_id;
+	setSnapshotId(pick_info->snapshot_id);
+	setPickName(pick_info->name);
+	setPickDesc(pick_info->desc);
+	setPosGlobal(pick_info->pos_global);
+
+	// Send remote parcel info request to get parcel name and sim (region) name.
+	sendParcelInfoRequest();
+
+	// *NOTE dzaporozhan
+	// We want to keep listening to APT_PICK_INFO because user may 
+	// edit the Pick and we have to update Pick info panel.
+	// revomeObserver is called from onClickBack
+}
+
+void LLPanelPickInfo::sendParcelInfoRequest()
+{
+	if (mParcelId != mRequestedId)
+	{
+		LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this);
+		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId);
+
+		mRequestedId = mParcelId;
+	}
+}
+
+void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("back_btn")->setClickedCallback(cb);
+}
+
+void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data)
+{
+	setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name,
+		parcel_data.sim_name, getPosGlobal()));
+
+	// We have received parcel info for the requested ID so clear it now.
+	mRequestedId.setNull();
+
+	if (mParcelId.notNull())
+	{
+		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
+	}
+}
+
+void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("edit_btn")->setClickedCallback(cb);
+}
+
+// PROTECTED AREA
+
+void LLPanelPickInfo::resetControls()
+{
+	if(getAvatarId() == gAgent.getID())
+	{
+		getChildView("edit_btn")->setEnabled(TRUE);
+		getChildView("edit_btn")->setVisible( TRUE);
+	}
+	else
+	{
+		getChildView("edit_btn")->setEnabled(FALSE);
+		getChildView("edit_btn")->setVisible( FALSE);
+	}
+}
+
+void LLPanelPickInfo::resetData()
+{
+	setPickName(LLStringUtil::null);
+	setPickDesc(LLStringUtil::null);
+	setPickLocation(LLStringUtil::null);
+	setPickId(LLUUID::null);
+	setSnapshotId(LLUUID::null);
+	mPosGlobal.clearVec();
+	mParcelId.setNull();
+	mRequestedId.setNull();
+}
+
+// static
+std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global)
+{
+	std::string location_text;
+	location_text.append(owner_name);
+	if (!original_name.empty())
+	{
+		if (!location_text.empty()) location_text.append(", ");
+		location_text.append(original_name);
+
+	}
+	if (!sim_name.empty())
+	{
+		if (!location_text.empty()) location_text.append(", ");
+		location_text.append(sim_name);
+	}
+
+	if (!location_text.empty()) location_text.append(" ");
+
+	if (!pos_global.isNull())
+	{
+		S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
+		S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
+		S32 region_z = ll_round((F32)pos_global.mdV[VZ]);
+		location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
+	}
+	return location_text;
+}
+
+void LLPanelPickInfo::setSnapshotId(const LLUUID& id) 
+{ 
+	mSnapshotCtrl->setImageAssetID(id);
+	mSnapshotCtrl->setValid(TRUE);
+}
+
+void LLPanelPickInfo::setPickName(const std::string& name)
+{
+	getChild<LLUICtrl>(XML_NAME)->setValue(name);
+}
+
+void LLPanelPickInfo::setPickDesc(const std::string& desc)
+{
+	getChild<LLUICtrl>(XML_DESC)->setValue(desc);
+}
+
+void LLPanelPickInfo::setPickLocation(const std::string& location)
+{
+	getChild<LLUICtrl>(XML_LOCATION)->setValue(location);
+}
+
+void LLPanelPickInfo::onClickMap()
+{
+	LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+	LLFloaterReg::showInstance("world_map", "center");
+}
+
+void LLPanelPickInfo::onClickTeleport()
+{
+	if (!getPosGlobal().isExactlyZero())
+	{
+		gAgent.teleportViaLocation(getPosGlobal());
+		LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+	}
+}
+
+void LLPanelPickInfo::onClickBack()
+{
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+//static
+LLPanelPickEdit* LLPanelPickEdit::create()
+{
+	LLPanelPickEdit* panel = new LLPanelPickEdit();
+	panel->buildFromFile(XML_PANEL_EDIT_PICK);
+	return panel;
+}
+
+LLPanelPickEdit::LLPanelPickEdit()
+ : LLPanelPickInfo()
+ , mLocationChanged(false)
+ , mNeedData(true)
+ , mNewPick(false)
+ , text_icon(nullptr)
+{
+}
+
+void LLPanelPickEdit::onOpen(const LLSD& key)
+{
+	LLUUID pick_id = key["pick_id"];
+	mNeedData = true;
+
+	// creating new Pick
+	if(pick_id.isNull())
+	{
+		mNewPick = true;
+
+		setAvatarId(gAgent.getID());
+
+		resetData();
+		resetControls();
+
+		setPosGlobal(gAgent.getPositionGlobal());
+
+		LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null;
+		std::string pick_name, pick_desc, region_name;
+
+		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+		if(parcel)
+		{
+			parcel_id = parcel->getID();
+			pick_name = parcel->getName();
+			pick_desc = parcel->getDesc();
+			snapshot_id = parcel->getSnapshotID();
+		}
+
+		LLViewerRegion* region = gAgent.getRegion();
+		if(region)
+		{
+			region_name = region->getName();
+		}
+
+		setParcelID(parcel_id);
+		getChild<LLUICtrl>("pick_name")->setValue(pick_name.empty() ? region_name : pick_name);
+		getChild<LLUICtrl>("pick_desc")->setValue(pick_desc);
+		setSnapshotId(snapshot_id);
+		setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal()));
+
+		enableSaveButton(true);
+	}
+	// editing existing pick
+	else
+	{
+		mNewPick = false;
+		LLPanelPickInfo::onOpen(key);
+
+		enableSaveButton(false);
+	}
+
+	resetDirty();
+}
+
+void LLPanelPickEdit::setPickData(const LLPickData* pick_data)
+{
+	if(!pick_data)
+	{
+		return;
+	}
+
+	mNeedData = false;
+
+	setParcelID(pick_data->parcel_id);
+	getChild<LLUICtrl>("pick_name")->setValue(pick_data->name);
+	getChild<LLUICtrl>("pick_desc")->setValue(pick_data->desc);
+	setSnapshotId(pick_data->snapshot_id);
+	setPosGlobal(pick_data->pos_global);
+	setPickLocation(createLocationText(LLStringUtil::null, pick_data->name,
+			pick_data->sim_name, pick_data->pos_global));
+}
+
+BOOL LLPanelPickEdit::postBuild()
+{
+	LLPanelPickInfo::postBuild();
+
+	mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPickEdit::onSnapshotChanged, this));
+
+	LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
+	line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), nullptr);
+
+	LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
+	text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
+
+	childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this));
+	childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this));
+
+	initTexturePickerMouseEvents();
+
+	return TRUE;
+}
+
+void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
+}
+
+void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
+}
+
+void LLPanelPickEdit::resetDirty()
+{
+	LLPanelPickInfo::resetDirty();
+
+	getChild<LLLineEditor>("pick_name")->resetDirty();
+	getChild<LLTextEditor>("pick_desc")->resetDirty();
+	mSnapshotCtrl->resetDirty();
+	mLocationChanged = false;
+}
+
+BOOL LLPanelPickEdit::isDirty() const
+{
+	if( mNewPick
+		|| LLPanelPickInfo::isDirty()
+		|| mLocationChanged
+		|| mSnapshotCtrl->isDirty()
+		|| getChild<LLLineEditor>("pick_name")->isDirty()
+		|| getChild<LLTextEditor>("pick_desc")->isDirty())
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+void LLPanelPickEdit::sendUpdate()
+{
+	LLPickData pick_data;
+
+	// If we don't have a pick id yet, we'll need to generate one,
+	// otherwise we'll keep overwriting pick_id 00000 in the database.
+	if (getPickId().isNull()) 
+	{
+		getPickId().generate();
+	}
+
+	pick_data.agent_id = gAgent.getID();
+	pick_data.session_id = gAgent.getSessionID();
+	pick_data.pick_id = getPickId();
+	pick_data.creator_id = gAgent.getID();;
+
+	//legacy var  need to be deleted
+	pick_data.top_pick = FALSE; 
+	pick_data.parcel_id = mParcelId;
+	pick_data.name = getChild<LLUICtrl>(XML_NAME)->getValue().asString();
+	pick_data.desc = getChild<LLUICtrl>(XML_DESC)->getValue().asString();
+	pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
+	pick_data.pos_global = getPosGlobal();
+	pick_data.sort_order = 0;
+	pick_data.enabled = TRUE;
+
+	LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
+
+	if(mNewPick)
+	{
+		// Assume a successful create pick operation, make new number of picks
+		// available immediately. Actual number of picks will be requested in 
+		// LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond.
+		LLAgentPicksInfo::getInstance()->incrementNumberOfPicks();
+	}
+}
+
+void LLPanelPickEdit::onSnapshotChanged()
+{
+	enableSaveButton(true);
+}
+
+void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl)
+{
+	enableSaveButton(isDirty());
+}
+
+void LLPanelPickEdit::resetData()
+{
+	LLPanelPickInfo::resetData();
+	mLocationChanged = false;
+}
+
+void LLPanelPickEdit::enableSaveButton(bool enable)
+{
+	getChildView(XML_BTN_SAVE)->setEnabled(enable);
+}
+
+void LLPanelPickEdit::onClickSetLocation()
+{
+	// Save location for later use.
+	setPosGlobal(gAgent.getPositionGlobal());
+
+	std::string parcel_name, region_name;
+
+	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if (parcel)
+	{
+		mParcelId = parcel->getID();
+		parcel_name = parcel->getName();
+	}
+
+	LLViewerRegion* region = gAgent.getRegion();
+	if(region)
+	{
+		region_name = region->getName();
+	}
+
+	setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal()));
+
+	mLocationChanged = true;
+	enableSaveButton(TRUE);
+}
+
+void LLPanelPickEdit::onClickSave()
+{
+	sendUpdate();
+
+	mLocationChanged = false;
+
+	LLSD params;
+	params["action"] = "save_new_pick";
+	notifyParent(params);
+}
+
+std::string LLPanelPickEdit::getLocationNotice()
+{
+	static std::string notice = getString("location_notice");
+	return notice;
+}
+
+void LLPanelPickEdit::processProperties(void* data, EAvatarProcessorType type)
+{
+	if(mNeedData)
+	{
+		LLPanelPickInfo::processProperties(data, type);
+	}
+}
+
+// PRIVATE AREA
+
+void LLPanelPickEdit::initTexturePickerMouseEvents()
+{
+	text_icon = getChild<LLIconCtrl>(XML_BTN_ON_TXTR);
+	mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseEnter, this, _1));
+	mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseLeave, this, _1));
+	
+	text_icon->setVisible(FALSE);
+}
+		
+void LLPanelPickEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
+{
+        text_icon->setVisible(TRUE);
+}
+
+void LLPanelPickEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
+{
+	text_icon->setVisible(FALSE);
+}
diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h
new file mode 100644
index 00000000000..c3af9b7251b
--- /dev/null
+++ b/indra/newview/llpanelpick.h
@@ -0,0 +1,255 @@
+/** 
+ * @file llpanelpick.h
+ * @brief LLPanelPick class definition
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+// Display of a "Top Pick" used both for the global top picks in the 
+// Find directory, and also for each individual user's picks in their
+// profile.
+
+#ifndef LL_LLPANELPICK_H
+#define LL_LLPANELPICK_H
+
+#include "llpanel.h"
+#include "llremoteparcelrequest.h"
+#include "llavatarpropertiesprocessor.h"
+
+class LLIconCtrl;
+class LLTextureCtrl;
+class LLScrollContainer;
+class LLMessageSystem;
+class LLAvatarPropertiesObserver;
+
+/**
+ * Panel for displaying Pick Information - snapshot, name, description, etc.
+ */
+class LLPanelPickInfo : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver
+{
+	LOG_CLASS(LLPanelPickInfo);
+public:
+	
+	// Creates new panel
+	static LLPanelPickInfo* create();
+
+	virtual ~LLPanelPickInfo();
+
+	/**
+	 * Initializes panel properties
+	 *
+	 * By default Pick will be created for current Agent location.
+	 * Use setPickData to change Pick properties.
+	 */
+	/*virtual*/ void onOpen(const LLSD& key) override;
+
+	/*virtual*/ BOOL postBuild() override;
+
+	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
+
+	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type) override;
+
+	/**
+	 * Sends remote parcel info request to resolve parcel name from its ID.
+	 */
+	void sendParcelInfoRequest();
+
+	/**
+	 * Sets "Back" button click callback
+	 */
+	virtual void setExitCallback(const commit_callback_t& cb);
+
+	/**
+	 * Sets "Edit" button click callback
+	 */
+	virtual void setEditPickCallback(const commit_callback_t& cb);
+
+	//This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing
+	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data) override;
+	/*virtual*/ void setParcelID(const LLUUID& parcel_id) override { mParcelId = parcel_id; }
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason) override {};
+
+protected:
+
+	LLPanelPickInfo();
+	
+	/**
+	 * Resets Pick information
+	 */
+	virtual void resetData();
+
+	/**
+	 * Resets UI controls (visibility, values)
+	 */
+	virtual void resetControls();
+
+	/** 
+	* "Location text" is actually the owner name, the original
+	* name that owner gave the parcel, and the location.
+	*/
+	static std::string createLocationText(
+		const std::string& owner_name, 
+		const std::string& original_name,
+		const std::string& sim_name, 
+		const LLVector3d& pos_global);
+
+	virtual void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+	virtual LLUUID& getAvatarId() { return mAvatarId; }
+
+	/**
+	 * Sets snapshot id.
+	 *
+	 * Will mark snapshot control as valid if id is not null.
+	 * Will mark snapshot control as invalid if id is null. If null id is a valid value,
+	 * you have to manually mark snapshot is valid.
+	 */
+	virtual void setSnapshotId(const LLUUID& id);
+	
+	virtual void setPickId(const LLUUID& id) { mPickId = id; }
+	virtual LLUUID& getPickId() { return mPickId; }
+	
+	virtual void setPickName(const std::string& name);
+	
+	virtual void setPickDesc(const std::string& desc);
+	
+	virtual void setPickLocation(const std::string& location);
+	
+	virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
+	virtual LLVector3d& getPosGlobal() { return mPosGlobal; }
+
+	/**
+	 * Callback for "Map" button, opens Map
+	 */
+	void onClickMap();
+
+	/**
+	 * Callback for "Teleport" button, teleports user to Pick location.
+	 */
+	void onClickTeleport();
+
+	void onClickBack();
+
+	S32						mScrollingPanelMinHeight;
+	S32						mScrollingPanelWidth;
+	LLScrollContainer*		mScrollContainer;
+	LLPanel*				mScrollingPanel;
+	LLTextureCtrl*			mSnapshotCtrl;
+
+	LLUUID mAvatarId;
+	LLVector3d mPosGlobal;
+	LLUUID mParcelId;
+	LLUUID mPickId;
+	LLUUID mRequestedId;
+};
+
+/**
+ * Panel for creating/editing Pick.
+ */
+class LLPanelPickEdit final : public LLPanelPickInfo
+{
+	LOG_CLASS(LLPanelPickEdit);
+public:
+
+	/**
+	 * Creates new panel
+	 */
+	static LLPanelPickEdit* create();
+
+	~LLPanelPickEdit() = default;
+	void onOpen(const LLSD& key) override;
+	virtual void setPickData(const LLPickData* pick_data);
+	BOOL postBuild() override;
+
+	/**
+	 * Sets "Save" button click callback
+	 */
+	virtual void setSaveCallback(const commit_callback_t& cb);
+
+	/**
+	 * Sets "Cancel" button click callback
+	 */
+	virtual void setCancelCallback(const commit_callback_t& cb);
+
+	/**
+	 * Resets panel and all cantrols to unedited state
+	 */
+	void resetDirty() override;
+
+	/**
+	 * Returns true if any of Pick properties was changed by user.
+	 */
+	BOOL isDirty() const override;
+
+	void processProperties(void* data, EAvatarProcessorType type) override;
+
+	/**
+	* Sends Pick properties to server.
+	*/
+	void sendUpdate();
+
+protected:
+
+	LLPanelPickEdit();
+
+	/**
+	 * Called when snapshot image changes.
+	 */
+	void onSnapshotChanged();
+	
+	/**
+	 * Callback for Pick snapshot, name and description changed event.
+	 */
+	void onPickChanged(LLUICtrl* ctrl);
+
+	/*virtual*/ void resetData() override;
+
+	/**
+	 * Enables/disables "Save" button
+	 */
+	void enableSaveButton(bool enable);
+
+	/**
+	 * Callback for "Set Location" button click
+	 */
+	void onClickSetLocation();
+
+	/**
+	 * Callback for "Save" button click
+	 */
+	void onClickSave();
+
+	std::string getLocationNotice();
+
+	bool mLocationChanged;
+	bool mNeedData;
+	bool mNewPick;
+
+private:
+
+	void initTexturePickerMouseEvents();
+        void onTexturePickerMouseEnter(LLUICtrl* ctrl);
+	void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+
+	LLIconCtrl* text_icon;
+};
+
+#endif // LL_LLPANELPICK_H
diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp
index 8a13f0c2368..5d8ece72e41 100644
--- a/indra/newview/llpanelprofileclassifieds.cpp
+++ b/indra/newview/llpanelprofileclassifieds.cpp
@@ -32,13 +32,14 @@
 #include "llavataractions.h"
 #include "llavatarpropertiesprocessor.h"
 #include "llclassifiedflags.h"
+#include "llclassifiedinfo.h"
 #include "llcombobox.h"
 #include "llcommandhandler.h" // for classified HTML detail page click tracking
 #include "llcorehttputil.h"
 #include "lldispatcher.h"
 #include "llfloaterclassified.h"
 #include "llfloaterreg.h"
-#include "llfloatersidepanelcontainer.h"
+#include "llfloaterpublishclassified.h"
 #include "llfloaterworldmap.h"
 #include "lliconctrl.h"
 #include "lllineeditor.h"
@@ -46,7 +47,6 @@
 #include "llnotificationsutil.h"
 #include "llpanelavatar.h"
 #include "llparcel.h"
-#include "llregistry.h"
 #include "llscrollcontainer.h"
 #include "llstartup.h"
 #include "llstatusbar.h"
@@ -57,8 +57,6 @@
 #include "llviewergenericmessage.h" // send_generic_message
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
-#include "llviewertexture.h"
-#include "llviewertexture.h"
 #include "rlvactions.h"
 #include "rlvhandler.h"
 
@@ -66,7 +64,6 @@
 //*TODO: verify this limit
 const S32 MAX_AVATAR_CLASSIFIEDS = 100;
 
-const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$
 const S32 DEFAULT_EDIT_CLASSIFIED_SCROLL_HEIGHT = 530;
 
 //static
@@ -952,12 +949,12 @@ void LLPanelProfileClassified::onSaveClick()
             return;
         }
 
-        mPublishFloater = LLFloaterReg::findTypedInstance<LLPublishClassifiedFloater>(
+        mPublishFloater = LLFloaterReg::findTypedInstance<LLFloaterPublishClassified>(
             "publish_classified", LLSD());
 
         if(!mPublishFloater)
         {
-            mPublishFloater = LLFloaterReg::getTypedInstance<LLPublishClassifiedFloater>(
+            mPublishFloater = LLFloaterReg::getTypedInstance<LLFloaterPublishClassified>(
                 "publish_classified", LLSD());
 
             mPublishFloater->setPublishClickedCallback(boost::bind
@@ -1483,47 +1480,3 @@ void LLPanelProfileClassified::updateTabLabel(const std::string& title)
         parent->setCurrentTabName(title);
     }
 }
-
-
-//-----------------------------------------------------------------------------
-// LLPublishClassifiedFloater
-//-----------------------------------------------------------------------------
-
-LLPublishClassifiedFloater::LLPublishClassifiedFloater(const LLSD& key)
- : LLFloater(key)
-{
-}
-
-LLPublishClassifiedFloater::~LLPublishClassifiedFloater()
-{
-}
-
-BOOL LLPublishClassifiedFloater::postBuild()
-{
-    LLFloater::postBuild();
-
-    childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false));
-    childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false));
-
-    return TRUE;
-}
-
-void LLPublishClassifiedFloater::setPrice(S32 price)
-{
-    getChild<LLUICtrl>("price_for_listing")->setValue(price);
-}
-
-S32 LLPublishClassifiedFloater::getPrice()
-{
-    return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger();
-}
-
-void LLPublishClassifiedFloater::setPublishClickedCallback(const commit_signal_t::slot_type& cb)
-{
-    getChild<LLButton>("publish_btn")->setClickedCallback(cb);
-}
-
-void LLPublishClassifiedFloater::setCancelClickedCallback(const commit_signal_t::slot_type& cb)
-{
-    getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
-}
diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h
index 188c16141d8..f41b3ac76d8 100644
--- a/indra/newview/llpanelprofileclassifieds.h
+++ b/indra/newview/llpanelprofileclassifieds.h
@@ -28,14 +28,11 @@
 #define LL_PANELPROFILECLASSIFIEDS_H
 
 #include "llavatarpropertiesprocessor.h"
-#include "llclassifiedinfo.h"
-#include "llfloater.h"
+#include "llfloaterpublishclassified.h"
 #include "llpanel.h"
 #include "llpanelavatar.h"
-#include "llrect.h"
 #include "lluuid.h"
 #include "v3dmath.h"
-#include "llcoros.h"
 #include "lleventcoro.h"
 
 class LLCheckBoxCtrl;
@@ -47,23 +44,6 @@ class LLTextEditor;
 class LLTextureCtrl;
 class LLUICtrl;
 
-
-class LLPublishClassifiedFloater final : public LLFloater
-{
-public:
-    LLPublishClassifiedFloater(const LLSD& key);
-    virtual ~LLPublishClassifiedFloater();
-
-    BOOL postBuild() override;
-
-    void setPrice(S32 price);
-    S32 getPrice();
-
-    void setPublishClickedCallback(const commit_signal_t::slot_type& cb);
-    void setCancelClickedCallback(const commit_signal_t::slot_type& cb);
-};
-
-
 /**
 * Panel for displaying Avatar's picks.
 */
@@ -335,7 +315,7 @@ class LLPanelProfileClassified
     bool mCanClose;
     bool mEditOnLoad;
 
-    LLPublishClassifiedFloater* mPublishFloater;
+    LLFloaterPublishClassified* mPublishFloater;
 };
 
 #endif // LL_PANELPROFILECLASSIFIEDS_H
diff --git a/indra/newview/llpanelprofilelegacy.cpp b/indra/newview/llpanelprofilelegacy.cpp
index 6d9addfef60..04fa5fbecd0 100644
--- a/indra/newview/llpanelprofilelegacy.cpp
+++ b/indra/newview/llpanelprofilelegacy.cpp
@@ -52,16 +52,15 @@
 #include "llagentpicksinfo.h"
 #include "llavataractions.h"
 #include "llcallingcard.h" // for LLAvatarTracker
+#include "llclassifieditem.h"
 #include "lldateutil.h"
 #include "lldroptarget.h"
 #include "llfloaterreporter.h"
 #include "llfloaterworldmap.h"
 #include "llgroupactions.h"
 #include "llpanelclassified.h"
-#if WIP_PROFILES
-#include "llpanelpicks.h"
+#include "llpanelpick.h"
 #include "llpickitem.h"
-#endif
 #include "llmutelist.h"
 #include "llsidetraypanelcontainer.h"
 #include "llslurl.h"
@@ -77,15 +76,11 @@ static const std::array<std::string, 6> sSkillsCheckboxes{{"can_texture", "can_a
 
 static LLPanelInjector<LLPanelProfileLegacy> t_panel_lprofile("panel_profile_legacy_sidetray");
 static LLPanelInjector<LLPanelProfileLegacy::LLPanelProfileGroups> t_panel_group("panel_profile_legacy_groups");
-#ifdef WIP_PROFILES
 static LLPanelInjector<LLPanelProfileLegacy::LLPanelProfilePicks> t_panel_picks("panel_profile_legacy_picks");
-#endif
 
 LLPanelProfileLegacy::LLPanelProfileLegacy()
 :	LLPanelProfileLegacyTab()
-#ifdef WIP_PROFILES
 ,	mPanelPicks(nullptr)
-#endif
 ,	mPanelGroups(nullptr)
 {
 	mChildStack.setParent(this);
@@ -112,10 +107,8 @@ LLPanelProfileLegacy::~LLPanelProfileLegacy()
 BOOL LLPanelProfileLegacy::postBuild()
 {
 	mPanelGroups = static_cast<LLPanelProfileGroups*>(getChild<LLUICtrl>("groups_tab_panel"));
-#ifdef WIP_PROFILES
 	mPanelPicks = static_cast<LLPanelProfilePicks*>(getChild<LLUICtrl>("picks_tab_panel"));
 	mPanelPicks->setProfilePanel(this);
-#endif
 	
 	if (dynamic_cast<LLSideTrayPanelContainer*>(getParent()) != nullptr)
 		getChild<LLUICtrl>("back")->setCommitCallback(boost::bind(&LLPanelProfileLegacy::onBackBtnClick, this));
@@ -161,9 +154,7 @@ void LLPanelProfileLegacy::onOpen(const LLSD& key)
 	setAvatarId(av_id);
 	
 	mPanelGroups->onOpen(LLSD(av_id));
-#ifdef WIP_PROFILES
 	mPanelPicks->onOpen(LLSD(av_id));
-#endif
 	// Oh joy!
 	bool is_self = (getAvatarId() == gAgentID);
 	getChild<LLView>("sl_profile_pic")->setEnabled(is_self);
@@ -810,7 +801,6 @@ void LLPanelProfileLegacy::closePanel(LLPanel* panel)
 }
 
 // LLPanelProfilePicks //
-#if WIP_PROFILES
 LLPanelProfileLegacy::LLPanelProfilePicks::LLPanelProfilePicks()
 :	LLPanelProfileLegacyTab()
 ,	mProfilePanel(nullptr)
@@ -818,6 +808,7 @@ LLPanelProfileLegacy::LLPanelProfilePicks::LLPanelProfilePicks()
 ,	mPicksList(nullptr)
 ,	mPanelPickEdit(nullptr)
 ,	mPanelPickInfo(nullptr)
+,	mPanelClassifiedEdit(nullptr)
 ,	mPanelClassifiedInfo(nullptr)
 ,	mPopupMenuHandle()
 ,	mPlusMenuHandle()
@@ -1066,7 +1057,8 @@ void LLPanelProfileLegacy::LLPanelProfilePicks::onClickDelete()
 	{
 		LLSD args;
 		args["PICK"] = value[PICK_NAME];
-		LLNotificationsUtil::add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelProfilePicks::callbackDeletePick, this, _1, _2));
+		LLNotificationsUtil::add("DeleteAvatarPick", args, LLSD(), 
+			boost::bind(&LLPanelProfilePicks::callbackDeletePick, this, _1, _2));
 		return;
 	}
 	value = mClassifiedsList->getSelectedValue();
@@ -1074,7 +1066,8 @@ void LLPanelProfileLegacy::LLPanelProfilePicks::onClickDelete()
 	{
 		LLSD args;
 		args["NAME"] = value[CLASSIFIED_NAME];
-		LLNotificationsUtil::add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelProfilePicks::callbackDeleteClassified, this, _1, _2));
+		LLNotificationsUtil::add("DeleteClassified", args, LLSD(), 
+			boost::bind(&LLPanelProfilePicks::callbackDeleteClassified, this, _1, _2));
 		return;
 	}
 }
@@ -1157,6 +1150,7 @@ void LLPanelProfileLegacy::LLPanelProfilePicks::openClassifiedInfo()
 	{
 		mPanelClassifiedInfo = LLPanelClassifiedInfo::create();
 		mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelProfilePicks::onPanelClassifiedClose, this, mPanelClassifiedInfo));
+		mPanelClassifiedInfo->setEditClassifiedCallback(boost::bind(&LLPanelProfilePicks::onPanelClassifiedEdit, this));
 		mPanelClassifiedInfo->setVisible(FALSE);
 	}
 	
@@ -1441,7 +1435,6 @@ inline LLPanelProfileLegacy* LLPanelProfileLegacy::LLPanelProfilePicks::getProfi
 	llassert_always(mProfilePanel != nullptr);
 	return mProfilePanel;
 }
-#endif
 
 // LLPanelProfileGroups //
 
diff --git a/indra/newview/llpanelprofilelegacy.h b/indra/newview/llpanelprofilelegacy.h
index 9731c87afeb..3d27fa628aa 100644
--- a/indra/newview/llpanelprofilelegacy.h
+++ b/indra/newview/llpanelprofilelegacy.h
@@ -33,11 +33,9 @@
 
 #include "llgroupmgr.h"
 #include "llpanelavatarlegacy.h"
-#if WIP_PROFILES
-#include "llclassifieditem.h"
-#endif
 
 class LLAvatarName;
+class LLClassifiedItem;
 class LLFlatListView;
 class LLPanel;
 class LLPanelPickEdit;
@@ -114,7 +112,6 @@ class LLPanelProfileLegacy final : public LLPanelProfileLegacyTab
 	ChildStack		mChildStack;
 	
 public:
-#if WIP_PROFILES
 	class LLPanelProfilePicks final : public LLPanelProfileLegacyTab
 	{
 		friend class LLPanelProfileLegacy;
@@ -172,15 +169,15 @@ class LLPanelProfileLegacy final : public LLPanelProfileLegacyTab
 		LLFlatListView* mPicksList;
 		LLPanelPickEdit* mPanelPickEdit;
 		LLPanelPickInfo* mPanelPickInfo;
+		LLPanelClassifiedEdit* mPanelClassifiedEdit;
 		LLPanelClassifiedInfo* mPanelClassifiedInfo;
 		LLHandle<LLView> mPopupMenuHandle;
 		LLHandle<LLToggleableMenu> mPlusMenuHandle;
 
 		// This map is needed for newly created classifieds. The purpose of panel is to
 		// sit in this map and listen to LLPanelClassifiedEdit::processProperties callback.
-		panel_classified_edit_map_t mEditClassifiedPanels;
+        std::map<LLUUID, LLPanelClassifiedEdit*> mEditClassifiedPanels;
 	};
-#endif
 	
 	class LLPanelProfileGroups final : public LLPanelProfileLegacyTab
 	{
@@ -227,9 +224,7 @@ class LLPanelProfileLegacy final : public LLPanelProfileLegacyTab
     };
 	
 private:
-#if WIP_PROFILES
 	LLPanelProfilePicks* mPanelPicks;
-#endif
 	LLPanelProfileGroups* mPanelGroups;
 };
 
diff --git a/indra/newview/llpickitem.cpp b/indra/newview/llpickitem.cpp
new file mode 100644
index 00000000000..35baa86a332
--- /dev/null
+++ b/indra/newview/llpickitem.cpp
@@ -0,0 +1,155 @@
+/**
+* @file llpickitem.cpp
+* @brief Widget
+*
+* $LicenseInfo:firstyear=2009&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llpickitem.h"
+
+#include "lltexturectrl.h"
+
+LLPickItem::LLPickItem()
+	: LLPanel()
+	, mPickID(LLUUID::null)
+	, mCreatorID(LLUUID::null)
+	, mParcelID(LLUUID::null)
+	, mSnapshotID(LLUUID::null)
+	, mNeedData(true)
+{
+	buildFromFile("panel_pick_list_item.xml");
+}
+
+LLPickItem::~LLPickItem()
+{
+	if (mCreatorID.notNull())
+	{
+		LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this);
+	}
+
+}
+
+LLPickItem* LLPickItem::create()
+{
+	return new LLPickItem();
+}
+
+void LLPickItem::init(LLPickData* pick_data)
+{
+	setPickDesc(pick_data->desc);
+	setSnapshotId(pick_data->snapshot_id);
+	mPosGlobal = pick_data->pos_global;
+	mSimName = pick_data->sim_name;
+	mPickDescription = pick_data->desc;
+	mUserName = pick_data->user_name;
+	mOriginalName = pick_data->original_name;
+
+	LLTextureCtrl* picture = getChild<LLTextureCtrl>("picture");
+	picture->setImageAssetID(pick_data->snapshot_id);
+}
+
+void LLPickItem::setPickName(const std::string& name)
+{
+	mPickName = name;
+	getChild<LLUICtrl>("picture_name")->setValue(name);
+
+}
+
+const std::string& LLPickItem::getPickName() const
+{
+	return mPickName;
+}
+
+const LLUUID& LLPickItem::getCreatorId() const
+{
+	return mCreatorID;
+}
+
+const LLUUID& LLPickItem::getSnapshotId() const
+{
+	return mSnapshotID;
+}
+
+void LLPickItem::setPickDesc(const std::string& descr)
+{
+	getChild<LLUICtrl>("picture_descr")->setValue(descr);
+}
+
+void LLPickItem::setPickId(const LLUUID& id)
+{
+	mPickID = id;
+}
+
+const LLUUID& LLPickItem::getPickId() const
+{
+	return mPickID;
+}
+
+const LLVector3d& LLPickItem::getPosGlobal() const
+{
+	return mPosGlobal;
+}
+
+const std::string LLPickItem::getDescription() const
+{
+	return getChild<LLUICtrl>("picture_descr")->getValue().asString();
+}
+
+void LLPickItem::update()
+{
+	setNeedData(true);
+	LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID);
+}
+
+void LLPickItem::processProperties(void *data, EAvatarProcessorType type)
+{
+	if (APT_PICK_INFO != type)
+	{
+		return;
+	}
+
+	LLPickData* pick_data = static_cast<LLPickData *>(data);
+	if (!pick_data || mPickID != pick_data->pick_id)
+	{
+		return;
+	}
+
+	init(pick_data);
+	setNeedData(false);
+	LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this);
+}
+
+BOOL LLPickItem::postBuild()
+{
+	setMouseEnterCallback(std::bind(&set_child_visible, this, "hovered_icon", true));
+	setMouseLeaveCallback(std::bind(&set_child_visible, this, "hovered_icon", false));
+	return TRUE;
+}
+
+void LLPickItem::setValue(const LLSD& value)
+{
+	if (!value.isMap()) return;;
+	if (!value.has("selected")) return;
+	getChildView("selected_icon")->setVisible(value["selected"]);
+}
+
diff --git a/indra/newview/llpickitem.h b/indra/newview/llpickitem.h
new file mode 100644
index 00000000000..d5156e7e5d8
--- /dev/null
+++ b/indra/newview/llpickitem.h
@@ -0,0 +1,85 @@
+/**
+* @file llpickitem.h
+* @brief Widget
+*
+* $LicenseInfo:firstyear=2009&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_PICKITEM_H
+#define LL_PICKITEM_H
+
+#include "llavatarpropertiesprocessor.h"
+#include "llpanel.h"
+
+struct LLPickData;
+
+static const std::string PICK_ID("pick_id");
+static const std::string PICK_CREATOR_ID("pick_creator_id");
+static const std::string PICK_NAME("pick_name");
+
+class LLPickItem final : public LLPanel, public LLAvatarPropertiesObserver
+{
+public:
+	LLPickItem();
+	~LLPickItem();
+	BOOL postBuild() override;
+
+	static LLPickItem* create();
+	void init(LLPickData* pick_data);
+	void setPickName(const std::string& name);
+	void setPickDesc(const std::string& descr);
+	void setPickId(const LLUUID& id);
+	void setCreatorId(const LLUUID& id) { mCreatorID = id; };
+	void setSnapshotId(const LLUUID& id) { mSnapshotID = id; };
+	void setNeedData(bool need) { mNeedData = need; };
+	const LLUUID& getPickId() const;
+	const std::string& getPickName() const;
+	const LLUUID& getCreatorId() const;
+	const LLUUID& getSnapshotId() const;
+	const LLVector3d& getPosGlobal() const;
+	const std::string getDescription() const;
+	const std::string& getSimName() const { return mSimName; }
+	const std::string& getUserName() const { return mUserName; }
+	const std::string& getOriginalName() const { return mOriginalName; }
+	const std::string& getPickDesc() const { return mPickDescription; }
+	void processProperties(void* data, EAvatarProcessorType type) override;
+	void update();
+
+	/** setting on/off background icon to indicate selected state */
+	void setValue(const LLSD& value) override;
+
+protected:
+	LLUUID mPickID;
+	LLUUID mCreatorID;
+	LLUUID mParcelID;
+	LLUUID mSnapshotID;
+	LLVector3d mPosGlobal;
+	bool mNeedData;
+
+	std::string mPickName;
+	std::string mUserName;
+	std::string mOriginalName;
+	std::string mPickDescription;
+	std::string mSimName;
+};
+
+#endif // LL_PICKITEM_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index b9635028ad4..7829c90cfc3 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -135,6 +135,7 @@
 #include "llfloaterprofilelegacy.h"
 #include "llfloaterprogressview.h"
 #include "llfloaterproperties.h"
+#include "llfloaterpublishclassified.h"
 #include "llfloaterregiondebugconsole.h"
 #include "llfloaterregioninfo.h"
 #include "llfloaterregionrestarting.h"
@@ -180,7 +181,6 @@
 #include "llmoveview.h"
 #include "llfloaterimnearbychat.h"
 #include "llpanelblockedlist.h"
-#include "llpanelprofileclassifieds.h"
 #include "llpreviewanim.h"
 #include "llpreviewgesture.h"
 #include "llpreviewnotecard.h"
@@ -370,7 +370,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("preview_texture", "floater_preview_texture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewTexture>, "preview");
 	LLFloaterReg::add("preview_trash", "floater_preview_trash.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreviewTrash>);
 	LLFloaterReg::add("properties", "floater_inventory_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProperties>);
-	LLFloaterReg::add("publish_classified", "floater_publish_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPublishClassifiedFloater>);
+	LLFloaterReg::add("publish_classified", "floater_publish_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPublishClassified>);
 	LLFloaterReg::add("save_pref_preset", "floater_save_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSavePrefPreset>);
 	LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSaveCameraPreset>);
 	LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>);
diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml
index 04a0bc800d8..d4a2745d1d6 100644
--- a/indra/newview/skins/default/xui/en/panel_classified_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml
@@ -38,15 +38,28 @@
   name="auto_renew_off">
     Disabled
  </panel.string>
+    <button
+     follows="top|left"
+     height="24"
+     image_hover_unselected="BackButton_Over"
+     image_pressed="BackButton_Press"
+     image_unselected="BackButton_Off"
+     layout="topleft"
+     name="back_btn"
+     left="10"
+     tab_stop="false"
+     top="2"
+     width="30"
+     use_draw_context_alpha="false" />
     <text
      follows="top|left|right"
      font="SansSerifHugeBold"
      height="26"
      layout="topleft"
-     left="12"
+     left_pad="4"
      name="title"
      text_color="LtGray"
-     top="2"
+     top="0"
      value="Classified Info"
      use_ellipses="true"
      width="275" />
@@ -407,7 +420,7 @@
 		         height="23"
 		         label="Teleport"
 		         layout="topleft"
-		         left="2"
+		         left="0"
 		         name="teleport_btn"
 		         top="0"
 		         width="101" />	
@@ -430,6 +443,24 @@
 		         top="0"
 		         width="100" />
 		  </layout_panel>	  
+		  
+		  <layout_panel
+			  follows="bottom|left|right"
+			  height="23"
+			  layout="bottomleft"
+			  left_pad="3"
+			  name="edit_btn_lp"
+		      auto_resize="true"
+			  width="101">
+			  <button
+		         follows="bottom|left|right"
+		         height="23"
+		         label="Edit"
+		         layout="topleft"
+		         name="edit_btn"
+		         top="0"
+		         width="101" />
+		  </layout_panel>
 	   </layout_stack>
     </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
new file mode 100644
index 00000000000..c8a6f568cee
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ follows="left|top|right|bottom"
+ height="569"
+ label="Edit Pick"
+ layout="topleft"
+ left="0"
+ min_height="350"
+ name="panel_edit_pick"
+ help_topic="profile_edit_pick"
+ top="0"
+ width="333">
+ <panel.string
+  name="location_notice">
+    (will update after save)
+ </panel.string>
+  <button
+     follows="top|left"
+     height="24"
+     image_hover_unselected="BackButton_Over"
+     image_pressed="BackButton_Press"
+     image_unselected="BackButton_Off"
+     layout="topleft"
+     name="back_btn"
+     left="10"
+     tab_stop="false"
+     top="2"
+     width="30"
+     use_draw_context_alpha="false" />
+   <text
+     type="string"
+     length="1"
+     follows="top"
+     font="SansSerifHugeBold"
+     height="26"
+     layout="topleft"
+     left_pad="4"
+     name="title"
+     text_color="LtGray"
+     top="2"
+     width="250">
+        Edit Pick
+    </text>
+   <scroll_container
+     color="DkGray2"
+     follows="all"
+     height="502"
+     layout="topleft"
+     left="8"
+     top_pad="10"
+     name="profile_scroll"
+     opaque="true"
+     width="312">
+    <panel
+     name="scroll_content_panel"
+     follows="left|top|right"
+     min_height="300"
+     layout="topleft"
+     top="0"
+     background_visible="false"
+     height="500"
+     left="0"
+     width="285">
+    <texture_picker
+     fallback_image="default_land_picture.j2c"
+     follows="left|top|right"
+     height="197"
+     width="272"
+     layout="topleft"
+     no_commit_on_selection="true"
+     top="10"
+     left="11"
+     name="pick_snapshot" />
+          <icon
+           height="197"
+           image_name="spacer24.tga"
+           layout="topleft"
+           name="edit_icon"
+           label=""
+           tool_tip="Click to select an image"
+           top="10"
+           left="11"
+           width="286" />
+        <text
+         type="string"
+         length="1"
+         follows="left|top|right"
+         height="15"
+         font="SansSerifSmall"
+         font.style="BOLD"
+         layout="topleft"
+         left="10"
+         top="215"
+         name="Name:"
+         text_color="white"
+         width="280">
+            Title:
+        </text>
+        <line_editor
+         follows="left|top|right"
+         font="SansSerif"
+         height="20"
+         layout="topleft"
+         left="10"
+         top_pad="2"
+         max_length_bytes="63"
+         name="pick_name"
+         width="273" />
+        <text
+         type="string"
+         length="1"
+         follows="left|top|right"
+         height="15"
+         font="SansSerifSmall"
+         font.style="BOLD"
+         layout="topleft"
+         left="10"
+         top_pad="20"
+         name="description_label"
+         text_color="white"
+         width="280">
+            Description:
+        </text>
+        <text_editor
+         follows="left|top|right"
+         height="100"
+         width="273"
+         hide_scrollbar="false"
+         layout="topleft"
+         left="10"
+         top_pad="2"
+         max_length="1023"
+         name="pick_desc"
+         spellcheck="true"
+         word_wrap="true" />
+        <text
+         type="string"
+         length="1"
+         font="SansSerifSmall"
+         font.style="BOLD"
+         follows="left|top|right"
+         height="15"
+         layout="topleft"
+         left="10"
+         name="location_label"
+         text_color="white"
+         top_pad="20"
+         width="280">
+            Location:
+        </text>
+        <text
+         type="string"
+         length="1"
+         follows="left|top|right"
+         height="50"
+         layout="topleft"
+         left="10"
+         name="pick_location"
+         top_pad="2"
+         width="280"
+         word_wrap="true">
+            loading...
+        </text>
+        <button
+         follows="left|top"
+         height="23"
+         label="Set to Current Location"
+         layout="topleft"
+         left="8"
+         top_pad="0"
+         name="set_to_curr_location_btn"
+         width="200" />
+    </panel>
+    </scroll_container>
+    <panel
+     follows="left|right|bottom"
+     height="23"
+     label="bottom_panel"
+     layout="topleft"
+     left="8"
+     name="bottom_panel"
+     top_pad="5"
+     width="315">
+     
+     	 <layout_stack
+		  follows="bottom|left|right"
+		  height="23"
+		  layout="topleft"
+		  name="layout_stack1"
+		  left="0"
+		  orientation="horizontal"
+		  top_pad="0"
+		  width="313">
+		  	 
+		  	 <layout_panel
+			  follows="bottom|left|right"
+			  height="23"
+			  layout="topleft"
+			  left="0"
+			  name="layout_panel1"
+		      auto_resize="true"
+			  width="150">
+		        <button
+		         follows="bottom|left|right"
+		         height="23"
+		         label="Save Pick"
+		         layout="topleft"
+		         name="save_changes_btn"
+		         top="0"
+		         left="1"
+		         width="149" />
+			  </layout_panel>
+			  
+			 <layout_panel
+			  follows="bottom|left|right"
+			  height="23"
+			  layout="topleft"
+			  left_pad="4"
+			  name="layout_panel2"
+		      auto_resize="true"
+			  width="146">
+		        <button
+		         follows="bottom|left|right"
+		         height="23"
+		         label="Cancel"
+		         layout="topleft"
+		         name="cancel_btn"
+		         top="0"
+		         left="1"
+		        width="145" />
+			  </layout_panel>
+	</layout_stack>
+		  
+    </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml
new file mode 100644
index 00000000000..99c47eb8257
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="570"
+ layout="topleft"
+ left="0"
+ min_height="350"
+ name="panel_pick_info"
+ help_topic="profile_pick_info"
+ top="0"
+ width="333">
+    <button
+     follows="top|left"
+     height="24"
+     image_hover_unselected="BackButton_Over"
+     image_pressed="BackButton_Press"
+     image_unselected="BackButton_Off"
+     layout="topleft"
+     name="back_btn"
+     left="10"
+     tab_stop="false"
+     top="2"
+     width="30"
+     use_draw_context_alpha="false" />
+    <text
+     follows="top|left|right"
+     font="SansSerifHugeBold"
+     height="26"
+     layout="topleft"
+     left_pad="4"
+     name="title"
+     text_color="LtGray"
+     top="2"
+     value="Pick Info"
+     use_ellipses="true"
+     width="275" />
+    <scroll_container
+     color="DkGray2"
+     opaque="true"
+     follows="all"
+     height="503"
+     layout="topleft"
+     left="8"
+     top_pad="10"
+     name="profile_scroll"
+     width="312">
+    <panel
+     name="scroll_content_panel"
+     follows="left|top|right"
+     min_height="300"
+     layout="topleft"
+     top="0"
+     background_visible="false"
+     height="400"
+     left="0"
+     width="285">
+        <texture_picker
+         fallback_image="default_land_picture.j2c"
+         enabled="false"
+         follows="left|top|right"
+         height="197"
+         layout="topleft"
+         left="11"
+         name="pick_snapshot"
+         top="10"
+         width="272" />
+        <text_editor
+         allow_scroll="false"
+         bg_visible="false"
+         follows="left|top|right"
+         h_pad="0"
+         height="35"
+         width="280"
+         layout="topleft"
+         font="SansSerifBig"
+         font.style="BOLD"
+         left="10"
+         top_pad="10"
+         name="pick_name"
+         read_only="true"
+         text_color="white"
+         v_pad="0"
+         value="[name]"
+         use_ellipses="true" />
+        <text_editor
+         allow_scroll="false"
+         bg_visible="false"
+         follows="left|top|right"
+         h_pad="0"
+         height="25"
+         layout="topleft"
+         left="10"
+         name="pick_location"
+         read_only="true"
+         width="280"
+         word_wrap="true"
+         v_pad="0"
+         value="[loading...]" />
+        <text_editor
+         bg_readonly_color="DkGray2"
+         follows="all"
+         height="100"
+         width="280"
+         parse_urls="true"	
+         layout="topleft"
+         left="10"
+         top_pad="2"
+         max_length="1023"
+         name="pick_desc"
+         read_only="true"
+         text_readonly_color="white"
+         value="[description]"
+         wrap="true" />
+    </panel>
+    </scroll_container>
+    <panel
+     follows="left|right|bottom"
+     height="23"
+     layout="topleft"
+     top_pad="5"
+     left="8"
+     name="buttons">
+       
+       <layout_stack
+		  follows="bottom|left|right"
+		  height="23"
+		  layout="topleft"
+		  name="layout_stack1"
+		  left="0"
+		  orientation="horizontal"
+		  top_pad="0"
+		  width="312">
+		  
+		  <layout_panel
+			  follows="bottom|left|right"
+			  height="23"
+			  layout="bottomleft"
+			  left="0"
+			  name="layout_panel1"
+		      auto_resize="true"
+			  width="101">
+			  <button
+			  	 follows="bottom|left|right"
+		         height="23"
+		         label="Teleport"
+		         layout="topleft"
+		         name="teleport_btn"
+		         top="0"
+		         width="101" />
+		  </layout_panel>
+		  
+		  <layout_panel
+			  follows="bottom|left|right"
+			  height="23"
+			  layout="bottomleft"
+			  left_pad="3"
+			  name="show_on_map_btn_lp"
+		      auto_resize="true"
+			  width="100">
+			  <button
+		         follows="bottom|left|right"
+		         height="23"
+		         label="Map"
+		         layout="topleft"
+		         name="show_on_map_btn"
+		         top_pad="0"
+		         width="100" />
+		  </layout_panel>	  
+		  
+		  <layout_panel
+			  follows="bottom|left|right"
+			  height="23"
+			  layout="bottomleft"
+			  left_pad="3"
+			  name="edit_btn_lp"
+		      auto_resize="true"
+			  width="101">
+			  <button
+		         follows="bottom|left|right"
+		         height="23"
+		         label="Edit"
+		         layout="topleft"
+		         name="edit_btn"
+		         top_pad="0"
+		         width="101" />
+		  </layout_panel>
+	   </layout_stack>
+    </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml b/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml
index 223a1357d94..f404a20e277 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml
@@ -159,7 +159,7 @@ Remove Friend
            name="interests_tab_panel"
            top="0" />
         </accordion_tab>
-        <!--<accordion_tab
+        <accordion_tab
          expanded="false"
          layout="topleft"
          name="avatar_picks_tab"
@@ -174,7 +174,7 @@ Remove Friend
            left="0"
            name="picks_tab_panel"
            top="0" />
-        </accordion_tab>-->
+        </accordion_tab>
         <accordion_tab
          expanded="false"
          layout="topleft"
-- 
GitLab