// $Id: RepGenSlotHtml.cpp,v 1.10 2010/11/11 01:47:57 philw Exp $ // // class RepGenSlotHtml : public RepGenSlot // //-- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- static const char* HeaderBackgroundColor ("#d8d8d8"); static const char* ColMapBackgroundColor ("#ffffd8"); static const int MAX_SLOT_DATA_ROWS (300); #ifndef RepGenSlotHtmlINCLUDED #include "RepGenSlotHtml.hpp" #endif //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #ifndef RwModelReportINCLUDED #include "RwModelReport.hpp" #endif #ifndef RepGenUtilsINCLUDED #include "RepGenUtils.hpp" #endif #ifndef cwfstreamINCLUDED #include "cwfstream.hpp" #endif #ifndef SlotINCLUDED #include "Slot.hpp" #endif #ifndef SeriesSlotINCLUDED #include "SeriesSlot.hpp" #endif #ifndef ListSlotINCLUDED #include "ListSlot.hpp" #endif #ifndef SlotColRefINCLUDED #include "SlotColRef.hpp" #endif #ifndef SimObjINCLUDED #include "SimObj.hpp" #endif #ifndef SlotGUIUtilsINCLUDED #include "SlotGUIUtils.hpp" #endif #include "rwStr.hpp" #include //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- static const QString nbspQstr (" "); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // constructor 1 of 1 RepGenSlotHtml::RepGenSlotHtml (RwModelReport* rep, const Slot* slotPtr) : RepGenSlot (rep, slotPtr) { } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- RepGenSlotHtml::~RepGenSlotHtml() { _modelReport = NULL; _slot = NULL; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from RepGenSlot void RepGenSlotHtml::writeSlotListHeader (SlotListType slotListType, const QString& slotColLabel, int indentLev, cwofstream& os) const { const QString indentStr (indentLev, QChar (' ')); // Indent String static const QString listRowTempl_ScalarSlot ( "INDENT\n" "INDENT %2\n" // type icons / name "INDENT Value\n" // slot value "INDENT Units\n" // slot units "INDENT" ); static const QString listRowTempl_SeriesSlot ( "INDENT\n" "INDENT %2\n" // type icons / slot name "INDENT Units\n" // slot units "INDENT Rows\n" // slot row count "INDENT Cols\n" // slot column count "INDENT Step\n" // series step size "INDENT Start\n" // start date "INDENT End\n" // end date "INDENT" ); static const QString listRowTempl_OtherSlot ( "INDENT\n" "INDENT %2\n" // type icons / slot name "INDENT Rows\n" // slot row count "INDENT Cols\n" // slot column count "INDENT Column Labels\n" // slot column labels "INDENT" ); QString formatStr (""); switch (slotListType) { case SlotList_Scalar: formatStr = listRowTempl_ScalarSlot; break; case SlotList_Series: formatStr = listRowTempl_SeriesSlot; break; case SlotList_Other: formatStr = listRowTempl_OtherSlot; break; } formatStr.replace (QString ("INDENT"), indentStr); const QString html = formatStr .arg (HeaderBackgroundColor) .arg (slotColLabel); os << qPrintable (html) << endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from RepGenSlot void RepGenSlotHtml::writeSlotListRow (SlotListType slotListType, int indentLevel, cwofstream& os) const { static const char (*mname) ("RepGenSlotHtml::writeScalarSlotListRow"); if (_slot == NULL) return; //---------------------->> static const QString IconAndNameTD_Templ ( "INDENT T_OBJ_ICON\n" // obj type icon "INDENT T_SLOT_ICON\n" // slot type icon "INDENT T_SLOT_NAME\n" ); // slot name (no link) static const QString ValueTD_Templ ( "INDENT T_VALUE\n" ); static const QString UnitsTD_Templ ( "INDENT T_UNITS\n" ); static const QString RowsTD_Templ ( "INDENT T_ROWS\n" ); static const QString ColsTD_Templ ( "INDENT T_COLS\n" ); static const QString LabsTD_Templ ( "INDENT T_LABS\n" ); static const QString StepTD_Templ ( "INDENT T_STEP\n" ); static const QString StartTD_Templ ( "INDENT T_START\n" ); static const QString EndTD_Templ ( "INDENT T_END\n" ); QString tabDatElement (IconAndNameTD_Templ); // three columns switch (slotListType) { case SlotList_Scalar: tabDatElement += ValueTD_Templ; tabDatElement += UnitsTD_Templ; break; case SlotList_Series: tabDatElement += UnitsTD_Templ; tabDatElement += RowsTD_Templ; tabDatElement += ColsTD_Templ; tabDatElement += StepTD_Templ; tabDatElement += StartTD_Templ; tabDatElement += EndTD_Templ; break; case SlotList_Other: tabDatElement += RowsTD_Templ; tabDatElement += ColsTD_Templ; tabDatElement += LabsTD_Templ; break; } QString tabRowElement = QString ("INDENT\n%1" "INDENT\n") .arg (tabDatElement); // Indentation Substitution const QString indentStr (indentLevel, QChar (' ')); // Indent String tabRowElement.replace (QString ("INDENT"), indentStr); // Align-Right TD Attribute tabRowElement.replace (QString ("Align_RT"), "align=\"right\""); // HTML IMG ALIGN ATTRIBUTE static const QString iconAlignText (""); // (No align attribute) const QString objIconHtml = RepGen::html_icon (objImgFileHtml(), objImgSize(), 0, objTypHtml(), iconAlignText); const QString objUrl = RepGen::localSimObjUrl (_slot->getSimObj()); const QString objIconLinkHtml = RepGen::html_link (objIconHtml, objUrl); const QString slotIconHtml = RepGen::html_icon (slotImgFileHtml(), slotImgSize(), 0, slotTypHtml(), iconAlignText); QString slotNameHtmlStr (slotNameHtml()); // tentative const bool linkSlot (slotDetailSupported()); if (linkSlot) { const QString slotUrl = RepGen::localSlotUrl (_slot, true); // quoted slotNameHtmlStr = QString ("%2") .arg (slotUrl) .arg (slotNameHtml()); } tabRowElement.replace (QString ("T_OBJ_ICON"), objIconLinkHtml); tabRowElement.replace (QString ("T_SLOT_ICON"), slotIconHtml); tabRowElement.replace (QString ("T_SLOT_NAME"), slotNameHtmlStr); tabRowElement.replace (QString ("T_VALUE"), slotValHtml()); tabRowElement.replace (QString ("T_UNITS"), slotUnitsHtml (false)); tabRowElement.replace (QString ("T_ROWS"), slotRowsHtml()); tabRowElement.replace (QString ("T_COLS"), slotColsHtml()); tabRowElement.replace (QString ("T_LABS"), slotLabelsHtml()); tabRowElement.replace (QString ("T_STEP"), seriesStepHtml()); tabRowElement.replace (QString ("T_START"), seriesStartHtml()); tabRowElement.replace (QString ("T_END"), seriesEndHtml()); os << qPrintable (tabRowElement) << endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // private void RepGenSlotHtml::writeSlotDetailTitleSection (cwofstream& os) { if (_slot == NULL) return; //---------------------->> SimObj* obj (_slot->getSimObj()); // may be NULL // ******************************** // *** Slot HTML Named Anchor *** // ******************************** const QString objName = (obj ? obj->getCompleteName() : "SimObj"); const QString slotName = _slot->getName(); const QString fullSlotName = _slot->getCompleteName(); const QString slotMunge = RepGen::reduceNameString (fullSlotName); const QString slotAnchor = QString ("") .arg (slotMunge); QString fullSlotTitle (fullSlotName); fullSlotTitle.replace (QChar ('.'), QString (" . ")); os << qPrintable (slotAnchor) << endl; // **************************** // *** Slot Detail Header *** // **************************** static const QString fmt ( "\n" " \n" " \n" " \n" " \n" " \n" "
  \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
