Files
SingularityViewer/indra/newview/llfloaterdirectory.cpp
Inusaito Sayori 7fee70543d Login Response support for destination_guide_url, OpenSimExtras support (properly) search-server-url, and support the new destination-guide-url from OpenSimExtras
Expands SignaledType's callback to accept const Type& as argument.
typedefs Signal::slot_type to slot_t so that SignaledType can be altered without needing to update all lines setting slots.

Merges floater_directory.xml with floater_directory(2|3).xml
Condenses translations down to one xml(, finally the nightmare is over).
Better ui code support for classic find all panel
Not like anyone cares, but ShowcaseURLDefault no longer persists value changes between sessions.

Moves SearchType and getSearchUrl(SearchType ty, bool is_web) from HippoGridInfo into a namespace in llpaneldirfind.cpp, the only place where it is used; so that it may wrap the sim feature lookup.

Thanks to Shyotl for the help in dynamically maintaining tab positions for dynamic tabs.
2014-07-31 08:12:00 -04:00

705 lines
20 KiB
C++

/**
* @file llfloaterdirectory.cpp
* @brief The "Find" floater. Should be llfloaterfind.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterdirectory.h"
#include "llfloatersearch.h" // For callback to open web search
#include "llpaneldirfind.h"
#include "llpaneldirevents.h"
#include "llpaneldirland.h"
#include "llpaneldirpeople.h"
#include "llpaneldirpopular.h"
#include "llpaneldirgroups.h"
#include "llpaneldirplaces.h"
#include "llpaneldirclassified.h"
#include "llagent.h"
#include "llpanelavatar.h"
#include "llpanelevent.h"
#include "llpanelclassified.h"
#include "llpanelgroup.h"
#include "llpanelplace.h"
#include "lluictrlfactory.h"
#include "hippogridmanager.h"
#include "lfsimfeaturehandler.h"
#include "llenvmanager.h"
#include "llnotificationsutil.h"
#include "llviewerregion.h"
const char* market_panel = "market_panel";
void set_tab_visible(LLTabContainer* container, LLPanel* tab, bool visible, LLPanel* prev_tab)
{
if (visible)
{
if (prev_tab)
container->lockTabs(container->getIndexForPanel(prev_tab) + 1);
container->addTabPanel(tab, tab->getLabel(), false, 0, false, LLTabContainer::START);
if (prev_tab)
container->unlockTabs();
}
else container->removeTabPanel(tab);
}
class LLPanelDirMarket : public LLPanelDirFind
{
public:
LLPanelDirMarket(const std::string& name, LLFloaterDirectory* floater)
: LLPanelDirFind(name, floater, "market_browser")
{}
/*virtual*/ void search(const std::string& url)
{
if (url.empty()) navigateToDefaultPage();
}
/*virtual*/ void navigateToDefaultPage()
{
if (mWebBrowser && !mMarketplaceURL.empty()) mWebBrowser->navigateTo(mMarketplaceURL);
}
/*virtual*/ BOOL postBuild()
{
if (gHippoGridManager->getConnectedGrid()->isSecondLife())
{
mMarketplaceURL = getString("default_search_page");
}
else
{
getChild<LLUICtrl>("reset_btn")->setCommitCallback(boost::bind(&LLPanelDirMarket::navigateToDefaultPage, this));
}
return LLPanelDirFind::postBuild();
}
void handleRegionChange(LLTabContainer* container)
{
if (LLViewerRegion* region = gAgent.getRegion())
{
if (region->getFeaturesReceived())
{
setMarketplaceURL(container);
}
else
{
region->setFeaturesReceivedCallback(boost::bind(&LLPanelDirMarket::setMarketplaceURL, this, container));
}
}
}
void setMarketplaceURL(LLTabContainer* container)
{
if (LLViewerRegion* region = gAgent.getRegion())
{
LLSD info;
region->getSimulatorFeatures(info);
if (info.has("MarketplaceURL"))
{
std::string url = info["MarketplaceURL"].asString();
if (mMarketplaceURL == url) return;
if (mMarketplaceURL.empty())
{
container->addTabPanel(this, getLabel());
mMarketplaceURL = url;
navigateToDefaultPage();
}
else
{
LLNotificationsUtil::add("MarketplaceURLChanged", LLSD(), LLSD(),
boost::bind(&LLPanelDirMarket::onConfirmChangeMarketplaceURL, this, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), url));
}
}
else if (!mMarketplaceURL.empty())
{
if (gFloaterView->getParentFloater(this)->getVisible()) // Notify the user that they're no longer on the region with the marketplace when search is open
{
LLNotificationsUtil::add("MarketplaceURLGone");
}
else // Search is not in use, remove the marketplace
{
mMarketplaceURL = "";
container->removeTabPanel(this);
}
}
}
}
void onConfirmChangeMarketplaceURL(const S32 option, const std::string& url)
{
if (option == 1) return; //no
else //yes
{
mMarketplaceURL = url;
if (option == 2) navigateToDefaultPage();
}
}
static void* create(void* data)
{
return new LLPanelDirMarket(market_panel, static_cast<LLFloaterDirectory*>(data));
}
private:
std::string mMarketplaceURL;
};
namespace {
void* createWebPanel(void* data)
{
struct LLPanelDirWeb : public LLPanelDirFind
{
LLPanelDirWeb(LLFloaterDirectory* f) : LLPanelDirFind("web_panel", f, "web_search_browser") {}
/*virtual*/ void search(const std::string& url) {}
/*virtual*/ void navigateToDefaultPage()
{
if (mWebBrowser) mWebBrowser->navigateTo(getString("default_search_page"));
}
};
return new LLPanelDirWeb(static_cast<LLFloaterDirectory*>(data));
}
} // namespace
LLFloaterDirectory* LLFloaterDirectory::sInstance = NULL;
//static
S32 LLFloaterDirectory::sOldSearchCount = 0; // debug
S32 LLFloaterDirectory::sNewSearchCount = 0; // debug
LLFloaterDirectory::LLFloaterDirectory(const std::string& name)
: LLFloater(name, std::string("FloaterFindRect2"), LLStringUtil::null),
mMinimizing(false)
{
sInstance = this;
mFindAllPanel = NULL;
mClassifiedPanel = NULL;
mEventsPanel = NULL;
mLandPanel = NULL;
mPanelAvatarp = NULL;
mPanelEventp = NULL;
mPanelGroupp = NULL;
mPanelGroupHolderp = NULL;
mPanelPlacep = NULL;
mPanelPlaceSmallp = NULL;
mPanelClassifiedp = NULL;
// Build the floater with our tab panel classes
bool secondlife = gHippoGridManager->getConnectedGrid()->isSecondLife();
LLCallbackMap::map_t factory_map;
factory_map["classified_panel"] = LLCallbackMap(createClassified, this);
factory_map["events_panel"] = LLCallbackMap(createEvents, this);
factory_map["places_panel"] = LLCallbackMap(createPlaces, this);
factory_map["land_sales_panel"] = LLCallbackMap(createLand, this);
factory_map["people_panel"] = LLCallbackMap(createPeople, this);
factory_map["groups_panel"] = LLCallbackMap(createGroups, this);
factory_map[market_panel] = LLCallbackMap(LLPanelDirMarket::create, this);
factory_map["find_all_panel"] = LLCallbackMap(createFindAll, this);
factory_map["showcase_panel"] = LLCallbackMap(createShowcase, this);
if (secondlife)
{
factory_map["web_panel"] = LLCallbackMap(createWebPanel, this);
}
else
{
factory_map["find_all_old_panel"] = LLCallbackMap(createFindAllOld, this);
}
factory_map["classified_details_panel"] = LLCallbackMap(createClassifiedDetail, this);
factory_map["event_details_panel"] = LLCallbackMap(createEventDetail, this);
factory_map["group_details_panel"] = LLCallbackMap(createGroupDetail, this);
factory_map["group_details_panel_holder"] = LLCallbackMap(createGroupDetailHolder, this);
factory_map["place_details_panel"] = LLCallbackMap(createPlaceDetail, this);
factory_map["place_details_small_panel"] = LLCallbackMap(createPlaceDetailSmall, this);
factory_map["Panel Avatar"] = LLCallbackMap(createPanelAvatar, this);
mCommitCallbackRegistrar.add("Search.WebFloater", boost::bind(&LLFloaterSearch::open, boost::bind(LLFloaterSearch::getInstance)));
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_directory.xml", &factory_map);
moveResizeHandlesToFront();
if (mPanelAvatarp)
{
mPanelAvatarp->selectTab(0);
}
LLTabContainer* container = getChild<LLTabContainer>("Directory Tabs");
if (secondlife)
{
container->removeTabPanel(getChild<LLPanel>("find_all_old_panel")); // Not used
}
else
{
container->removeTabPanel(getChild<LLPanel>("web_panel")); // Not needed
LLPanel* panel(getChild<LLPanel>("find_all_panel"));
LLPanel* prev_tab(getChild<LLPanel>("find_all_old_panel"));
LFSimFeatureHandler& inst(LFSimFeatureHandler::instance());
set_tab_visible(container, panel, !inst.searchURL().empty(), prev_tab);
inst.setSearchURLCallback(boost::bind(set_tab_visible, container, panel, !boost::bind(&std::string::empty, _1), prev_tab));
panel = getChild<LLPanel>("showcase_panel");
prev_tab = getChild<LLPanel>("events_panel");
set_tab_visible(container, panel, !inst.destinationGuideURL().empty(), prev_tab);
inst.setDestinationGuideURLCallback(boost::bind(set_tab_visible, container, panel, !boost::bind(&std::string::empty, _1), prev_tab));
LLPanelDirMarket* marketp = static_cast<LLPanelDirMarket*>(container->getPanelByName(market_panel));
container->removeTabPanel(marketp); // Until we get a MarketPlace URL, tab is removed.
marketp->handleRegionChange(container);
LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLPanelDirMarket::handleRegionChange, marketp, container));
}
container->setCommitCallback(boost::bind(&LLFloaterDirectory::onTabChanged,_2));
}
LLFloaterDirectory::~LLFloaterDirectory()
{
sInstance = NULL;
//Note: this function is defined in the class LLFloater.
//however, it causes crash if this line is postponed to ~LLFloater().
//because it uses some pointers deleted below. That is, those pointers are used again after deleting.
setMinimized( FALSE );
delete mPanelAvatarp; mPanelAvatarp = NULL;
delete mPanelEventp; mPanelEventp = NULL;
delete mPanelGroupp; mPanelGroupp = NULL;
delete mPanelGroupHolderp; mPanelGroupHolderp = NULL;
delete mPanelPlacep; mPanelPlacep = NULL;
delete mPanelPlaceSmallp; mPanelPlaceSmallp = NULL;
delete mPanelClassifiedp; mPanelClassifiedp = NULL;
gSavedSettings.setBOOL("ShowDirectory", FALSE);
}
// static
void *LLFloaterDirectory::createFindAll(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mFindAllPanel = LLPanelDirFindAllInterface::create(self);
return self->mFindAllPanel;
}
// static
void* LLFloaterDirectory::createClassified(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mClassifiedPanel = new LLPanelDirClassified("classified_panel", self);
return self->mClassifiedPanel;
}
// static
void* LLFloaterDirectory::createEvents(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mEventsPanel = new LLPanelDirEvents("events_panel", self);
return self->mEventsPanel;
}
// static
void* LLFloaterDirectory::createShowcase(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
return new LLPanelDirPopular("showcase_panel", self);
}
// static
void* LLFloaterDirectory::createPlaces(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
return new LLPanelDirPlaces("places_panel", self);
}
// static
void* LLFloaterDirectory::createLand(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mLandPanel = new LLPanelDirLand("land_panel", self);
return self->mLandPanel;
}
// static
void* LLFloaterDirectory::createPeople(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
return new LLPanelDirPeople("people_panel", self);
}
// static
void* LLFloaterDirectory::createGroups(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
return new LLPanelDirGroups("groups_panel", self);
}
// static
void *LLFloaterDirectory::createFindAllOld(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
return new LLPanelDirFindAllOld("find_all_old_panel", self);
}
// static
void* LLFloaterDirectory::createClassifiedDetail(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mPanelClassifiedp = new LLPanelClassifiedInfo(true, false);
self->mPanelClassifiedp->setVisible(FALSE);
return self->mPanelClassifiedp;
}
//----------------------------------------------------------------------------
void* LLFloaterDirectory::createPanelAvatar(void* data)
{
LLFloaterDirectory* self = (LLFloaterDirectory*)data;
self->mPanelAvatarp = new LLPanelAvatar("Avatar", LLRect(),
FALSE); // disallow editing in search context (SL-48632)
self->mPanelAvatarp->setVisible(FALSE);
return self->mPanelAvatarp;
}
//----------------------------------------------------------------------------
// static
void* LLFloaterDirectory::createEventDetail(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mPanelEventp = new LLPanelEvent();
LLUICtrlFactory::getInstance()->buildPanel(self->mPanelEventp, "panel_event.xml");
self->mPanelEventp->setVisible(FALSE);
return self->mPanelEventp;
}
// static
void* LLFloaterDirectory::createGroupDetail(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mPanelGroupp = new LLPanelGroup(gAgent.getGroupID());
self->mPanelGroupp->setAllowEdit(false); // Singu Note: This setting actually just tells the panel whether or not it is in search
self->mPanelGroupp->setVisible(FALSE);
return self->mPanelGroupp;
}
// static
void* LLFloaterDirectory::createGroupDetailHolder(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mPanelGroupHolderp = new LLPanel(std::string("PanelGroupHolder"));
self->mPanelGroupHolderp->setVisible(FALSE);
return self->mPanelGroupHolderp;
}
// static
void* LLFloaterDirectory::createPlaceDetail(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mPanelPlacep = new LLPanelPlace();
LLUICtrlFactory::getInstance()->buildPanel(self->mPanelPlacep, "panel_place.xml");
self->mPanelPlacep->setVisible(FALSE);
return self->mPanelPlacep;
}
// static
void* LLFloaterDirectory::createPlaceDetailSmall(void* userdata)
{
LLFloaterDirectory *self = (LLFloaterDirectory*)userdata;
self->mPanelPlaceSmallp = new LLPanelPlace();
LLUICtrlFactory::getInstance()->buildPanel(self->mPanelPlaceSmallp, "panel_place_small.xml");
self->mPanelPlaceSmallp->setVisible(FALSE);
return self->mPanelPlaceSmallp;
}
// static
void LLFloaterDirectory::requestClassifieds()
{
if (sInstance && sInstance->mClassifiedPanel)
{
sInstance->mClassifiedPanel->performQuery();
}
}
void LLFloaterDirectory::searchInAll(const std::string& search_text)
{
LLPanelDirFindAllInterface::search(sInstance->mFindAllPanel, search_text);
performQueryOn2("classified_panel", search_text);
performQueryOn2("events_panel", search_text);
performQueryOn2("groups_panel", search_text);
performQueryOn2("people_panel", search_text);
performQueryOn2("places_panel", search_text);
sInstance->open();
}
void LLFloaterDirectory::showFindAll(const std::string& search_text)
{
showPanel(LFSimFeatureHandler::instance().searchURL().empty() ? "find_all_old_panel" : "find_all_panel");
LLPanelDirFindAllInterface::search(sInstance->mFindAllPanel, search_text);
}
void LLFloaterDirectory::showClassified(const LLUUID& classified_id)
{
showPanel("classified_panel");
if (sInstance->mClassifiedPanel)
{
sInstance->mClassifiedPanel->selectByUUID(classified_id);
}
}
// static
void LLFloaterDirectory::showClassified(const std::string& search_text)
{
performQueryOn("classified_panel", search_text);
}
// static
void LLFloaterDirectory::showEvents(S32 event_id)
{
showPanel("events_panel");
if (sInstance->mEventsPanel)
{
// HACK: force query for today's events
sInstance->mEventsPanel->setDay(0);
sInstance->mEventsPanel->performQuery();
if (event_id != 0)
{
sInstance->mEventsPanel->selectEventByID(event_id);
}
}
}
// static
void LLFloaterDirectory::showEvents(const std::string& search_text)
{
performQueryOn("events_panel", search_text);
}
// static
void LLFloaterDirectory::showLandForSale(const LLUUID& parcel_id)
{
showPanel("land_sales_panel");
if (sInstance->mLandPanel)
{
sInstance->mLandPanel->selectByUUID(parcel_id);
}
}
// static
void LLFloaterDirectory::showDestinations()
{
showPanel("showcase_panel");
}
// static
void LLFloaterDirectory::showGroups(const std::string& search_text)
{
performQueryOn("groups_panel", search_text);
}
// static
void LLFloaterDirectory::showPeople(const std::string& search_text)
{
performQueryOn("people_panel", search_text);
}
// static
void LLFloaterDirectory::showPlaces(const std::string& search_text)
{
performQueryOn("places_panel", search_text);
}
//static
void LLFloaterDirectory::performQueryOn(const std::string& name, const std::string& search_text)
{
showPanel(name);
performQueryOn2(name, search_text);
}
//static
void LLFloaterDirectory::performQueryOn2(const std::string& name, const std::string& search_text)
{
if (search_text.empty()) return; // We're done here.
LLPanelDirBrowser* panel = sInstance->getChild<LLPanelDirBrowser>(name);
panel->getChild<LLUICtrl>("name")->setValue(search_text);
panel->performQuery();
}
// static
void LLFloaterDirectory::refreshGroup(const LLUUID& group_id)
{
if (sInstance && sInstance->mPanelGroupp
&& (sInstance->mPanelGroupp->getID() == group_id) )
{
sInstance->mPanelGroupp->refreshData();
}
}
void LLFloaterDirectory::focusCurrentPanel()
{
LLTabContainer* tabs = getChild<LLTabContainer>("Directory Tabs");
if (!tabs) return;
LLPanel* panel = tabs->getCurrentPanel();
if (!panel) return;
panel->setFocus(TRUE);
}
// static
void LLFloaterDirectory::showPanel(const std::string& tabname)
{
// This function gets called when web browser clicks are processed,
// so we don't delete the existing panel, which would delete the
// web browser instance currently handling the click. JC
if (!sInstance)
{
sInstance = new LLFloaterDirectory("directory");
}
sInstance->open(); /*Flawfinder: ignore*/
sInstance->childShowTab("Directory Tabs", tabname);
sInstance->focusCurrentPanel();
}
// static
void LLFloaterDirectory::toggleFind(void*)
{
if (!sInstance)
{
std::string panel = gSavedSettings.getString("LastFindPanel");
if (!gHippoGridManager->getConnectedGrid()->isSecondLife())
{
LFSimFeatureHandler& inst(LFSimFeatureHandler::instance());
if (panel == "web_panel"
|| (inst.searchURL().empty() && panel == "find_all_panel")
|| (inst.destinationGuideURL().empty() && panel == "showcase_panel"))
panel = "find_all_old_panel";
}
else if (panel == "find_all_old_panel") panel = "find_all_panel";
showPanel(panel);
// HACK: force query for today's events
if (sInstance->mEventsPanel)
{
sInstance->mEventsPanel->setDay(0);
//sInstance->mEventsPanel->performQuery(); // Temporary change to help DB - Sabin
}
return;
}
BOOL panel_visible = sInstance->getVisible();
if (!panel_visible)
{
sInstance->open(); /*Flawfinder: ignore*/
sInstance->focusCurrentPanel();
}
else
{
sInstance->close();
}
}
// static
void LLFloaterDirectory::toggleEvents(void*)
{
if (!sInstance)
{
showEvents(0);
return;
}
BOOL panel_visible = sInstance->getVisible();
if (!panel_visible)
{
sInstance->open(); /*Flawfinder: ignore*/
sInstance->showEvents(0);
}
else
{
LLPanel *current_panel = sInstance->childGetVisibleTab("Directory Tabs");
if (current_panel == sInstance->mEventsPanel)
{
sInstance->close();
}
else
{
sInstance->showEvents(0);
}
}
}
// static
void LLFloaterDirectory::hide(void*)
{
if (sInstance)
{
sInstance->close();
}
}
// virtual
void LLFloaterDirectory::setVisible(BOOL visible)
{
gSavedSettings.setBOOL("ShowDirectory", visible);
LLFloater::setVisible(visible);
}
void LLFloaterDirectory::onClose(bool app_quitting)
{
setVisible(FALSE);
}
// static
void LLFloaterDirectory::onTabChanged( const LLSD& param )
{
gSavedSettings.setString("LastFindPanel", param.asString());
}
void LLFloaterDirectory::hideAllDetailPanels()
{
if (mPanelAvatarp) mPanelAvatarp->setVisible(FALSE);
if (mPanelEventp) mPanelEventp->setVisible(FALSE);
if (mPanelGroupp) mPanelGroupp->setVisible(FALSE);
if (mPanelGroupHolderp) mPanelGroupHolderp->setVisible(FALSE);
if (mPanelPlacep) mPanelPlacep->setVisible(FALSE);
if (mPanelPlaceSmallp) mPanelPlaceSmallp->setVisible(FALSE);
if (mPanelClassifiedp) mPanelClassifiedp->setVisible(FALSE);
}