From 4d7f622a3c6a2fdec1c57ad4506ae49786b37dfc Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:02:03 +0300 Subject: viewer#2065 Region restart schedule floater --- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 11 + indra/newview/llfloaterregioninfo.cpp | 23 ++ indra/newview/llfloaterregioninfo.h | 2 + indra/newview/llfloaterregionrestartschedule.cpp | 386 +++++++++++++++++++++ indra/newview/llfloaterregionrestartschedule.h | 74 ++++ indra/newview/llviewerregion.cpp | 1 + .../xui/en/floater_region_restart_schedule.xml | 278 +++++++++++++++ .../skins/default/xui/en/panel_region_general.xml | 14 +- 9 files changed, 790 insertions(+), 1 deletion(-) create mode 100644 indra/newview/llfloaterregionrestartschedule.cpp create mode 100644 indra/newview/llfloaterregionrestartschedule.h create mode 100644 indra/newview/skins/default/xui/en/floater_region_restart_schedule.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d4c2875c6c..def2d8f0c0 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -278,6 +278,7 @@ set(viewer_SOURCE_FILES llfloaterregioninfo.cpp llfloaterreporter.cpp llfloaterregionrestarting.cpp + llfloaterregionrestartschedule.cpp llfloatersavecamerapreset.cpp llfloatersaveprefpreset.cpp llfloatersceneloadstats.cpp @@ -945,6 +946,7 @@ set(viewer_HEADER_FILES llfloaterregioninfo.h llfloaterreporter.h llfloaterregionrestarting.h + llfloaterregionrestartschedule.h llfloatersavecamerapreset.h llfloatersaveprefpreset.h llfloatersceneloadstats.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 235d294849..97cab58eb1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12682,6 +12682,17 @@ Value 1 + Use24HourClock + + Comment + 12 vs 24. At the moment only for region restart schedule floater + Persist + 0 + Type + Boolean + Value + 0 + EnvironmentPersistAcrossLogin Comment diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index cc9aca1338..02ef342c2a 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -61,6 +61,7 @@ #include "llfloatergroups.h" #include "llfloaterreg.h" #include "llfloaterregiondebugconsole.h" +#include "llfloaterregionrestartschedule.h" #include "llfloatertelehub.h" #include "llgltfmateriallist.h" #include "llinventorymodel.h" @@ -259,6 +260,7 @@ bool LLFloaterRegionInfo::postBuild() panel = new LLPanelRegionGeneralInfo; mInfoPanels.push_back(panel); panel->getCommitCallbackRegistrar().add("RegionInfo.ManageTelehub", boost::bind(&LLPanelRegionInfo::onClickManageTelehub, panel)); + panel->getCommitCallbackRegistrar().add("RegionInfo.ManageRestart", boost::bind(&LLPanelRegionInfo::onClickManageRestartSchedule, panel)); panel->buildFromFile("panel_region_general.xml"); mTab->addTabPanel(panel); @@ -862,6 +864,25 @@ void LLPanelRegionInfo::onClickManageTelehub() LLFloaterReg::showInstance("telehubs"); } +void LLPanelRegionInfo::onClickManageRestartSchedule() +{ + LLFloater* floaterp = mFloaterRestartScheduleHandle.get(); + // Show the dialog + if (!floaterp) + { + floaterp = new LLFloaterRegionRestartSchedule(this); + } + + if (floaterp->getVisible()) + { + floaterp->closeFloater(); + } + else + { + floaterp->openFloater(); + } +} + ///////////////////////////////////////////////////////////////////////////// // LLPanelRegionGeneralInfo // @@ -877,6 +898,8 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region) getChildView("kick_all_btn")->setEnabled(allow_modify); getChildView("im_btn")->setEnabled(allow_modify); getChildView("manage_telehub_btn")->setEnabled(allow_modify); + getChildView("manage_restart_btn")->setEnabled(allow_modify); + getChildView("manage_restart_btn")->setVisible(LLFloaterRegionRestartSchedule::canUse()); // Data gets filled in by processRegionInfo diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 60564435d7..b604a28fc3 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -154,6 +154,7 @@ public: void disableButton(const std::string& btn_name); void onClickManageTelehub(); + void onClickManageRestartSchedule(); protected: void initCtrl(const std::string& name); @@ -174,6 +175,7 @@ protected: // member data LLHost mHost; + LLHandle mFloaterRestartScheduleHandle; }; ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llfloaterregionrestartschedule.cpp b/indra/newview/llfloaterregionrestartschedule.cpp new file mode 100644 index 0000000000..59bcb22dce --- /dev/null +++ b/indra/newview/llfloaterregionrestartschedule.cpp @@ -0,0 +1,386 @@ +/** + * @file llfloaterregionrestartschedule.cpp + * @author Andrii Kleshchev + * @brief LLFloaterRegionRestartSchedule class + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "llfloaterregionrestartschedule.h" + +#include "llagent.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "lllineeditor.h" +#include "llviewercontrol.h" + + +// match with values used by capability +constexpr char CHECKBOX_PREFIXES[] = +{ + 's', + 'm', + 't', + 'w', + 'r', + 'f', + 'a', +}; + +const std::string CHECKBOX_NAME = "_chk"; + +LLFloaterRegionRestartSchedule::LLFloaterRegionRestartSchedule( + LLView* owner) + : LLFloater(LLSD()) + , mOwnerHandle(owner->getHandle()) +{ + buildFromFile("floater_region_restart_schedule.xml"); +} + +LLFloaterRegionRestartSchedule::~LLFloaterRegionRestartSchedule() +{ + +} + +bool LLFloaterRegionRestartSchedule::postBuild() +{ + mPMAMButton = getChild("am_pm_btn"); + mPMAMButton->setClickedCallback([this](LLUICtrl*, const LLSD&) { onPMAMButtonClicked(); }); + + // By default mPMAMButton is supposed to be visible. + // If localized xml set mPMAMButton to be invisible, assume + // 24h format and prealligned "UTC" label + if (mPMAMButton->getVisible()) + { + bool use_24h_format = gSavedSettings.getBOOL("Use24HourClock"); + if (use_24h_format) + { + mPMAMButton->setVisible(false); + LLUICtrl* lbl = getChild("utc_label"); + lbl->translate(-mPMAMButton->getRect().getWidth(), 0); + } + } + + mSaveButton = getChild("save_btn"); + mSaveButton->setClickedCallback([this](LLUICtrl*, const LLSD&) { onSaveButtonClicked(); }); + + mCancelButton = getChild("cancel_btn"); + mCancelButton->setClickedCallback([this](LLUICtrl*, const LLSD&) { closeFloater(false); }); + + + mHoursLineEditor = getChild("hours_edt"); + mHoursLineEditor->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mHoursLineEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& value) { onCommitHours(value); }); + + mMinutesLineEditor = getChild("minutes_edt"); + mMinutesLineEditor->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mMinutesLineEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& value) { onCommitMinutes(value); }); + + for (char c : CHECKBOX_PREFIXES) + { + std::string name = c + CHECKBOX_NAME; + LLCheckBoxCtrl* chk = getChild(name); + chk->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& value) { mSaveButton->setEnabled(true); }); + } + + resetUI(false); + + return true; +} + +void LLFloaterRegionRestartSchedule::onOpen(const LLSD& key) +{ + std::string url = gAgent.getRegionCapability("RegionSchedule"); + if (!url.empty()) + { + LLCoros::instance().launch("LLFloaterRegionRestartSchedule::requestRegionShcheduleCoro", + boost::bind(&LLFloaterRegionRestartSchedule::requestRegionShcheduleCoro, url, getHandle())); + + mSaveButton->setEnabled(false); + } + else + { + LL_WARNS("Region") << "Started region schedule floater, but RegionSchedule capability is not available" << LL_ENDL; + } +} + +void LLFloaterRegionRestartSchedule::draw() +{ + LLView* owner = mOwnerHandle.get(); + if (owner) + { + static LLCachedControl max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); + drawConeToOwner(mContextConeOpacity, max_opacity, owner); + } + + LLFloater::draw(); +} + +void LLFloaterRegionRestartSchedule::onPMAMButtonClicked() +{ + mSaveButton->setEnabled(true); + mTimeAM = !mTimeAM; + updateAMPM(); +} + +void LLFloaterRegionRestartSchedule::onSaveButtonClicked() +{ + std::string url = gAgent.getRegionCapability("RegionSchedule"); + if (!url.empty()) + { + std::string days; + for (char c : CHECKBOX_PREFIXES) + { + std::string name = c + CHECKBOX_NAME; + LLCheckBoxCtrl* chk = getChild(name); + if (chk->getValue()) + { + days += c; + } + } + LLSD restart; + if (days.size() < 7) + { + LLStringUtil::toUpper(days); + restart["type"] = "W"; + // if days are empty, will reset schedule + restart["days"] = days; + } + else + { + restart["type"] = "D"; + } + S32 hours = mHoursLineEditor->getValue().asInteger(); + if (mPMAMButton->getVisible()) + { + if (hours == 12) + { + hours = 0; // 12:00 AM equals 0:00, while 12:00 PM equals 12:00 + } + if (!mTimeAM) + { + hours += 12; + } + } + restart["time"] = hours * 3600 + mMinutesLineEditor->getValue().asInteger() * 60; + + LLSD body; + body["restart"] = restart; // event name, at the moment only "restart" is supported + LLCoros::instance().launch("LLFloaterRegionRestartSchedule::setRegionShcheduleCoro", + boost::bind(&LLFloaterRegionRestartSchedule::setRegionShcheduleCoro, url, body, getHandle())); + + mSaveButton->setEnabled(false); + } + else + { + LL_WARNS("Region") << "Saving region schedule, but RegionSchedule capability is not available" << LL_ENDL; + } +} + +void LLFloaterRegionRestartSchedule::onCommitHours(const LLSD& value) +{ + S32 hours = value.asInteger(); + if (mPMAMButton->getVisible()) + { + // 0:00 equals 12:00 AM 1:00 equals 1:00 AM, 12am < 1am < 2am < 3am... + if (hours == 0) hours = 12; + llclamp(hours, 1, 12); + } + else + { + llclamp(hours, 0, 23); + } + mHoursLineEditor->setText(llformat("%02d", hours)); + mSaveButton->setEnabled(true); +} + +void LLFloaterRegionRestartSchedule::onCommitMinutes(const LLSD& value) +{ + S32 minutes = value.asInteger(); + llclamp(minutes, 0, 59); + mMinutesLineEditor->setText(llformat("%02d", minutes)); + mSaveButton->setEnabled(true); +} + +void LLFloaterRegionRestartSchedule::resetUI(bool enable_ui) +{ + for (char c : CHECKBOX_PREFIXES) + { + std::string name = c + CHECKBOX_NAME; + LLCheckBoxCtrl* chk = getChild(name); + chk->setValue(false); + chk->setEnabled(enable_ui); + } + if (mPMAMButton->getVisible()) + { + mHoursLineEditor->setValue("12"); + mPMAMButton->setEnabled(enable_ui); + } + else + { + mHoursLineEditor->setValue("00"); + } + mMinutesLineEditor->setValue("00"); + mMinutesLineEditor->setEnabled(enable_ui); + mHoursLineEditor->setEnabled(enable_ui); + mTimeAM = true; + updateAMPM(); +} + +void LLFloaterRegionRestartSchedule::updateAMPM() +{ + std::string value; + if (mTimeAM) + { + value = getString("am_string"); + } + else + { + value = getString("pm_string"); + } + mPMAMButton->setLabel(value); +} + +bool LLFloaterRegionRestartSchedule::canUse() +{ + std::string url = gAgent.getRegionCapability("RegionSchedule"); + return !url.empty(); +} + +void LLFloaterRegionRestartSchedule::requestRegionShcheduleCoro(std::string url, LLHandle handle) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("RegionShcheduleRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + + httpOpts->setWantHeaders(true); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LLFloaterRegionRestartSchedule* floater = dynamic_cast(handle.get()); + if (!floater) + { + LL_DEBUGS("Region") << "Region Restart Schedule floater is already dead" << LL_ENDL; + } + else if (!status) + { + LL_WARNS("Region") << "Failed to get region schedule: " << status.toString() << LL_ENDL; + floater->resetUI(false); + } + else if (!result.has("restart")) + { + floater->resetUI(true); // no restart schedule yet + } + else + { + // example: 'restart':{'days':'TR','time':i7200,'type':'W'} + LLSD &restart = result["restart"]; + std::string type = restart["type"]; + std::string days = restart["days"]; + if (type == "W") // weekly || restart.has("days") + { + LLStringUtil::toLower(days); + for (char c : CHECKBOX_PREFIXES) + { + bool enabled = days.find(c) != std::string::npos; + std::string name = c + CHECKBOX_NAME; + LLCheckBoxCtrl *chk = floater->getChild(name); + chk->setValue(enabled); + chk->setEnabled(true); + } + } + else // dayly + { + for (char c : CHECKBOX_PREFIXES) + { + std::string name = c + CHECKBOX_NAME; + LLCheckBoxCtrl* chk = floater->getChild(name); + chk->setValue(true); + chk->setEnabled(true); + } + } + + S32 seconds_after_midnight = restart["time"].asInteger(); + S32 hours = seconds_after_midnight / 3600; + S32 minutes = (seconds_after_midnight % 3600) / 60; + + if (floater->mPMAMButton->getVisible()) + { + if (hours >= 12) + { + hours -= 12; + floater->mTimeAM = false; + } + else + { + floater->mTimeAM = true; + } + if (hours == 0) + { + hours = 12; // 0:00 equals 12:00 AM , 1:00 equals 1:00 AM + } + floater->mPMAMButton->setEnabled(true); + } + else + { + floater->mTimeAM = true; + } + floater->updateAMPM(); + floater->mHoursLineEditor->setText(llformat("%02d", hours)); + floater->mHoursLineEditor->setEnabled(true); + floater->mMinutesLineEditor->setText(llformat("%02d", minutes)); + floater->mMinutesLineEditor->setEnabled(true); + + LL_DEBUGS("Region") << "Region restart schedule type: " << type + << " Days: " << days + << " Time:" << hours << ":" << minutes << LL_ENDL; + } +} + +void LLFloaterRegionRestartSchedule::setRegionShcheduleCoro(std::string url, LLSD body, LLHandle handle) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("RegionShcheduleSetter", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + + httpOpts->setWantHeaders(true); + + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LLFloaterRegionRestartSchedule* floater = dynamic_cast(handle.get()); + if (floater) + { + floater->closeFloater(); + } +} diff --git a/indra/newview/llfloaterregionrestartschedule.h b/indra/newview/llfloaterregionrestartschedule.h new file mode 100644 index 0000000000..465ed538a5 --- /dev/null +++ b/indra/newview/llfloaterregionrestartschedule.h @@ -0,0 +1,74 @@ +/** + * @file llfloaterregionrestartschedule.h + * @author Andrii Kleshchev + * @brief LLFloaterRegionRestartSchedule class header file + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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_LLFLOATERREGIONRESTARTSCHEDULE_H +#define LL_LLFLOATERREGIONRESTARTSCHEDULE_H + +#include "llfloater.h" + +class LLLineEditor; +class LLButton; + +class LLFloaterRegionRestartSchedule : public LLFloater +{ +public: + LLFloaterRegionRestartSchedule(LLView* owner); + + virtual ~LLFloaterRegionRestartSchedule(); + + bool postBuild() override; + void onOpen(const LLSD& key) override; + void draw() override; + + void onPMAMButtonClicked(); + void onSaveButtonClicked(); + + void onCommitHours(const LLSD& value); + void onCommitMinutes(const LLSD& value); + + void resetUI(bool enable_ui); + void updateAMPM(); + + static bool canUse(); + +protected: + static void requestRegionShcheduleCoro(std::string url, LLHandle handle); + static void setRegionShcheduleCoro(std::string url, LLSD body, LLHandle handle); + + LLHandle mOwnerHandle; + F32 mContextConeOpacity{ 0.f }; + + LLLineEditor* mHoursLineEditor{nullptr}; + LLLineEditor* mMinutesLineEditor{ nullptr }; + LLButton* mPMAMButton{ nullptr }; + LLButton* mSaveButton{ nullptr }; + LLButton* mCancelButton{ nullptr }; + + bool mTimeAM{ true }; +}; + +#endif // LL_LLFLOATERREGIONRESTARTSCHEDULE_H diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 7623ab56a5..ac64c47abe 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3276,6 +3276,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("VoiceSignalingRequest"); capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite capabilityNames.append("RegionObjects"); + capabilityNames.append("RegionSchedule"); capabilityNames.append("RemoteParcelRequest"); capabilityNames.append("RenderMaterials"); capabilityNames.append("RequestTextureDownload"); diff --git a/indra/newview/skins/default/xui/en/floater_region_restart_schedule.xml b/indra/newview/skins/default/xui/en/floater_region_restart_schedule.xml new file mode 100644 index 0000000000..fd04acde35 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_region_restart_schedule.xml @@ -0,0 +1,278 @@ + + + + + am + pm + + + Restart the region on following days: + + + + + + + + + + + + + + + + + + Su + + + + Mo + + + + Tu + + + + We + + + + Th + + + + Fr + + + + Sa + + + + at + + + + : + + + + -- cgit v1.2.3