Object:  %1
Slot:  %2
 \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
%3 %4  %5 %6
\n" "
\n" "
   
\n" ); static const QString iconAlignText (""); // (No align attribute) const QString objIconHtml = RepGen::html_icon (objImgFileHtml(), objImgSize(), 0, objTypHtml(), iconAlignText); const QString objUrl = RepGen::localSimObjUrl (obj); const QString objIconLinkHtml = RepGen::html_link (objIconHtml, objUrl); const QString objLongTypStr (obj ? obj->getLongTypeName(true) : ""); const QString slotIconHtml = RepGen::html_icon (slotImgFileHtml(), slotImgSize(), 0, slotTypHtml(), iconAlignText); const QString slotTitleContent = fmt .arg (objName) .arg (slotName) .arg (objIconLinkHtml) .arg (objLongTypStr) // verbose .arg (slotIconHtml) .arg (slotTypHtml (true)); // verbose const QString boxedTitle = RepGen::htmlTableBox (0, slotTitleContent, 3); os << qPrintable (boxedTitle) << endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // private void RepGenSlotHtml::writeSlotDataTable (cwofstream& os) { if (_slot == NULL) return; //---------------------->> // **************************************** // *** Write Pre-Table Notes (if any) *** // *** (1) Row Truncation Notice *** // *** (2) Column Map Entity Name *** // **************************************** bool paragraphWritten (false); // tentative const int dataRowCnt = SlotGUIUtils::getNumSlotRows (_slot); const bool truncateRows = (dataRowCnt > MAX_SLOT_DATA_ROWS); if (truncateRows) { static const QString truncMsgFmt ( "

