00001
00032
00033
00034
00035
00036 #include "llviewerprecompiledheaders.h"
00037
00038 #include "llpanelclassified.h"
00039
00040 #include "lldir.h"
00041 #include "lldispatcher.h"
00042 #include "llparcel.h"
00043 #include "message.h"
00044
00045 #include "llagent.h"
00046 #include "llalertdialog.h"
00047 #include "llbutton.h"
00048 #include "llcheckboxctrl.h"
00049 #include "llclassifiedflags.h"
00050 #include "llclassifiedstatsresponder.h"
00051 #include "llviewercontrol.h"
00052 #include "lllineeditor.h"
00053 #include "llfloateravatarinfo.h"
00054 #include "llfloaterclassified.h"
00055 #include "lltabcontainervertical.h"
00056 #include "lltextbox.h"
00057 #include "llcombobox.h"
00058 #include "llviewertexteditor.h"
00059 #include "lltexturectrl.h"
00060 #include "lluiconstants.h"
00061 #include "llvieweruictrlfactory.h"
00062 #include "llviewerparcelmgr.h"
00063 #include "llviewerwindow.h"
00064 #include "llworldmap.h"
00065 #include "llfloaterworldmap.h"
00066 #include "llviewergenericmessage.h"
00067 #include "llviewerregion.h"
00068 #include "llviewerwindow.h"
00069 #include "viewer.h"
00070
00071 const S32 MINIMUM_PRICE_FOR_LISTING = 50;
00072
00073
00074
00075
00076
00077
00078 class LLDispatchClassifiedClickThrough : public LLDispatchHandler
00079 {
00080 public:
00081 virtual bool operator()(
00082 const LLDispatcher* dispatcher,
00083 const std::string& key,
00084 const LLUUID& invoice,
00085 const sparam_t& strings)
00086 {
00087 if (strings.size() != 4) return false;
00088 LLUUID classified_id(strings[0]);
00089 S32 teleport_clicks = atoi(strings[1].c_str());
00090 S32 map_clicks = atoi(strings[2].c_str());
00091 S32 profile_clicks = atoi(strings[3].c_str());
00092 LLPanelClassified::setClickThrough(classified_id, teleport_clicks,
00093 map_clicks,
00094 profile_clicks,
00095 false);
00096 return true;
00097 }
00098 };
00099
00100 static LLDispatchClassifiedClickThrough sClassifiedClickThrough;
00101
00102
00103 std::list<LLPanelClassified*> LLPanelClassified::sAllPanels;
00104
00105 LLPanelClassified::LLPanelClassified(BOOL in_finder, bool from_search)
00106 : LLPanel("Classified Panel"),
00107 mInFinder(in_finder),
00108 mFromSearch(from_search),
00109 mDirty(false),
00110 mForceClose(false),
00111 mLocationChanged(false),
00112 mClassifiedID(),
00113 mCreatorID(),
00114 mPriceForListing(0),
00115 mDataRequested(FALSE),
00116 mPaidFor(FALSE),
00117 mPosGlobal(),
00118 mSnapshotCtrl(NULL),
00119 mNameEditor(NULL),
00120 mDescEditor(NULL),
00121 mLocationEditor(NULL),
00122 mCategoryCombo(NULL),
00123 mMatureCheck(NULL),
00124 mAutoRenewCheck(NULL),
00125 mUpdateBtn(NULL),
00126 mTeleportBtn(NULL),
00127 mMapBtn(NULL),
00128 mProfileBtn(NULL),
00129 mInfoText(NULL),
00130 mSetBtn(NULL),
00131 mClickThroughText(NULL),
00132 mTeleportClicksOld(0),
00133 mMapClicksOld(0),
00134 mProfileClicksOld(0),
00135 mTeleportClicksNew(0),
00136 mMapClicksNew(0),
00137 mProfileClicksNew(0)
00138
00139 {
00140 sAllPanels.push_back(this);
00141
00142 std::string classified_def_file;
00143 if (mInFinder)
00144 {
00145 gUICtrlFactory->buildPanel(this, "panel_classified.xml");
00146 }
00147 else
00148 {
00149 gUICtrlFactory->buildPanel(this, "panel_avatar_classified.xml");
00150 }
00151
00152
00153 gGenericDispatcher.addHandler("classifiedclickthrough",
00154 &sClassifiedClickThrough);
00155 }
00156
00157
00158 LLPanelClassified::~LLPanelClassified()
00159 {
00160 sAllPanels.remove(this);
00161 }
00162
00163
00164 void LLPanelClassified::reset()
00165 {
00166 mClassifiedID.setNull();
00167 mCreatorID.setNull();
00168 mParcelID.setNull();
00169
00170
00171 mDataRequested = TRUE;
00172
00173 mDirty = false;
00174 mPaidFor = FALSE;
00175
00176 mPosGlobal.clearVec();
00177
00178 clearCtrls();
00179 }
00180
00181
00182 BOOL LLPanelClassified::postBuild()
00183 {
00184 mSnapshotCtrl = LLViewerUICtrlFactory::getTexturePickerByName(this, "snapshot_ctrl");
00185 mSnapshotCtrl->setCommitCallback(onCommitAny);
00186 mSnapshotCtrl->setCallbackUserData(this);
00187 mSnapshotSize = mSnapshotCtrl->getRect();
00188
00189 mNameEditor = LLViewerUICtrlFactory::getLineEditorByName(this, "given_name_editor");
00190 mNameEditor->setMaxTextLength(DB_PARCEL_NAME_LEN);
00191 mNameEditor->setCommitOnFocusLost(TRUE);
00192 mNameEditor->setFocusReceivedCallback(onFocusReceived);
00193 mNameEditor->setCommitCallback(onCommitAny);
00194 mNameEditor->setCallbackUserData(this);
00195 mNameEditor->setPrevalidate( LLLineEditor::prevalidateASCII );
00196
00197 mDescEditor = LLUICtrlFactory::getTextEditorByName(this, "desc_editor");
00198 mDescEditor->setCommitOnFocusLost(TRUE);
00199 mDescEditor->setFocusReceivedCallback(onFocusReceived);
00200 mDescEditor->setCommitCallback(onCommitAny);
00201 mDescEditor->setCallbackUserData(this);
00202 mDescEditor->setTabToNextField(TRUE);
00203
00204 mLocationEditor = LLViewerUICtrlFactory::getLineEditorByName(this, "location_editor");
00205
00206 mSetBtn = LLViewerUICtrlFactory::getButtonByName(this, "set_location_btn");
00207 mSetBtn->setClickedCallback(onClickSet);
00208 mSetBtn->setCallbackUserData(this);
00209
00210 mTeleportBtn = LLViewerUICtrlFactory::getButtonByName(this, "classified_teleport_btn");
00211 mTeleportBtn->setClickedCallback(onClickTeleport);
00212 mTeleportBtn->setCallbackUserData(this);
00213
00214 mMapBtn = LLViewerUICtrlFactory::getButtonByName(this, "classified_map_btn");
00215 mMapBtn->setClickedCallback(onClickMap);
00216 mMapBtn->setCallbackUserData(this);
00217
00218 if(mInFinder)
00219 {
00220 mProfileBtn = LLViewerUICtrlFactory::getButtonByName(this, "classified_profile_btn");
00221 mProfileBtn->setClickedCallback(onClickProfile);
00222 mProfileBtn->setCallbackUserData(this);
00223 }
00224
00225 mCategoryCombo = LLViewerUICtrlFactory::getComboBoxByName(this, "classified_category_combo");
00226 LLClassifiedInfo::cat_map::iterator iter;
00227 for (iter = LLClassifiedInfo::sCategories.begin();
00228 iter != LLClassifiedInfo::sCategories.end();
00229 iter++)
00230 {
00231 mCategoryCombo->add(iter->second, (void *)((intptr_t)iter->first), ADD_BOTTOM);
00232 }
00233 mCategoryCombo->setCurrentByIndex(0);
00234 mCategoryCombo->setCommitCallback(onCommitAny);
00235 mCategoryCombo->setCallbackUserData(this);
00236
00237 mMatureCheck = LLViewerUICtrlFactory::getCheckBoxByName(this, "classified_mature_check");
00238 mMatureCheck->setCommitCallback(onCommitAny);
00239 mMatureCheck->setCallbackUserData(this);
00240 if (gAgent.isTeen())
00241 {
00242
00243 mMatureCheck->setVisible(FALSE);
00244 }
00245
00246 if (!mInFinder)
00247 {
00248 mAutoRenewCheck = LLUICtrlFactory::getCheckBoxByName(this, "auto_renew_check");
00249 mAutoRenewCheck->setCommitCallback(onCommitAny);
00250 mAutoRenewCheck->setCallbackUserData(this);
00251 }
00252
00253 mUpdateBtn = LLUICtrlFactory::getButtonByName(this, "classified_update_btn");
00254 mUpdateBtn->setClickedCallback(onClickUpdate);
00255 mUpdateBtn->setCallbackUserData(this);
00256
00257 if (!mInFinder)
00258 {
00259 mClickThroughText = LLUICtrlFactory::getTextBoxByName(this, "click_through_text");
00260 }
00261
00262 return TRUE;
00263 }
00264
00265 BOOL LLPanelClassified::titleIsValid()
00266 {
00267
00268
00269 const LLString& name = mNameEditor->getText();
00270 if (name.empty())
00271 {
00272 gViewerWindow->alertXml("BlankClassifiedName");
00273 return FALSE;
00274 }
00275 if (!isalnum(name[0]))
00276 {
00277 gViewerWindow->alertXml("ClassifiedMustBeAlphanumeric");
00278 return FALSE;
00279 }
00280
00281 return TRUE;
00282 }
00283
00284 void LLPanelClassified::apply()
00285 {
00286
00287
00288 if (checkDirty() && mPaidFor)
00289 {
00290 sendClassifiedInfoUpdate();
00291 }
00292 }
00293
00294
00295
00296 void LLPanelClassified::saveCallback(S32 option, void* data)
00297 {
00298 LLPanelClassified* self = (LLPanelClassified*)data;
00299 switch(option)
00300 {
00301 case 0:
00302 self->sendClassifiedInfoUpdate();
00303
00304
00305 case 1:
00306 {
00307 self->mForceClose = true;
00308
00309 LLView* view = self;
00310 while (view)
00311 {
00312 if (view->getWidgetType() == WIDGET_TYPE_FLOATER)
00313 {
00314 LLFloater* f = (LLFloater*)view;
00315 f->close();
00316 break;
00317 }
00318 view = view->getParent();
00319 }
00320 }
00321 break;
00322
00323 case 2:
00324 default:
00325 app_abort_quit();
00326 break;
00327 }
00328 }
00329
00330 BOOL LLPanelClassified::canClose()
00331 {
00332 if (mForceClose || !checkDirty())
00333 return TRUE;
00334
00335 LLString::format_map_t args;
00336 args["[NAME]"] = mNameEditor->getText();
00337 LLAlertDialog::showXml("ClassifiedSave", args, saveCallback, this);
00338 return FALSE;
00339 }
00340
00341
00342 void LLPanelClassified::initNewClassified()
00343 {
00344
00345 mClassifiedID.generate();
00346
00347 mCreatorID = gAgent.getID();
00348
00349 mPosGlobal = gAgent.getPositionGlobal();
00350
00351 mPaidFor = FALSE;
00352
00353
00354 LLParcel* parcel = gParcelMgr->getAgentParcel();
00355 if (parcel)
00356 {
00357 mNameEditor->setText(parcel->getName());
00358
00359 mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID());
00360
00361 mCategoryCombo->setCurrentByIndex(0);
00362 }
00363
00364
00365
00366
00367
00368
00369
00370 mUpdateBtn->setLabel(childGetText("publish_txt"));
00371 }
00372
00373
00374 void LLPanelClassified::setClassifiedID(const LLUUID& id)
00375 {
00376 mClassifiedID = id;
00377 }
00378
00379
00380 void LLPanelClassified::setClickThrough(const LLUUID& classified_id,
00381 S32 teleport,
00382 S32 map,
00383 S32 profile,
00384 bool from_new_table)
00385 {
00386 for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
00387 {
00388 LLPanelClassified* self = *iter;
00389
00390 if (self->mClassifiedID != classified_id)
00391 {
00392 continue;
00393 }
00394
00395
00396
00397
00398
00399 if (from_new_table)
00400 {
00401 self->mTeleportClicksNew = teleport;
00402 self->mMapClicksNew = map;
00403 self->mProfileClicksNew = profile;
00404 }
00405 else
00406 {
00407 self->mTeleportClicksOld = teleport;
00408 self->mMapClicksOld = map;
00409 self->mProfileClicksOld = profile;
00410 }
00411
00412 if (self->mClickThroughText)
00413 {
00414 std::string msg = llformat("Clicks: %d teleport, %d map, %d profile",
00415 self->mTeleportClicksNew + self->mTeleportClicksOld,
00416 self->mMapClicksNew + self->mMapClicksOld,
00417 self->mProfileClicksNew + self->mProfileClicksOld);
00418 self->mClickThroughText->setText(msg);
00419 }
00420 }
00421 }
00422
00423
00424
00425 void LLPanelClassified::markForServerRequest()
00426 {
00427 mDataRequested = FALSE;
00428 }
00429
00430
00431 std::string LLPanelClassified::getClassifiedName()
00432 {
00433 return mNameEditor->getText();
00434 }
00435
00436
00437 void LLPanelClassified::sendClassifiedInfoRequest()
00438 {
00439 LLMessageSystem *msg = gMessageSystem;
00440
00441 if (mClassifiedID != mRequestedID)
00442 {
00443 msg->newMessageFast(_PREHASH_ClassifiedInfoRequest);
00444 msg->nextBlockFast(_PREHASH_AgentData);
00445 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
00446 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00447 msg->nextBlockFast(_PREHASH_Data);
00448 msg->addUUIDFast(_PREHASH_ClassifiedID, mClassifiedID);
00449 gAgent.sendReliableMessage();
00450
00451 mDataRequested = TRUE;
00452 mRequestedID = mClassifiedID;
00453
00454
00455
00456 std::string url = gAgent.getRegion()->getCapability("SearchStatRequest");
00457 LLSD body;
00458 body["classified_id"] = mClassifiedID;
00459
00460 if (!url.empty())
00461 {
00462 llinfos << "Classified stat request via capability" << llendl;
00463 LLHTTPClient::post(url, body, new LLClassifiedStatsResponder(this->getHandle(), mClassifiedID));
00464 }
00465 }
00466 }
00467
00468
00469 void LLPanelClassified::sendClassifiedInfoUpdate()
00470 {
00471
00472
00473 if (mClassifiedID.isNull())
00474 {
00475
00476 mClassifiedID.generate();
00477 }
00478
00479 LLMessageSystem* msg = gMessageSystem;
00480
00481 msg->newMessageFast(_PREHASH_ClassifiedInfoUpdate);
00482 msg->nextBlockFast(_PREHASH_AgentData);
00483 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00484 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00485 msg->nextBlockFast(_PREHASH_Data);
00486 msg->addUUIDFast(_PREHASH_ClassifiedID, mClassifiedID);
00487
00488 U32 category = mCategoryCombo->getCurrentIndex() + 1;
00489 msg->addU32Fast(_PREHASH_Category, category);
00490 msg->addStringFast(_PREHASH_Name, mNameEditor->getText());
00491 msg->addStringFast(_PREHASH_Desc, mDescEditor->getText());
00492
00493
00494 msg->addUUIDFast(_PREHASH_ParcelID, mParcelID);
00495
00496 msg->addU32Fast(_PREHASH_ParentEstate, 0);
00497 msg->addUUIDFast(_PREHASH_SnapshotID, mSnapshotCtrl->getImageAssetID());
00498 msg->addVector3dFast(_PREHASH_PosGlobal, mPosGlobal);
00499 BOOL mature = mMatureCheck->get();
00500
00501
00502 BOOL auto_renew = FALSE;
00503 if (mAutoRenewCheck)
00504 {
00505 auto_renew = mAutoRenewCheck->get();
00506 }
00507 U8 flags = pack_classified_flags(mature, auto_renew);
00508 msg->addU8Fast(_PREHASH_ClassifiedFlags, flags);
00509 msg->addS32("PriceForListing", mPriceForListing);
00510 gAgent.sendReliableMessage();
00511
00512 mDirty = false;
00513 }
00514
00515
00516
00517 void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void **)
00518 {
00519 lldebugs << "processClassifiedInfoReply()" << llendl;
00520
00521
00522 LLUUID agent_id;
00523 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
00524 if (agent_id != gAgent.getID())
00525 {
00526 llwarns << "Agent ID mismatch in processClassifiedInfoReply"
00527 << llendl;
00528 return;
00529 }
00530
00531 LLUUID classified_id;
00532 msg->getUUIDFast(_PREHASH_Data, _PREHASH_ClassifiedID, classified_id);
00533
00534 LLUUID creator_id;
00535 msg->getUUIDFast(_PREHASH_Data, _PREHASH_CreatorID, creator_id);
00536
00537 LLUUID parcel_id;
00538 msg->getUUIDFast(_PREHASH_Data, _PREHASH_ParcelID, parcel_id);
00539
00540 char name[DB_PARCEL_NAME_SIZE];
00541 msg->getStringFast(_PREHASH_Data, _PREHASH_Name, DB_PARCEL_NAME_SIZE, name);
00542
00543 char desc[DB_PICK_DESC_SIZE];
00544 msg->getStringFast(_PREHASH_Data, _PREHASH_Desc, DB_PICK_DESC_SIZE, desc);
00545
00546 LLUUID snapshot_id;
00547 msg->getUUIDFast(_PREHASH_Data, _PREHASH_SnapshotID, snapshot_id);
00548
00549
00550
00551 char buffer[256];
00552 LLString location_text;
00553
00554 msg->getStringFast(_PREHASH_Data, _PREHASH_ParcelName, 256, buffer);
00555 if (buffer[0] != '\0')
00556 {
00557 location_text.assign(buffer);
00558 location_text.append(", ");
00559 }
00560 else
00561 {
00562 location_text.assign("");
00563 }
00564
00565 char sim_name[256];
00566 msg->getStringFast(_PREHASH_Data, _PREHASH_SimName, 256, sim_name);
00567
00568 LLVector3d pos_global;
00569 msg->getVector3dFast(_PREHASH_Data, _PREHASH_PosGlobal, pos_global);
00570
00571 S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
00572 S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
00573 S32 region_z = llround((F32)pos_global.mdV[VZ]);
00574
00575 snprintf(buffer, sizeof(buffer), "%s (%d, %d, %d)", sim_name, region_x, region_y, region_z);
00576 location_text.append(buffer);
00577
00578 U8 flags;
00579 msg->getU8Fast(_PREHASH_Data, _PREHASH_ClassifiedFlags, flags);
00580
00581 bool mature = is_cf_mature(flags);
00582 bool auto_renew = is_cf_auto_renew(flags);
00583
00584 U32 date = 0;
00585 msg->getU32Fast(_PREHASH_Data, _PREHASH_CreationDate, date);
00586 time_t tim = date;
00587 tm *now=localtime(&tim);
00588
00589
00590 U32 expiration_date = 0;
00591 msg->getU32("Data", "ExpirationDate", expiration_date);
00592
00593 U32 category = 0;
00594 msg->getU32Fast(_PREHASH_Data, _PREHASH_Category, category);
00595
00596 S32 price_for_listing = 0;
00597 msg->getS32("Data", "PriceForListing", price_for_listing);
00598
00599
00600 for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
00601 {
00602 LLPanelClassified* self = *iter;
00603
00604 if (self->mClassifiedID != classified_id)
00605 {
00606 continue;
00607 }
00608
00609
00610 self->mClassifiedID = classified_id;
00611 self->mCreatorID = creator_id;
00612 self->mParcelID = parcel_id;
00613 self->mPriceForListing = price_for_listing;
00614 self->mSimName.assign(sim_name);
00615 self->mPosGlobal = pos_global;
00616
00617
00618 self->mNameEditor->setText(LLString(name));
00619 self->mDescEditor->setText(LLString(desc));
00620 self->mSnapshotCtrl->setImageAssetID(snapshot_id);
00621 self->mLocationEditor->setText(location_text);
00622 self->mLocationChanged = false;
00623
00624 self->mCategoryCombo->setCurrentByIndex(category - 1);
00625 self->mMatureCheck->set(mature);
00626 if (self->mAutoRenewCheck)
00627 {
00628 self->mAutoRenewCheck->set(auto_renew);
00629 }
00630
00631 LLString datestr = llformat("%02d/%02d/%d", now->tm_mon+1, now->tm_mday, now->tm_year+1900);
00632 self->childSetTextArg("ad_placed_paid", "[DATE]", datestr);
00633 self->childSetTextArg("ad_placed_paid", "[AMT]", llformat("%d", price_for_listing));
00634 self->childSetText("classified_info_text", self->childGetValue("ad_placed_paid").asString());
00635
00636
00637 self->mPaidFor = TRUE;
00638
00639 self->mUpdateBtn->setLabel(self->childGetText("update_txt"));
00640 }
00641 }
00642
00643 void LLPanelClassified::draw()
00644 {
00645 if (getVisible())
00646 {
00647 refresh();
00648
00649 LLPanel::draw();
00650 }
00651 }
00652
00653
00654 void LLPanelClassified::refresh()
00655 {
00656 if (!mDataRequested)
00657 {
00658 sendClassifiedInfoRequest();
00659 }
00660
00661
00662 BOOL godlike = gAgent.isGodlike();
00663 BOOL is_self = (gAgent.getID() == mCreatorID);
00664
00665
00666 if (mInFinder)
00667 {
00668
00669
00670
00671 mSnapshotCtrl->setEnabled(godlike);
00672 if(godlike)
00673 {
00674
00675 mSnapshotCtrl->setRect(LLRect(20, 375, 320, 175));
00676
00677 }
00678 else
00679 {
00680 mSnapshotCtrl->setRect(mSnapshotSize);
00681
00682 }
00683 mNameEditor->setEnabled(godlike);
00684 mDescEditor->setEnabled(godlike);
00685 mCategoryCombo->setEnabled(godlike);
00686 mCategoryCombo->setVisible(godlike);
00687
00688
00689
00690
00691 mMatureCheck->setEnabled(godlike);
00692 mMatureCheck->setVisible(godlike);
00693
00694
00695
00696
00697 mSetBtn->setVisible(FALSE);
00698 mSetBtn->setEnabled(FALSE);
00699
00700 mUpdateBtn->setEnabled(godlike);
00701 mUpdateBtn->setVisible(godlike);
00702 }
00703 else
00704 {
00705 mSnapshotCtrl->setEnabled(is_self);
00706 mNameEditor->setEnabled(is_self);
00707 mDescEditor->setEnabled(is_self);
00708
00709 mCategoryCombo->setEnabled(is_self);
00710
00711
00712
00713 mMatureCheck->setEnabled(is_self);
00714
00715 if (mAutoRenewCheck)
00716 {
00717 mAutoRenewCheck->setEnabled(is_self);
00718 mAutoRenewCheck->setVisible(is_self);
00719 }
00720
00721 mClickThroughText->setEnabled(is_self);
00722 mClickThroughText->setVisible(is_self);
00723
00724 mSetBtn->setVisible(is_self);
00725 mSetBtn->setEnabled(is_self);
00726
00727 mUpdateBtn->setEnabled(is_self && checkDirty());
00728 mUpdateBtn->setVisible(is_self);
00729 }
00730 }
00731
00732
00733 void LLPanelClassified::onClickUpdate(void* data)
00734 {
00735 LLPanelClassified* self = (LLPanelClassified*)data;
00736
00737 if(self == NULL) return;
00738
00739
00740
00741 if ( ! self->titleIsValid() )
00742 {
00743 return;
00744 };
00745
00746
00747 if (self->mPaidFor)
00748 {
00749 callbackConfirmPublish(0, self);
00750 }
00751 else
00752 {
00753
00754 LLFloaterPriceForListing::show( callbackGotPriceForListing, self );
00755 }
00756 }
00757
00758
00759 void LLPanelClassified::callbackGotPriceForListing(S32 option, LLString text, void* data)
00760 {
00761 LLPanelClassified* self = (LLPanelClassified*)data;
00762
00763
00764 if (option != 0) return;
00765
00766 S32 price_for_listing = strtol(text.c_str(), NULL, 10);
00767 if (price_for_listing < MINIMUM_PRICE_FOR_LISTING)
00768 {
00769 LLString::format_map_t args;
00770 LLString price_text = llformat("%d", MINIMUM_PRICE_FOR_LISTING);
00771 args["[MIN_PRICE]"] = price_text;
00772
00773 gViewerWindow->alertXml("MinClassifiedPrice", args);
00774 return;
00775 }
00776
00777
00778
00779 self->mPriceForListing = price_for_listing;
00780
00781 LLString::format_map_t args;
00782 args["[AMOUNT]"] = llformat("%d", price_for_listing);
00783 gViewerWindow->alertXml("PublishClassified", args, &callbackConfirmPublish, self);
00784
00785 }
00786
00787
00788
00789 void LLPanelClassified::confirmPublish(S32 option)
00790 {
00791
00792 if (option != 0) return;
00793
00794 sendClassifiedInfoUpdate();
00795
00796
00797
00798 if (mInFinder)
00799 {
00800
00801
00802
00803 }
00804 else
00805 {
00806 LLTabContainerVertical* tab = (LLTabContainerVertical*)getParent();
00807 tab->setCurrentTabName(mNameEditor->getText());
00808 }
00809
00810
00811 mSnapshotCtrl->resetDirty();
00812 mNameEditor->resetDirty();
00813 mDescEditor->resetDirty();
00814 mLocationEditor->resetDirty();
00815 mLocationChanged = false;
00816 mCategoryCombo->resetDirty();
00817 mMatureCheck->resetDirty();
00818 if (mAutoRenewCheck)
00819 {
00820 mAutoRenewCheck->resetDirty();
00821 }
00822 }
00823
00824
00825 void LLPanelClassified::callbackConfirmPublish(S32 option, void* data)
00826 {
00827 LLPanelClassified* self = (LLPanelClassified*)data;
00828 self->confirmPublish(option);
00829 }
00830
00831
00832 void LLPanelClassified::onClickTeleport(void* data)
00833 {
00834 LLPanelClassified* self = (LLPanelClassified*)data;
00835
00836 if (!self->mPosGlobal.isExactlyZero())
00837 {
00838 gAgent.teleportViaLocation(self->mPosGlobal);
00839 gFloaterWorldMap->trackLocation(self->mPosGlobal);
00840
00841 self->sendClassifiedClickMessage("teleport");
00842 }
00843 }
00844
00845
00846
00847 void LLPanelClassified::onClickMap(void* data)
00848 {
00849 LLPanelClassified* self = (LLPanelClassified*)data;
00850 gFloaterWorldMap->trackLocation(self->mPosGlobal);
00851 LLFloaterWorldMap::show(NULL, TRUE);
00852
00853 self->sendClassifiedClickMessage("map");
00854 }
00855
00856
00857 void LLPanelClassified::onClickProfile(void* data)
00858 {
00859 LLPanelClassified* self = (LLPanelClassified*)data;
00860 LLFloaterAvatarInfo::showFromDirectory(self->mCreatorID);
00861 self->sendClassifiedClickMessage("profile");
00862 }
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 void LLPanelClassified::onClickSet(void* data)
00875 {
00876 LLPanelClassified* self = (LLPanelClassified*)data;
00877
00878
00879 self->mPosGlobal = gAgent.getPositionGlobal();
00880
00881 LLString location_text;
00882 location_text.assign("(will update after publish)");
00883 location_text.append(", ");
00884
00885 S32 region_x = llround((F32)self->mPosGlobal.mdV[VX]) % REGION_WIDTH_UNITS;
00886 S32 region_y = llround((F32)self->mPosGlobal.mdV[VY]) % REGION_WIDTH_UNITS;
00887 S32 region_z = llround((F32)self->mPosGlobal.mdV[VZ]);
00888
00889 location_text.append(self->mSimName);
00890 location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
00891
00892 self->mLocationEditor->setText(location_text);
00893 self->mLocationChanged = true;
00894
00895
00896 self->mParcelID.setNull();
00897
00898 onCommitAny(NULL, data);
00899 }
00900
00901
00902 BOOL LLPanelClassified::checkDirty()
00903 {
00904 mDirty = FALSE;
00905 if ( mSnapshotCtrl ) mDirty |= mSnapshotCtrl->isDirty();
00906 if ( mNameEditor ) mDirty |= mNameEditor->isDirty();
00907 if ( mDescEditor ) mDirty |= mDescEditor->isDirty();
00908 if ( mLocationEditor ) mDirty |= mLocationEditor->isDirty();
00909 if ( mLocationChanged ) mDirty |= TRUE;
00910 if ( mCategoryCombo ) mDirty |= mCategoryCombo->isDirty();
00911 if ( mMatureCheck ) mDirty |= mMatureCheck->isDirty();
00912 if ( mAutoRenewCheck ) mDirty |= mAutoRenewCheck->isDirty();
00913
00914 return mDirty;
00915 }
00916
00917
00918 void LLPanelClassified::onCommitAny(LLUICtrl* ctrl, void* data)
00919 {
00920 LLPanelClassified* self = (LLPanelClassified*)data;
00921 if (self)
00922 {
00923 self->checkDirty();
00924 }
00925 }
00926
00927
00928 void LLPanelClassified::onFocusReceived(LLUICtrl* ctrl, void* data)
00929 {
00930
00931 onCommitAny(ctrl, data);
00932 }
00933
00934
00935 void LLPanelClassified::sendClassifiedClickMessage(const char* type)
00936 {
00937
00938
00939 std::vector<std::string> strings;
00940 strings.push_back(mClassifiedID.asString());
00941 strings.push_back(type);
00942 LLUUID no_invoice;
00943
00944
00945 LLSD body;
00946 body["type"] = type;
00947 body["from_search"] = mFromSearch;
00948 body["classified_id"] = mClassifiedID;
00949 std::string url = gAgent.getRegion()->getCapability("SearchStatTracking");
00950
00951
00952 if (!url.empty())
00953 {
00954 llinfos << "LLPanelClassified::sendClassifiedClickMessage via capability" << llendl;
00955 LLHTTPClient::post(url, body, new LLHTTPClient::Responder());
00956 }
00957 else
00958 {
00959 send_generic_message("classifiedclick", strings, no_invoice);
00960 }
00961 }
00962
00964
00965 LLFloaterPriceForListing::LLFloaterPriceForListing()
00966 : LLFloater("PriceForListing"),
00967 mCallback(NULL),
00968 mUserData(NULL)
00969 { }
00970
00971
00972 LLFloaterPriceForListing::~LLFloaterPriceForListing()
00973 { }
00974
00975
00976 BOOL LLFloaterPriceForListing::postBuild()
00977 {
00978 LLLineEditor* edit = LLUICtrlFactory::getLineEditorByName(this, "price_edit");
00979 if (edit)
00980 {
00981 edit->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
00982 LLString min_price = llformat("%d", MINIMUM_PRICE_FOR_LISTING);
00983 edit->setText(min_price);
00984 edit->selectAll();
00985 edit->setFocus(TRUE);
00986 }
00987
00988 childSetAction("set_price_btn", onClickSetPrice, this);
00989
00990 childSetAction("cancel_btn", onClickCancel, this);
00991
00992 setDefaultBtn("set_price_btn");
00993 return TRUE;
00994 }
00995
00996
00997 void LLFloaterPriceForListing::show( void (*callback)(S32, LLString, void*), void* userdata)
00998 {
00999 LLFloaterPriceForListing *self = new LLFloaterPriceForListing();
01000
01001
01002 gUICtrlFactory->buildFloater(self, "floater_price_for_listing.xml");
01003 self->center();
01004
01005 self->mCallback = callback;
01006 self->mUserData = userdata;
01007 }
01008
01009
01010 void LLFloaterPriceForListing::onClickSetPrice(void* data)
01011 {
01012 buttonCore(0, data);
01013 }
01014
01015
01016 void LLFloaterPriceForListing::onClickCancel(void* data)
01017 {
01018 buttonCore(1, data);
01019 }
01020
01021
01022 void LLFloaterPriceForListing::buttonCore(S32 button, void* data)
01023 {
01024 LLFloaterPriceForListing* self = (LLFloaterPriceForListing*)data;
01025
01026 if (self->mCallback)
01027 {
01028 LLString text = self->childGetText("price_edit");
01029 self->mCallback(button, text, self->mUserData);
01030 self->close();
01031 }
01032 }