// // $Id: ExchangeCfgDlg.cpp,v 1.11 2008/12/24 02:06:34 philw Exp $ // // Gnats 4630 Workaround (Crash in Exchange Cfg Dlg after deleting an Account) static const bool MAKE_DLG_MODAL (true); // see note in code. //************************************************************************* // HEADER FILES //************************************************************************* //------------------------------- // Qt Includes #ifndef GusSelectorINCLUDED #include "GusSelector.hpp" #endif #ifndef RwQtUtilsINCLUDED #include "RwQtUtils.hpp" #endif #ifndef ExchangeMgrDlgINCLUDED #include "ExchangeMgrDlg.hpp" #endif #ifndef ExchangeCfgDlgINCLUDED #include "ExchangeCfgDlg.hpp" #endif #ifndef QGuiINCLUDED #include "QGui.hpp" #endif #ifndef QtAcctMgrDlgINCLUDED #include "QtAcctMgrDlg.hpp" #endif #ifndef QtAcctGuiMgrINCLUDED #include "QtAcctGuiMgr.hpp" #endif #ifndef libQtAccountingMsgsINCLUDED #include "libQtAccountingMsgs.hpp" #endif #ifndef QtSplyMgrDlgINCLUDED #include "QtSplyMgrDlg.hpp" #endif #ifndef AccountingSystemConfigINCLUDED #include "AccountingSystemConfig.hpp" #endif #ifndef DlgGeometryMgrINCLUDED #include "DlgGeometryMgr.hpp" #endif #include #include #include #include #include #include #include #include #include #include #include #include #undef slots ///////////////////////// end of qt includes ///////////////////////// //------------------------------- // ACCOUNTING LIBRARY #ifndef AccountMgrINCLUDED #include "AccountMgr.hpp" #endif #ifndef PaybackINCLUDED #include "Payback.hpp" #endif #ifndef ExchangeINCLUDED #include "Exchange.hpp" #endif #ifndef SupplyINCLUDED #include "Supply.hpp" #endif //------------------------------- // SIM LIBRARY #ifndef SystemINCLUDED #include "System.hpp" #endif #ifndef SimWorkspaceINCLUDED #include "SimWS.hpp" #endif #ifndef RootSelectionINCLUDED #include "RootSelection.hpp" #endif //------------------------------- // UNITS LIBRARY #ifndef UnitMgrINCLUDED # include "UnitMgr.hpp" #endif //------------------------------- // ACCOUNTING GUI LIBRARIES //------------------------------- // UTILS LIBRARY #ifndef cwFormatINCLUDED #include "cwFormat.hpp" #endif #ifndef cwExceptINCLUDED #include "cwExcept.hpp" #endif #ifndef EditListINCLUDED #include "EditList.hpp" #endif //************************************************************************* // OTHER CONSTANTS, ENUMS, GLOBALS //************************************************************************* //---------------- // DISPLAY FORMATS // This usage is consistent with the format information presentation // in the SlotCfgDlg, and AcctCfgDlg. // Total number of formats available to user // in which to display numeric data static const int NUMDISPLAYFORMATS = 3; // The names of the formats as they should appear in the user interface. // The list of format names has been made static because they are the // same for every instance of this dialog, and so the strings we're // putting within it can be used by the Units option menu. static const RWCString FloatFormatName = "Float"; static const RWCString IntegerFormatName = "Integer"; static const RWCString ScientificFormatName = "Scientific"; static RWCString displayFormatString[] = { FloatFormatName, IntegerFormatName, ScientificFormatName }; // The format control character that should // be used to display numeric values in those formats. // The list of format control characters has been made static // because they are the same for every instance of this dialog. static const RWCString FloatConversionChar = "%f"; static const RWCString IntegerConversionChar = "%d"; static const RWCString ScientificConversionChar = "%e"; static RWCString displayFormatConversionChar[] = { FloatConversionChar, IntegerConversionChar, ScientificConversionChar }; // Borrow Supply Buttons enum { radioSelectSupply = 0, radioInputBorrow }; // Payback Destination Buttons enum { radioSelectDest = 0, radioNoDest }; // Columns in ListView enum { listNameCol = 0, listLossCol }; // Grand Unified Selector (GUS) -- Static data members RootSelection* ExchangeCfgDlg::_rootSelection (NULL); GusSelector* ExchangeCfgDlg::_gusSelector (NULL); ExchangeCfgDlg* ExchangeCfgDlg::_gusExchCfgDlgUser (NULL); char ExchangeCfgDlg::_gusUse; // 'B' Borrow Sply, // 'D' Pback Dest, // 'A' Add Pback Source // 'M' Modify Pback Source //------------------------------------ // FUNCTION PROTOTYPES //======================================================= //+public // // METHOD: // ExchangeCfgDlg::ExchangeCfgDlg (Exchange * exchange, // AcctGuiDefs::DisplayMode mode) // // PURPOSE: // Constructor to create an Exchange Configuration Dialog // for either a new or already-existing exchange. // // The particular information shown in the dialog is determined // by whether the exchange is just now being created, or // is instead an existing exchange that needs to be edited. // //- ExchangeCfgDlg::ExchangeCfgDlg (Exchange* exchange, AcctGuiDefs::DisplayMode mode) : ExchangeCfgDlgBase(), GusListener(), _origExchange(exchange), _exchangeCopy(NULL), _borrowNameCache (""), _destNameCache (""), _isCancelCompleted(false), _deleteNewExchange(false), _displayMode(mode), _workspaceClearedCB(NULL), _accountingStateChangedCB(NULL), _exchangeOrigCB(NULL), _exchangeCopyCB(NULL), _isDialogClosing(false) { // Obtain the editable copy of the exchange if (getEditableExchange(mode) != true) { // We can't proceed with editing the exchange // Close dialog - cancel not needed _isCancelCompleted = true; close(true); } //--------------------------------------------------------------------- // DO DIALOG INITIALIZATION // Fixup to Qt4 uic3 code generation. For some reason, the generated code // sets the central widget's contents margins to 0. (11 is reasonable). // QWidget* cenWid = centralWidget(); QLayout* cenLayout (cenWid ? cenWid->layout() : NULL); if (cenLayout) { cenLayout->setContentsMargins (11,11,11,11); // (left, top, right, bot) } if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::ExchangeCfgDlg()"); } else { // Initialize bottom buttons to same width RwQtUtils::qButtonSetCommonWidth(0, 0, _okButton, _applyButton, _resetButton, _cancelButton); // Initialize the list properties _paySourceListView->setAllColumnsShowFocus(true); _paySourceListView->setShowSortIndicator(false); _paySourceListView->setSelectionMode(Q3ListView::Single); // Initialize the context menu. _contextMenu = new Q3PopupMenu(this); _addPaybackSourceAction->addTo(_contextMenu); _modifyPaybackSourceAction->addTo(_contextMenu); _removePaybackSourceAction->addTo(_contextMenu); _contextMenu ->insertSeparator(); //----------------- _editPaybackLossAction->addTo(_contextMenu); // Add validators for scale lineEdit to be doubles only QDoubleValidator* doubleValidator(new QDoubleValidator(this)); _scaleLineEdit->setValidator(doubleValidator); // Initialize dialog contents updateDialogContent(); // Connect signals and slots connectSignals(); // Add callbacks addCallbacks(); } if (!rwSystem->modelEditIsAllowed() || rwWorkspace->isBaselineModel()) { disableModelEdit(); } // Set Window Icon. QGui::setWindowLogoIcon (this); if (MAKE_DLG_MODAL) { // Gnats 4630 [Phil, 5-22-2009]: I've spent basically three days // trying to bail out of an active EditObj edit state when an Account // deletion causes a Supply deletion of a Supply involved in either // the original Exchange or the edit copy. For now, we'll just make // the Exchange Configuration Dialog Modal. setWindowModality (Qt::ApplicationModal); } } ExchangeCfgDlg::~ExchangeCfgDlg() { // Delete calbacks deleteCallbacks(); // Clear GUS and Root Selection if (_gusExchCfgDlgUser == this) { closeGusSupplySelector(); if (_rootSelection != NULL) { delete _rootSelection; _rootSelection = NULL; } } } bool ExchangeCfgDlg::getEditableExchange (AcctGuiDefs::DisplayMode mode) { //--------------------------------------------------------------------- // GET THE EDITABLE COPY OF THIS EXCHANGE // We're making a copy of that exchange, so the // user can edit the copy without the changes // taking immediate effect on the actual exchange. if (mode == AcctGuiDefs::NEW_EXCHANGE) { try { // Create an editable copy of the new exchange, // and put it into the list of editable exchanges. _exchangeCopy = AccountMgrObj->addExchange(_origExchange); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); return false; } } else if (mode == AcctGuiDefs::EXISTING_EXCHANGE) { try { // Get the editable copy of the existing exchange. _exchangeCopy = AccountMgrObj->editExchange(_origExchange); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); return false; } } else { // Unknown mode rwAssert(false); return false; } return true; } void ExchangeCfgDlg::connectSignals() { // Connect Action Signals connect( _fileAction_CloseWindow, SIGNAL( activated() ), this, SLOT( closeHandler() ) ); connect( _fileAction_ShowWorkspace, SIGNAL( activated() ), this, SLOT( showWorkspaceHandler() ) ); connect( _systemAction_ConfigSystem, SIGNAL( activated() ), this, SLOT( configureSystemHandler() ) ); connect( _systemAction_AcctManager, SIGNAL( activated() ), this, SLOT( manageAccountsHandler() ) ); connect( _systemAction_SuppliesMgr, SIGNAL( activated() ), this, SLOT( manageSuppliesHandler() ) ); connect( _addPaybackSourceAction, SIGNAL( activated() ), this, SLOT( addButtonHandler() ) ); connect( _modifyPaybackSourceAction, SIGNAL( activated() ), this, SLOT( modifyButtonHandler() ) ); connect( _removePaybackSourceAction, SIGNAL( activated() ), this, SLOT( removeButtonHandler() ) ); connect( _editPaybackLossAction, SIGNAL( activated() ), this, SLOT( editPaybackLossHandler() ) ); // Connect Exchange Name Signals connect (_nameLineEdit, SIGNAL( returnPressed() ), SLOT(nameLineEditHandler() ) ); connect (_nameLineEdit, SIGNAL( lostFocus() ), SLOT(nameLineEditHandler() ) ); // Connect Borrow Signals connect( _borrowButtonGroup, SIGNAL( clicked(int) ), this, SLOT( borrowButtonHandler(int) ) ); connect( _selBorrowButton, SIGNAL( clicked() ), this, SLOT( selBorrowButtonHandler() ) ); // Connect Payback Destination Signals connect( _payDestButtonGroup, SIGNAL( clicked(int) ), this, SLOT( payDestButtonHandler(int) ) ); connect( _selDestButton, SIGNAL( clicked() ), this, SLOT( selDestButtonHandler() ) ); // Connect Payback Source Signals connect( _addButton, SIGNAL( clicked() ), this, SLOT( addButtonHandler() ) ); connect( _modifyButton, SIGNAL( clicked() ), this, SLOT( modifyButtonHandler() ) ); connect( _removeButton, SIGNAL( clicked() ), this, SLOT( removeButtonHandler() ) ); connect( _paySourceListView, SIGNAL( contextMenuRequested(Q3ListViewItem*,const QPoint&,int) ), this, SLOT( displayContextHandler(Q3ListViewItem*,const QPoint&,int) ) ); connect( _paySourceListView, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedHandler() ) ); connect( _paySourceListView, SIGNAL( doubleClicked(Q3ListViewItem*,const QPoint&,int) ), this, SLOT( paySourceDoubleClickHandler(Q3ListViewItem*,const QPoint&,int) ) ); // Connect Unit Signals connect( _userUnitsCombo, SIGNAL( activated(const QString&) ), this, SLOT( userUnitsComboHandler(const QString&) ) ); connect( _formatCombo, SIGNAL( activated(const QString&) ), this, SLOT( formatComboHandler(const QString&) ) ); connect(_scaleLineEdit, SIGNAL( returnPressed() ), SLOT(scaleLineEditHandler() ) ); connect(_scaleLineEdit, SIGNAL( lostFocus() ), SLOT(scaleLineEditHandler() ) ); connect( _precisionSpin, SIGNAL( valueChanged(int) ), this, SLOT( precisionSpinHandler(int) ) ); // Connect lower Button Signals connect( _okButton, SIGNAL( clicked() ), this, SLOT( okButtonHandler() ) ); connect( _applyButton, SIGNAL( clicked() ), this, SLOT( applyButtonHandler() ) ); connect( _resetButton, SIGNAL( clicked() ), this, SLOT( resetButtonHandler() ) ); connect( _cancelButton, SIGNAL( clicked() ), this, SLOT( closeHandler() ) ); } void ExchangeCfgDlg::updateDialogContent() { static const char (*mname) ("ExchangeCfgDlg::updateDialogContent"); // std::cout << mname << std::endl; // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::updateDialogContent()"); } // Put the exchange name in the line edit. const RWCString exchangeName = _exchangeCopy->getName(); _nameLineEdit->setText(exchangeName.data()); // Update the borrow frame const Supply* theBorrow = _exchangeCopy->getBorrowSupply(); const bool hasBorrowSupply = (theBorrow != NULL); // Put the borrow supply name in the line edit if (hasBorrowSupply) { const RWCString borrowName = theBorrow->getName(); _borrowNameCache = borrowName.data(); _borrowLineEdit->setText (_borrowNameCache); // std::cout << mname << " borrowNameCache = '" // << qPrintable (_borrowNameCache) << "'" << std::endl; // The exchange is set up to obtain borrow values // from a user-defined supply, so select the // "Select Supply" radiobutton. _borrowButtonGroup->setButton (radioSelectSupply); } else // (not hasBorrowSupply) { // Even though the exchange is set up to get // borrow values from a user-defined supply, // a supply has not been selected. _borrowLineEdit->setText(""); // The exchange is set up to let the user provide input for borrow // values, so select the "Input Borrowed Amounts" radiobutton. _borrowButtonGroup->setButton (radioInputBorrow); } // Update the destination frame Supply* theDestination = _exchangeCopy->getDestSupply(); const bool hasDestSupply (theDestination != NULL); if (hasDestSupply) { // Put the destination supply name in the line edit const RWCString destinationName = theDestination->getName(); _destNameCache = destinationName.data(); _payDestLineEdit->setText (_destNameCache); // The exchange is set up to have a payback destination // so select the "Select Destination" radiobutton. _payDestButtonGroup->setButton (radioSelectDest); } else { // Even though the exchange is set up to have a // payback destination, one has not been specified for use. _payDestLineEdit->setText(""); // The exchange is not set up with a destination supply _payDestButtonGroup->setButton (radioNoDest); } // Update the Payback sources frame _editablePaybacksList = _exchangeCopy->getPaybackEditList(); const Payback* currentPayback; PaybackSrcItem* item; _paySourceListView->clear(); foreach_EditList (Payback, *_editablePaybacksList, currentPayback) { if (rwAssert(currentPayback != NULL)) { // Make sure this isn't a deleted payback if (currentPayback->isDeleted() == false) { // Add the payback to the list view item = new PaybackSrcItem(_paySourceListView, currentPayback); } } } // Update the units frame // Obtain the list of available user unit names that are appropriate // for the exchange's unit type (which is always 'Volume') and // populate the combo box. UnitNameList listOfUserUnitNames; unit_type selectedUnitType = _exchangeCopy->getUnitType(); unitMgr->getUnitNames(listOfUserUnitNames, selectedUnitType); _userUnitsCombo->clear(); cwIterator it; int index(0); int selectedIndex(0); FORALL(it, listOfUserUnitNames) { const RWCString userUnitName = listOfUserUnitNames.elem(it); _userUnitsCombo->insertItem(userUnitName.data()); if (userUnitName == _exchangeCopy->getUsrUnits()) { selectedIndex = index; } index++; } _userUnitsCombo->setCurrentItem(selectedIndex); // Update format option combo box _formatCombo->clear(); selectedIndex = 0; for (int row = 0; row < NUMDISPLAYFORMATS; row++) { // Add the name of this format to the option menu. // Notice that the string must be persistent in order to // be used within the option menu. There's no need to delete these // strings later to avoid memory leaks. RWCString formatString = displayFormatString[row]; _formatCombo->insertItem(formatString.data()); if (_exchangeCopy->getUsrFormat() == displayFormatConversionChar[row]) { selectedIndex = row; } } _formatCombo->setCurrentItem(selectedIndex); // Update precision spinner _precisionSpin->setValue(_exchangeCopy->getUsrPrecision()); // Update scale lineEdit QString scale = QString::number(_exchangeCopy->getUsrScale()); _scaleLineEdit->setText(scale); // Update enabledness of items in the dialog updateEnabledness(); } void ExchangeCfgDlg::updateEnabledness() { // Update borrow supply frame if (_selBorrowRadioButton->isChecked()) { // Select supply option _selBorrowButton->setEnabled(true); _borrowLineEdit->setEnabled(true); } else { // Input Borrow amounts option _selBorrowButton->setEnabled(false); _borrowLineEdit->setEnabled(false); } // Update payback destination frame if (_selDestRadioButton->isChecked()) { // Select destination option _selDestButton->setEnabled(true); _payDestLineEdit->setEnabled(true); } else { // No destination _selDestButton->setEnabled(false); _payDestLineEdit->setEnabled(false); } // Update Payback sources frame // An item must be selected in list view // for Modify and Remove buttons to be enabled // and for modify, remove, and edit loss actions // in context menu to be enabled if (_paySourceListView->selectedItem()) { _modifyButton->setEnabled(true); _removeButton->setEnabled(true); _modifyPaybackSourceAction->setEnabled(true); _removePaybackSourceAction->setEnabled(true); _editPaybackLossAction->setEnabled(true); } else { _modifyButton->setEnabled(false); _removeButton->setEnabled(false); _modifyPaybackSourceAction->setEnabled(false); _removePaybackSourceAction->setEnabled(false); _editPaybackLossAction->setEnabled(false); } // Modify enabledness for viewer mode if (!rwSystem->modelEditIsAllowed() || rwWorkspace->isBaselineModel()) { disableModelEdit(); } } void ExchangeCfgDlg::disableModelEdit() { // Prevent the user from modifying the model from the GUI. // Disable apply and OK buttons _okButton->setEnabled(false); _applyButton->setEnabled(false); // Disable Borrow Supply button group _borrowButtonGroup->setEnabled(false); // Disable Payback Destination Supply button group _payDestButtonGroup->setEnabled(false); // Disable Payback Sources group box _paySourceGroupBox->setEnabled(false); // Let the user freely configure the Units tab } //===================================================================== // GRAND UNIFIED SELECTOR METHODS //===================================================================== void ExchangeCfgDlg::showGusSupplySelector (const RWCString& caption, char gusUse, Supply* sply) { // Note: This check is to ensure that only one GUS Supply Selector // is ever shown. if (_gusSelector) { delete _gusSelector; _gusSelector = NULL; } if (_rootSelection == NULL) { _rootSelection = new RootSelection(); _rootSelection->setRootSubclassType (Root::SUBCLASS_SUPPLY); _rootSelection->addAllAvailableFilters(); } _gusUse = gusUse; _rootSelection->clearTerminalSelection(); _rootSelection->setName (caption.data()); if (sply != NULL) { _rootSelection->clearSelection(); _rootSelection->clearSimObjClasses(); _rootSelection->clearFilters(); _rootSelection->initSelectionWithSupply(sply); _rootSelection->recompute(); } GusOptions gusOpts; gusOpts._singleTerminalSelection = true; _gusExchCfgDlgUser = this; _gusSelector = new GusSelector (_rootSelection, gusOpts); _gusSelector->setListener (this); _gusSelector->show(); } void ExchangeCfgDlg::closeGusSupplySelector () { // Note: Don't delete _rootSelection. Save it for reuse. // Delete it when this client dialog box is deleted. if (_gusExchCfgDlgUser == this) { if (_rootSelection) _rootSelection->clearSelection(); if (_gusSelector) { delete _gusSelector; _gusSelector = NULL; } } } void ExchangeCfgDlg::gusProcessSelectedSupply (GusSelector* /*gus*/) { static const char (*mname) ("ExchangeCfgDlg::gusProcessSelectedSupply"); Supply (*sply) (_rootSelection->firstSupply()); if (sply == NULL) return; //--------------------->> const RWCString supplyName (sply->getName()); switch (_gusUse) { case 'B': // *** Borrow Supply *** //-------------------------------------------- // ADD THE NEWLY SELECTED SUPPLY OBJECT AS THE // BORROWER IN THE EXCHANGE // Set the exchange's borrower. try { _exchangeCopy->setBorrowSupply (sply); // Show the appropriate borrow name text in the dialog. _borrowNameCache = supplyName.data(); _borrowLineEdit->setText (_borrowNameCache); // std::cout << mname << " borrowNameCache = '" // << qPrintable (_borrowNameCache) << "'" << std::endl; } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } break; case 'D': // *** Payback Destination *** //--------------------------------------------------------- // ADD THE NEWLY SELECTED SUPPLY OBJECT AS THE // PAYBACK DESTINATION FOR THE EXCHANGE // Set the exchange's payback destination. try { _exchangeCopy->setDestSupply((Supply*) sply); // Show the appropriate destination name text in the dialog. _destNameCache = supplyName.data(); _payDestLineEdit->setText (_destNameCache); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } break; case 'A': // *** Add Payback Source *** addPaybackSource(sply); break; case 'M': // *** Modify Payback Source *** modifyPaybackSource(sply); break; default: // ERROR rwAssert (("Invalid _gusUse flag", 0)); } } // virtual void ExchangeCfgDlg::gusOk (GusSelector* gus, GusClientData*) { // Note: The selector will automatically close and be deleted after // returning to the caller of this method. Drop our Gus pointer. if (_gusSelector && (_gusExchCfgDlgUser == this) && rwAssert (gus == _gusSelector)) _gusSelector = NULL; // Add new Slot-Things to the SCT. gusProcessSelectedSupply (gus); } // virtual void ExchangeCfgDlg::gusApply (GusSelector* gus, GusClientData*) { // Add new Slot-Things to the SCT. gusProcessSelectedSupply (gus); // Clear terminal selection to prepare to select more Slots. RootSelection (*sel) (gus->rootSelection()); sel->clearTerminalSelection(); } // virtual void ExchangeCfgDlg::gusCancel (GusSelector* gus, GusClientData*) { // Note: The selector will automatically close and be deleted after // returning to the caller of this method. Drop our Gus pointer. if (_gusSelector && (_gusExchCfgDlgUser == this) && rwAssert (gus == _gusSelector)) _gusSelector = NULL; } // Payback Source methods void ExchangeCfgDlg::addPaybackSource(Supply* sply) { // If the selected supply exists as a supply for an active payback, // warn user and do not do the add (we can't have two paybacks // with the same supply). // If the selected supply exists as a supply for a payback marked // as deleted, undelete that payback. // Otherwise add a new payback with the selected supply // Check if supply already belongs to an active payback const Payback *currentPayback; bool undelete(false); Payback* undeletePayback; foreach_EditList (Payback, *_editablePaybacksList, currentPayback) { if (rwAssert(currentPayback != NULL)) { // Identify the payback source for this payback. Supply* currentSupply = currentPayback->getPaybackSupply(); if (currentSupply == sply) { if (!currentPayback->isDeleted()) { // Supply exists in an active payback // Warn user and exit int answer = QMessageBox::warning(this, "Exchange Cfg Error", "Selected supply already in payback source list.\n" "Addition cancelled.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); return; } else { // Note that a payback with the supply is currently deleted // and can be undeleted if no active one with the // supply is found undelete = true; undeletePayback = (Payback*) currentPayback; } } } } PaybackSrcItem* item(NULL); if (undelete) { // Deleted payback found with the supply - undelete it undeletePayback->isDeleted(false); // Add the undeleted payback to the list view // (display gets updated by the constructor) item = new PaybackSrcItem(_paySourceListView, undeletePayback); } else { // No payback found with supply - add a new one Payback* newPayback = new Payback(_exchangeCopy); if (rwAssert ((_editablePaybacksList != NULL) && (newPayback != NULL))) { try { // Create an editable copy of the new payback, and put that // copy into our list of editable paybacks for the exchange. // Set it to use the specified supply. Payback* editablePayback = _editablePaybacksList-> addObj(newPayback); editablePayback->setPaybackSupply(sply); // Add the new edit payback to the list view // (display gets updated by the constructor) item = new PaybackSrcItem(_paySourceListView, editablePayback); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } } // Set new item as the selected one if (item != NULL) { _paySourceListView->setSelected(item, true); } } void ExchangeCfgDlg::modifyPaybackSource(Supply* sply) { // Modify the supply for the payback source unless the new // supply already exists as a supply for an active payback // in the editable exchange. (we can't have two paybacks // with the same supply) // Check if supply already belongs to an active payback const Payback *currentPayback; foreach_EditList (Payback, *_editablePaybacksList, currentPayback) { if (rwAssert(currentPayback != NULL)) { // Identify the payback source for this payback. Supply* currentSupply = currentPayback->getPaybackSupply(); if (currentSupply == sply) { if (!currentPayback->isDeleted()) { // Supply exists in an active payback // Warn user and exit int answer = QMessageBox::warning(this, "Exchange Cfg Error", "Selected supply already in payback source list.\n" "Modification cancelled.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); return; } } } } // Ok to modify payback with selected supply PaybackSrcItem* paybackItem( (PaybackSrcItem*)_paySourceListView->selectedItem()); if (paybackItem != NULL) { const Payback* thePayback = paybackItem->getPaybackPtr(); if (thePayback != NULL) { try { // Change the supply in the payback source // of the exchange copy const_cast(thePayback)->setPaybackSupply(sply); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } } // Update display of PaybackSrcItem in payback soure list paybackItem->updateItemDisplay(); } void ExchangeCfgDlg::saveNameLineEditChange() { if (_isDialogClosing) { // We are processing a residual lost focus signal // Data members may be bad, so just return return; } // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::destinationRadiobuttonsHandler()"); } // Change the name of the Exchange on edit copy. RWCString name(_nameLineEdit->text().ascii()); try { _exchangeCopy->setName(name); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } void ExchangeCfgDlg::saveScaleLineEditChange() { if (_isDialogClosing) { // We are processing a residual lost focus signal // Data members may be bad, so just return return; } // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::unitsOptionMenuHandler()"); } // Set new scale on the edit exchange copy bool ok(true); QString newScaleText(_scaleLineEdit->text()); double newScale(newScaleText.toDouble(&ok)); _exchangeCopy->setUsrScale(newScale); } void ExchangeCfgDlg::closeDialog (bool isCancelRequired) { // The dialog is going to be closed, so we don't // want to waste time updating its contents. deleteCallbacks(); // Cancel needed unless coming from OK button if (isCancelRequired) { // Cancel edits to exchange if (rwAssert(_exchangeCopy != NULL)) { // Cancel the edits being made to the exchange try { AccountMgrObj->cancelExchangeEdit(_origExchange, _exchangeCopy); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } if (_displayMode == AcctGuiDefs::NEW_EXCHANGE) { // Set flag to delete the new exchange // (since the user has cancelled its formal creation). if (_origExchange != NULL) { _deleteNewExchange = true; } } } // In all cases the Accounting GUI Manager tracks the configuration dialogs // so we must use the manager to close and destroy this dialog. // First note that cancel has been completed _isCancelCompleted = true; QtAcctGuiMgrInst->removeExchangeCfgDlg (_origExchange); } void ExchangeCfgDlg::closeEvent(QCloseEvent *e) { // This set so no stray line edit lost focus signals // processed after dialog closed into bad state _isDialogClosing = true; if (_isCancelCompleted == false) { // CloseDialog call is needed to cancel changes // and close this dialog through // the Account GUI Manager closeDialog (true); // (Cancel Required) } if (_deleteNewExchange) { // We were configuring a new exchange that was // cancelled without saving, so delete it delete _origExchange; _origExchange = NULL; } // Accept the close event so the dialog closes e->accept(); } bool ExchangeCfgDlg::checkInputs() { // Make sure any changes in line edit widgets have been applied // (a lost focus event in the line edit may not have been processed // yet before getting here through an OK or Apply button click) saveNameLineEditChange(); saveScaleLineEditChange(); //------------------------------------------------------ // CHECK UNIQUE EXCHANGE NAME RWCString newExchName (_nameLineEdit->text().ascii()); const Exchange* conflictExch = AccountMgrObj->getExchange (newExchName, _origExchange); if (conflictExch != NULL) { QMessageBox::information (this, "Exchange Configuration Error", "The Exchange name is not unique.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); return (false); //----------->> } //------------------------------------------------------ // CHECK USER'S INTENT RE BORROWER bool presentMsg = false; RWCString errMsg(""); // If the user has chosen the option to specify a borrower, // warn them if one has not been specified. if ( (_borrowButtonGroup->selectedId()) == radioSelectSupply) { Supply* theBorrow = _exchangeCopy->getBorrowSupply(); if (theBorrow == NULL) { presentMsg = true; errMsg += "NO BORROW SUPPLY\n"; errMsg += "Normally you should select an existing supply,\n"; errMsg += "or else select the Input Borrowed Amounts option.\n\n"; } } //------------------------------------------------------ // CHECK USER'S INTENT RE PAYBACK DESTINATION, // If the user has chosen the option to specify a payback destination, // inform them if one has not been specified. if ( (_payDestButtonGroup->selectedId()) == radioSelectDest) { Supply* theDest = _exchangeCopy->getDestSupply(); if (theDest == NULL) { presentMsg = true; errMsg += "NO PAYBACK DESTINATION SUPPLY\n"; errMsg += "Normally you should select an existing supply,\n"; errMsg += "or else select the No Destination option.\n\n"; } } //------------------------------------------------------ // CHECK USER'S INTENT RE PAYBACK SOURCES // Inform user in no payback sources are specified if (_paySourceListView->childCount() == 0) { presentMsg = true; errMsg += "NO PAYBACK SOURCES\n"; errMsg += "Normally you should select at least one payback source.\n\n"; } //------------------------------------------------------ // Present message and see if user wants to go ahead without recommended data. if (presentMsg) { errMsg += "Are you sure you want to save the Exchange in this state?\n "; int answer = QMessageBox::warning(this, "Exchange Configuration Confirmation", errMsg.data(), QMessageBox::Ok, QMessageBox::Cancel, QMessageBox::NoButton); if (answer == QMessageBox::Cancel) { return false; } } return true; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void ExchangeCfgDlg::closeDialogPublic() { const bool cancelRequired (!_isCancelCompleted); closeDialog (cancelRequired); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Virtual from QWidget void ExchangeCfgDlg::showEvent (QShowEvent *evt) { // Call base class method Q3MainWindow::showEvent (evt); // Conditionally restore dialog geometry from prior hide. DlgGeometryMgr::processShow ("ExchangeCfgDlg", _origExchange, this, evt); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Virtual from QWidget void ExchangeCfgDlg::hideEvent (QHideEvent *evt) { // Save dialog geometry. DlgGeometryMgr::processHide ("ExchangeCfgDlg", _origExchange, this, evt); // Call base class method Q3MainWindow::hideEvent (evt); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Callback methods void ExchangeCfgDlg::addCallbacks(void) { //======================================================= // DELETE PREVIOUSLY REGISTERED CALLBACKS // We don't want a bunch of duplicate callbacks, // so delete the prior list. deleteCallbacks(); //======================================================= // REGISTER TO RECEIVE CALLBACKS FROM RIVERWARE SYSTEM // The dialog needs to respond if the workspace has been cleared. // (Specifically, it needs to cancel edits and close.) if (!_workspaceClearedCB) { MethodCb* cb = new MethodCb( this, &ExchangeCfgDlg::workspaceClearedHandler, ANY_CALLBACK_TYPE); rwSystem->addCCallback (ANY_CALLBACK_TYPE, cb); _workspaceClearedCB = cb; } //======================================================= // REGISTER TO RECEIVE CALLBACKS FROM THE ACCOUNT MANAGER // The dialog must respond if the accounting system is disabled. // (Specifically, it needs to cancel edits and close.) if (!_accountingStateChangedCB) { MethodCb* cb = new MethodCb( this, &ExchangeCfgDlg::accountingStateChangedHandler, ACCOUNTING_STATE_CHANGED); AccountMgrObj->addCCallback (ACCOUNTING_STATE_CHANGED, cb); _accountingStateChangedCB = cb; } //----------------------------------------------- // REGISTER CALLBACKS ON THE ORIGINAL EXCHANGE if (rwAssert (_origExchange != NULL) && !_exchangeOrigCB) { MethodCb* cb = new MethodCb( this, &ExchangeCfgDlg::exchangeOrigCBHandler, ANY_CALLBACK_TYPE); _origExchange->addCCallback (ANY_CALLBACK_TYPE, cb); _exchangeOrigCB = cb; } //----------------------------------------------- // REGISTER CALLBACKS ON THE COPY OF THE EXCHANGE // The dialog needs to respond if the exchange we're configuring is changed. // (Specifically, it needs to update the particular data that has changed.) if (rwAssert (_exchangeCopy != NULL) && !_exchangeCopyCB) { MethodCb* cb = new MethodCb( this, &ExchangeCfgDlg::exchangeCopyCBHandler, ANY_CALLBACK_TYPE); _exchangeCopy->addCCallback (ANY_CALLBACK_TYPE, cb); _exchangeCopyCB = cb; } } void ExchangeCfgDlg::deleteCallbacks(void) { //======================================================= // REMOVE CALLBACK REGISTRATIONS FROM THE SYSTEM if (_workspaceClearedCB) { rwSystem->deleteCallback(_workspaceClearedCB); _workspaceClearedCB = NULL; } //======================================================= // REMOVE CALLBACK REGISTRATION FROM THE ACCOUNT MANAGER if (_accountingStateChangedCB) { AccountMgrObj->deleteCallback(_accountingStateChangedCB); _accountingStateChangedCB = NULL; } //======================================================= // REMOVE CALLBACK REGISTRATION FROM THE EXCHANGE if (_exchangeOrigCB) { if (_origExchange) { _origExchange->deleteCallback(_exchangeOrigCB); } _exchangeOrigCB = NULL; } if (_exchangeCopyCB) { if (_exchangeCopy) { _exchangeCopy->deleteCallback(_exchangeCopyCB); } _exchangeCopyCB = NULL; } } int ExchangeCfgDlg::workspaceClearedHandler(CallbackType type, CallbackData* /* data */, void* /* clientData */) { static const char (*mname) ("ExchangeCfgDlg::workspaceClearedHandler"); // The object upon which the exchange resides is no longer available. // There's no point in going forward with any exchange edits. // std::cout << mname << " " << callbackTypeStr (type) << std::endl; if ( (type == WS_CLEARED) || (type == WS_CLEARING) ) { // Cancel the edits being made to the copy of the exchange, // and cause this dialog to be closed. closeDialog (true); // (Cancel Required) } return (true); } int ExchangeCfgDlg::accountingStateChangedHandler(CallbackType /* type */, CallbackData* /* data */, void* /* clientData */) { if (AccountMgrObj->getAccountingState() != ACCOUNTING_ENABLED) { // Cancel the edits being made to the copy of the exchange, // and cause this dialog to be closed. closeDialog (true); // (Cancel Required) } return (true); } int ExchangeCfgDlg::exchangeCBHandler(CallbackType cbType, CallbackData*, // cbData void*, // clientData bool isCopy) { static const char (*mname) ("ExchangeCfgDlg::exchangeCBHandler"); std::cout << mname << " " << (isCopy ? "[COPY]" : "[ORIG]") << " " << callbackTypeStr (cbType) << std::endl; if (cbType == EXCHANGE_CHANGED) { // Exchange edit copy has changed // Update dialog to reflect change updateDialogContent(); } else if (cbType == EXCHANGE_DELETED) { // The copy of the exchange has NOT yet been deleted, but is about // to be. We don't need to cancel the edits because deletion of the // exchange copy implicitly does that. Call dialog close with cancel // not required. // closeDialog (false); // (Cancel Not Required) } else if (cbType == EXCHANGE_ABORT_EDIT_NEEDED) { // The deletion of a related object (e.g. an Account having a Supply // involved in this Exchange) had violated the EditObj requirements for // all such events first checking the valid EditObj states of everything // in the world which needs to be considered. That is incredibly // expensive to implement, so we're not. If the use explicitly deletes // an Account or Object, we'll shut down this edit. That is, instead // of crashing a little later. So there. // closeDialog (true); } return (true); } int ExchangeCfgDlg::exchangeOrigCBHandler (CallbackType cbType , CallbackData* cbData, void* clientData) { const int retVal = exchangeCBHandler (cbType, cbData, clientData, false); // not isCopy return (retVal); } int ExchangeCfgDlg::exchangeCopyCBHandler (CallbackType cbType , CallbackData* cbData, void* clientData) { const int retVal = exchangeCBHandler (cbType, cbData, clientData, true); // isCopy return (retVal); } // Protected slots for Qt Signals void ExchangeCfgDlg::showWorkspaceHandler() { // Raise the workspace QGui::raiseWorkspace(); } void ExchangeCfgDlg::configureSystemHandler() { // Invoke the Accounting System configuration dialog. AccountingSystemConfig::openDlg(NULL); } void ExchangeCfgDlg::manageAccountsHandler() { // Invoke the Account Manager dialog. QtAcctMgrDlg::openDlg (NULL); } void ExchangeCfgDlg::manageSuppliesHandler() { // Open Qt Supply Manager Dialogs QtSplyMgrDlg::openDlg (NULL, NULL); } void ExchangeCfgDlg::borrowButtonHandler(int id) { static const char (*mname) ("ExchangeCfgDlg::borrowButtonHandler"); // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::destinationRadiobuttonsHandler()"); return; //----->> } if (id == radioSelectSupply) { const RWCString cacheBorrowName (_borrowNameCache.ascii()); Supply* cacheBorrowSply = const_cast (AccountMgrObj->getSupply (cacheBorrowName)); if (cacheBorrowSply && (cacheBorrowSply->getRole() == Supply::Standalone)) { _borrowLineEdit->setText (_borrowNameCache); _exchangeCopy->setBorrowSupply (cacheBorrowSply); } else { // The Borrow Name Cache no longer refers to an existing available // Supply. Wipe it out. _borrowNameCache = ""; _borrowLineEdit->setText (_borrowNameCache); _exchangeCopy->setBorrowSupply (NULL); } } else if (id == radioInputBorrow) { _exchangeCopy->setBorrowSupply (NULL); } else { // Is the select button - handled in selBorrowButtonHandler() return; } updateEnabledness(); } void ExchangeCfgDlg::payDestButtonHandler(int id) { // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::destinationRadiobuttonsHandler()"); } if (id == radioSelectDest) { const RWCString cacheDestName (_destNameCache.ascii()); Supply* cacheDestSply = const_cast (AccountMgrObj->getSupply (cacheDestName)); if (cacheDestSply && (cacheDestSply->getRole() == Supply::Standalone)) { _payDestLineEdit->setText (_destNameCache); _exchangeCopy->setDestSupply (cacheDestSply); } else { // The Dest Name Cache no longer refers to an existing available // Supply. Wipe it out. _destNameCache = ""; _payDestLineEdit->setText (_destNameCache); _exchangeCopy->setDestSupply (NULL); } // _exchangeCopy->hasDestSupply(true); } else if (id == radioNoDest) { _exchangeCopy->setDestSupply (NULL); } else { // Is the select button - handled in selDestButtonHandler() return; } updateEnabledness(); } void ExchangeCfgDlg::selBorrowButtonHandler() { // ************************************************ // *** Show Grand Unified Supply Selector (GUS) *** // ************************************************ Supply (*curBorrowSupply) (_exchangeCopy->getBorrowSupply()); RWCString selectionName ("Borrow Supply for Exchange "); selectionName += _exchangeCopy->getName(); showGusSupplySelector (selectionName, 'B', // Borrow Supply curBorrowSupply); } void ExchangeCfgDlg::selDestButtonHandler() { // ************************************************ // *** Show Grand Unified Supply Selector (GUS) *** // ************************************************ Supply (*curDestSupply) (_exchangeCopy->getDestSupply()); RWCString selectionName ("Payback Destination for Exchange "); selectionName += _exchangeCopy->getName(); showGusSupplySelector (selectionName, 'D', // Payback Destination Supply curDestSupply); } void ExchangeCfgDlg::nameLineEditHandler() { saveNameLineEditChange(); } void ExchangeCfgDlg::addButtonHandler() { // ************************************************ // *** Show Grand Unified Supply Selector (GUS) *** // ************************************************ RWCString selectionName ("Payback Source for Exchange "); selectionName += _exchangeCopy->getName(); showGusSupplySelector (selectionName, 'A', // Add Payback Source Supply NULL); } void ExchangeCfgDlg::modifyButtonHandler() { // ************************************************ // *** Show Grand Unified Supply Selector (GUS) *** // ************************************************ PaybackSrcItem* paybackItem( (PaybackSrcItem*)_paySourceListView->selectedItem()); // Must be a selected item to modify if (paybackItem != NULL) { const Payback* currentPayback(paybackItem->getPaybackPtr()); Supply* currentSupply = currentPayback->getPaybackSupply(); RWCString selectionName ("Payback Source for Exchange "); selectionName += _exchangeCopy->getName(); showGusSupplySelector (selectionName, 'M', // Modify Payback Source Supply currentSupply); } else { // Warn user no payback source selected int answer = QMessageBox::warning(this, "Exchange Cfg Error", "No payback source selected for modification.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } void ExchangeCfgDlg::removeButtonHandler() { // Get selected payback for removal PaybackSrcItem* paybackItem( (PaybackSrcItem*)_paySourceListView->selectedItem()); // Must be a selected item to remove if (paybackItem != NULL) { // Ask user to confirm intent to delete the selected payback source. int answer = QMessageBox::warning(this, "Exchange Cfg Confirmation", "Are you sure you want to delete the " "selected Payback Source?", QMessageBox::Ok, QMessageBox::Cancel, QMessageBox::NoButton); if (answer == QMessageBox::Cancel) { return; } const Payback* currentPayback(paybackItem->getPaybackPtr()); if (currentPayback != NULL) { // Mark payback as deleted const_cast(currentPayback)->isDeleted(true); } // Delete list view item (list view handles update of list) delete paybackItem; // Update enabledness of buttons updateEnabledness(); } else { // Warn user no supply selected int answer = QMessageBox::warning(this, "Exchange Cfg Error", "No payback source selected for removal.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } void ExchangeCfgDlg::userUnitsComboHandler(const QString& units) { // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::unitsOptionMenuHandler()"); } // Set the new units on the exchange edit copy RWCString newUnits(units.ascii()); _exchangeCopy->setUsrUnits(newUnits); } void ExchangeCfgDlg::formatComboHandler(const QString& formatString) { // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::unitsOptionMenuHandler()"); } // Set the new format on the edit exchange copy RWCString newFormatString(formatString.ascii()); for (int i=0; i < NUMDISPLAYFORMATS; i++) { // Determine the element number corresponding to that format name. if (newFormatString == displayFormatString[i]) { // Get the format control character that corresponds // to that element number, and set it as the format. _exchangeCopy->setUsrFormat(displayFormatConversionChar[i]); } } } void ExchangeCfgDlg::scaleLineEditHandler() { saveScaleLineEditChange(); } void ExchangeCfgDlg::precisionSpinHandler(int value) { // There's no point in proceeding if we don't have // a valid copy of the exchange to edit. if (!rwAssert(NULL != _exchangeCopy)) { rwInternalError(GUIID_RESOURCE, MSG_NO_EDIT_EXCH, "ExchangeCfgDlg::unitsOptionMenuHandler()"); } // Set new precision of the edit exchange copy _exchangeCopy->setUsrPrecision(value); } void ExchangeCfgDlg::okButtonHandler() { // Check input and give user opportunity to // cancel out if something is incomplete if (checkInputs() != true) { // User has canceled save return; } // We don't need dialog to update with changes we apply // to the exchange deleteCallbacks(); // Save changes through Account Manager if (rwAssert(_exchangeCopy != NULL)) { try { AccountMgrObj->okExchangeEdit(_origExchange, _exchangeCopy); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); // Don't close - allow user to fix problems // Refresh dialog updateDialogContent(); addCallbacks(); return; } } // Call dialog close with cancel not required closeDialog (false); // (Cancel Not Required) } void ExchangeCfgDlg::applyButtonHandler() { // Check input and give user opportunity to // cancel out if something is incomplete if (checkInputs() != true) { // User has canceled apply return; } // We don't need dialog to update with changes we apply // to the exchange deleteCallbacks(); // Apply changes through Account Manager if (rwAssert(_exchangeCopy != NULL)) { try { AccountMgrObj->applyExchangeEdit(_origExchange, _exchangeCopy); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); // Allow user to fix problems // Refresh dialog updateDialogContent(); addCallbacks(); return; } } // Refresh dialog and add callbacks // since dialog will remain open updateDialogContent(); addCallbacks(); // Since apply was successful, make sure // the dialog now shows a display mode // of EXISTING_EXCHANGE _displayMode = AcctGuiDefs::EXISTING_EXCHANGE; } void ExchangeCfgDlg::resetButtonHandler() { // We don't need dialog to update with changes to exchange deleteCallbacks(); // Cancel changes through Account Manager if (rwAssert(_exchangeCopy != NULL)) { try { AccountMgrObj->cancelExchangeEdit(_origExchange, _exchangeCopy); } catch (const cwException &error) { // Produce error message dialog int answer = QMessageBox::warning(this, "Exchange Cfg Error", error.what(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } // Previous editable copy of exchange has now been destroyed // Obtain new editable copy of the exchange if (getEditableExchange(_displayMode) != true) { // We can't proceed with editing the exchange // Close dialog - cancel not needed _isCancelCompleted = true; close(true); } // Update dialog contents and add callbacks updateDialogContent(); addCallbacks(); } void ExchangeCfgDlg::closeHandler() { // Make sure dialog closes down properly closeDialog (true); // (Cancel Required) } void ExchangeCfgDlg::displayContextHandler(Q3ListViewItem* /*qitem*/, const QPoint& pos, int /*col*/) { // Pop up the context menu _contextMenu->popup(pos); } void ExchangeCfgDlg::editPaybackLossHandler() { // Get selected list item PaybackSrcItem* paybackItem( (PaybackSrcItem*)_paySourceListView->selectedItem()); // Must be a selected item to edit the loss for if (paybackItem != NULL) { paybackItem->startRename(listLossCol); } else { // Warn user no payback source selected int answer = QMessageBox::warning(this, "Exchange Cfg Error", "No payback source selected for loss editing.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } void ExchangeCfgDlg::selectionChangedHandler() { // Update enabledness of Payback source buttons updateEnabledness(); } void ExchangeCfgDlg::paySourceDoubleClickHandler(Q3ListViewItem* item, const QPoint& /*pos*/, int /*col*/) { // Get list item PaybackSrcItem* paybackItem((PaybackSrcItem*)item); // Must be a selected item to edit the loss for if (paybackItem != NULL) { paybackItem->startRename(listLossCol); } } /////////////////////////////////////////////////////////////////////////////// // // ExchangeCfgDlgDlg::PaybackSrcItem // /////////////////////////////////////////////////////////////////////////////// ExchangeCfgDlg::PaybackSrcItem::PaybackSrcItem(Q3ListView* parent, const Payback* paybackPtr) : Q3ListViewItem(parent), _paybackPtr(paybackPtr), _parent(parent) { // Make loss column editable setRenameEnabled(listLossCol, true); setRenameEnabled(listNameCol, false); // If loss value is NaN, default it to zero ScalarSlot* lossSlot = (ScalarSlot*) ((Payback*)_paybackPtr)->getSlot(Payback::LossCoeff); if (rwAssert(lossSlot != NULL)) { // Get the value double lossValue = lossSlot->getValue(lossSlot->getUsrScale(), lossSlot->getUsrUnits()); if (!isValid(lossValue)) { lossSlot->setValue(0, lossSlot->getUsrScale(), lossSlot->getUsrUnits()); } } updateItemDisplay(); } // virtual ExchangeCfgDlg::PaybackSrcItem::~PaybackSrcItem() { } void ExchangeCfgDlg::PaybackSrcItem::updateItemDisplay() { QString text(""); // Set payback name const Supply* paybackSupply = _paybackPtr->getPaybackSupply(); if (NULL != paybackSupply) { text = paybackSupply->getName().data(); } setText(0, text); // Set loss value text = ""; ScalarSlot* lossSlot = (ScalarSlot*) ((Payback*)_paybackPtr)->getSlot(Payback::LossCoeff); RWCString lossText; if (rwAssert(lossSlot != NULL)) { // Get the formatted value RWCString lossValueString; cwFormatValue(lossSlot->getValue(lossSlot->getUsrScale(), lossSlot->getUsrUnits()), lossSlot->getUsrFormat(), lossSlot->getUsrPrecision(), lossValueString); text = lossValueString.data(); } setText(listLossCol, text); } // virtual from QListViewItem void ExchangeCfgDlg::PaybackSrcItem::startRename (int col) { // Call base class method Q3ListViewItem::startRename (col); QLineEdit* incellEdit = RwQtUtils::cellLineEditor (_parent); // Width of lineEdit set here because appears to be a bug when the // listview is shrunk in the x direction. The lineEdit width // automatically gets set so narrow that you can't see any characters // in it. We set it here to be one less than the width of the columns // and this seems to work fine. incellEdit->setMinimumWidth(_parent->columnWidth(listLossCol) - 1); if (incellEdit) { const QValidator* priorValidator = incellEdit->validator(); if (priorValidator == NULL) { // Assign a new Validator to this QLineEdit. I believe that // making a validator a child of the QLineEdit will take care // of the life-cycle of the thing. QDoubleValidator* newValidator( new QDoubleValidator(incellEdit, "Payback Loss Validator")); incellEdit->setValidator(newValidator); } } } // virtual protected from QListViewItem void ExchangeCfgDlg::PaybackSrcItem::okRename(int col) { // Called when user presses enter during in-place renaming of column col // Call base class method Q3ListViewItem::okRename(col); // Apply new loss value to the Payback double newLoss(text(listLossCol).toDouble()); ScalarSlot* lossSlot = (ScalarSlot*) ((Payback*)_paybackPtr)->getSlot(Payback::LossCoeff); if (rwAssert(lossSlot != NULL)) { SetStatus theStatus = lossSlot->setValue(newLoss, lossSlot->getUsrScale(), lossSlot->getUsrUnits()); if (theStatus != SET_OK) { // Produce error message dialog int answer = QMessageBox::warning(_parent, "Exchange Cfg Error", "Setting loss value on Payback was not successful.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); updateItemDisplay(); } } } //--- (end ExchangeCfgDlg.cpp) ---