The number of rows in this slot (%1) exceeds the maximum \n" "number of slot rows for this report (%2). Only the first and \n" "last several rows are shown.

" ); const QString truncMsg = truncMsgFmt .arg (dataRowCnt) .arg (MAX_SLOT_DATA_ROWS); os << qPrintable (truncMsg) << endl; paragraphWritten = true; } QString colMapEntityName (""); const bool colMapEntityDef = SlotGUIUtils::getColMapEntityName (_slot, colMapEntityName); if (colMapEntityDef && !colMapEntityName.isEmpty()) { // Write Column Map Entity description static const QString colMapEntFmt ( "

Numeric column header value entity: %1

\n"); QString colMapEntStr = colMapEntFmt .arg (colMapEntityName); os << qPrintable (colMapEntStr) << endl; paragraphWritten = true; } if (!paragraphWritten) { os << " 
" << endl; } // ************************************** // *** Set up HTML Table Attributes *** // ************************************** static const QString cellPaddingFmt (" cellpadding=\"%1\""); static const QString cellSpacingFmt (" cellspacing=\"%2\""); static const QString borderPixFmt (" border=\"%3\""); const QString cellPadding (cellPaddingFmt .arg (4)); // PADDING const QString cellSpacing (cellSpacingFmt .arg (0)); // CELL SPACING const QString borderPix (borderPixFmt .arg (1)); // BORDER static const QString tableElement ( QString ("") .arg (cellPadding) .arg (cellSpacing) .arg (borderPix) ); // ************************* // *** Slot Data Table *** // ************************* os << qPrintable (tableElement) << endl; writeSlotDataTableColMap (1, os); writeSlotDataTableHeader (1, os); for (int rowInx = 0; rowInx < dataRowCnt; ++rowInx) { writeSlotDataTableRow (rowInx, 1, os); if (truncateRows) { if (rowInx == 4) { // Draw divider row writeSlotDataTableRow ((-1), 1, os); // Skip ahead rowInx = std::max (5, dataRowCnt-5); } } } os << "\n" << " 
" << endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // private void RepGenSlotHtml::writeSlotDataTableHeader (int indentLevel, cwofstream& os) { if (_slot == NULL) return; //---------------------->> // ListSlots don't need a slot data table header if (_slot->isA (Slot::ListSlotBit)) return; //--------------------------------------->> static const QString trFmtBeg ("INDENT\n"); static const QString tdFmtLft ("INDENT %1\n"); static const QString tdFmtRgt ("INDENT %1\n"); static const QString trFmtEnd ("INDENT\n"); QString trElement (trFmtBeg.arg (HeaderBackgroundColor)); trElement += tdFmtLft.arg (nbspQstr); const int dataColCnt = SlotGUIUtils::getNumCols (_slot); for (int colInx = 0; colInx < dataColCnt; ++colInx) { const QString colLab = SlotGUIUtils::getColLabel (_slot, colInx).toLocal8Bit().constData(); const ScaledUnitPtr scUnit = SlotGUIUtils::getScaledUnitPtr (_slot, colInx); const QString colUnits = SlotGUIUtils::scaledUnitDisplayStr (scUnit); bool alignRight (true); // tentative QString colHeaderHtml (""); // tentative if (!colLab.isEmpty()) { alignRight = false; colHeaderHtml = colLab; } if (!colUnits.isEmpty()) { if (!colHeaderHtml.isEmpty()) colHeaderHtml += "
"; colHeaderHtml += QString ("[%2]") .arg (colUnits); } if (colHeaderHtml.isEmpty()) { colHeaderHtml = nbspQstr; } trElement += (alignRight ? tdFmtRgt : tdFmtLft) .arg (colHeaderHtml); } trElement += trFmtEnd; const QString indentStr (indentLevel, QChar (' ')); // Indent String trElement.replace (QString ("INDENT"), indentStr); os << qPrintable (trElement) << endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // private void RepGenSlotHtml::writeSlotDataTableColMap (int indentLevel, cwofstream& os) { if (_slot == NULL) return; //---------------------->> // Only TableSlots (incl. subclasses) support Column Maps (NumericDimension) if (!_slot->isA (Slot::TableSlotBit)) return; //----------------------------------------->> QStringList colMapUsrValStrs; QString colMapUnitsStr (""); const bool colMapDataFound = SlotGUIUtils::getColMapUsrValues (_slot, colMapUsrValStrs, colMapUnitsStr); if (!colMapDataFound) return; //------------------------->> if (!colMapUnitsStr.startsWith (QChar ('['))) colMapUnitsStr = QString ("[%1]") .arg (colMapUnitsStr); static const QString trFmtBeg ("INDENT\n"); static const QString tdFmtLft ("INDENT %1\n"); static const QString tdFmtRgt ("INDENT %1\n"); static const QString trFmtEnd ("INDENT\n"); QString trElement (trFmtBeg.arg (ColMapBackgroundColor)); trElement += tdFmtLft.arg (nbspQstr); // blank row header column const int dataColCnt = SlotGUIUtils::getNumCols (_slot); for (int colInx = 0; colInx < dataColCnt; ++colInx) { const QString colMapStr = colMapUsrValStrs.value (colInx); const QString valStr = colMapStr.isEmpty() ? nbspQstr : colMapStr; const QString unitStr = colMapStr.isEmpty() ? nbspQstr : colMapUnitsStr; const QString colMapHtml = QString ("%1
%2") .arg (valStr) .arg (unitStr); trElement += tdFmtRgt.arg (colMapHtml); } trElement += trFmtEnd; const QString indentStr (indentLevel, QChar (' ')); // Indent String trElement.replace (QString ("INDENT"), indentStr); os << qPrintable (trElement) << endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // private void RepGenSlotHtml::writeSlotDataTableRow (int row, int indentLevel, cwofstream& os) { static const QString ellipsis ("..."); //-------------------------------------------------------- // NOTE: if (row < 0), show a divider row (with ellipsis). //-------------------------------------------------------- if (_slot == NULL) return; //---------------------->> const bool isListSlot (_slot->isA (Slot::ListSlotBit)); static const QString trFmtBeg ("INDENT\n"); static const QString tdFmtLft ("INDENT %1\n"); static const QString tdFmtRgt ("INDENT %1\n"); static const QString trFmtEnd ("INDENT\n"); QString trElement (trFmtBeg); // *********************************** // *** Row Header (First Column) *** // *********************************** const bool supportsTextRowLabel (_slot->isA (Slot::TableSlotBit) || _slot->isA (Slot::SeriesSlotBit) ); QString rowLab (nbspQstr); // tentative bool rowHeaderColAlignRight (true); // tentative if (row < 0) { rowLab = ellipsis; } else // (row >= 0) { rowLab = QString::number (row); // tentative if (supportsTextRowLabel) { const QString rowLabStr = SlotGUIUtils::getRowLabel (_slot, row); if (!rowLabStr.isEmpty()) { rowLab = rowLabStr; rowHeaderColAlignRight = false; } } } trElement += (rowHeaderColAlignRight ? tdFmtRgt.arg (rowLab) : tdFmtLft.arg (rowLab)); // ************************************************ // *** Special Column for ListSlots: Item Icon *** // ************************************************ if (isListSlot) { const ListSlotBase* lslot = dynamic_cast (_slot); if (lslot) { IconHandle lsIcon ((SimObj*) NULL, false); const bool iconOk = lslot->getItemIcon (row, lsIcon); if (iconOk) { const QString imgFileStr = RepGen::imgFileStr (lsIcon, _modelReport); const QSize imgSize = RepGen::imgSize (lsIcon); const QString altText = lsIcon.iconDescStr(); const QString objIconHtml = RepGen::html_icon (imgFileStr, imgSize, 0, altText, ""); trElement += tdFmtLft.arg (objIconHtml); } else { trElement += tdFmtLft.arg (nbspQstr); } } } // *************************** // *** Slot Data Columns *** // *************************** const QString tdFmt (isListSlot ? tdFmtLft : tdFmtRgt); const int dataColCnt = SlotGUIUtils::getNumCols (_slot); for (int colInx = 0; colInx < dataColCnt; ++colInx) { if (row < 0) { trElement += tdFmt.arg (ellipsis); } else { const QString valStr = SlotGUIUtils::getValueUsrStr (_slot, row, colInx, false, //-- for edit false); //-- alt units trElement += tdFmt.arg (valStr); } } trElement += trFmtEnd; const QString indentStr (indentLevel, QChar (' ')); // Indent String trElement.replace (QString ("INDENT"), indentStr); os << qPrintable (trElement) << endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // ***************************** // *** HTML Slot Utilities *** // ***************************** QString RepGenSlotHtml::slotTypHtml (bool verbose /*=false*/) const { const QString str = slotTypStr (verbose); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::slotImgFileHtml() const { if (_slot) { const IconHandle slotIcon (_slot); const QString filename = RepGen::imgFileStr (slotIcon, _modelReport); return (filename); //-------------->> } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QSize RepGenSlotHtml::slotImgSize() const { QSize slotTypeIconSize (0,0); // tentative if (_slot) { const IconHandle slotIcon (_slot); slotTypeIconSize = RepGen::imgSize (slotIcon); } return (slotTypeIconSize); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::slotNameHtml() const { const QString str = slotNameStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::slotValHtml() const { const QString str = slotValStr(); // [RepGenSlot] (for scalars) if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::slotUnitsHtml (bool withBrackets) const { const QString str = slotUnitsStr (withBrackets); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::slotRowsHtml() const { const QString str = slotRowsStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::slotColsHtml() const { const QString str = slotColsStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::slotLabelsHtml() const { const QString str = slotLabelsStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::seriesStepHtml() const { const QString str = seriesStepStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::seriesStartHtml() const { const QString str = seriesStartStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::seriesEndHtml() const { const QString str = seriesEndStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::objTypHtml() const { const QString str = objTypStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::objImgFileHtml() const { const SimObj* simObj = (_slot ? _slot->getSimObj() : NULL); if (simObj) { const IconHandle objIcon (simObj, false); // Not Large const QString filename = RepGen::imgFileStr (objIcon, _modelReport); return (filename); //-------------->> } return (nbspQstr); //   } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QSize RepGenSlotHtml::objImgSize() const { QSize objTypeIconSize (0,0); // tentative SimObj* obj = (_slot ? _slot->getSimObj() : NULL); if (obj) { const IconHandle objIcon (obj, false); // not large objTypeIconSize = RepGen::imgSize (objIcon); } return (objTypeIconSize); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QString RepGenSlotHtml::objNameHtml() const { const QString str = objNameStr(); // [RepGenSlot] if (!str.isEmpty()) { return (str); } return (nbspQstr); //   } //--- (end RepGenSlotHtml.cpp) ---