// // File: hdsNavtree.cpp // // Legal Notice: This file is part of the HadronZoo C++ Class Library. Copyright 2025 HadronZoo Project (http://www.hadronzoo.com) // // The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free // Software Foundation, either version 3 of the License, or any later version. // // The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR // A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses. //
#include <iostream> #include <fstream>
#include <unistd.h> #include <stdarg.h> #include <dirent.h> #include <netdb.h> #include <signal.h>
#include "hzErrcode.h" #include "hzDissemino.h"
using namespace std ;
/* ** Functions */
const hdsArticle* hdsNavtree::GetItem (const hzString& refname) const { _navitem item ; // Title/articleId
if (!m_ItemsByName.Exists(refname)) return 0 ;
item = m_ItemsByName[refname] ; if (item.m_ItemId) return m_Articles[item.m_ItemId - 1] ; return 0 ; }
const hdsArticle* hdsNavtree::GetItem (uint32_t itemId) const { if (itemId == 0 || itemId > m_Articles.Count()) return 0 ;
return m_Articles[itemId - 1] ; }
hzEcode hdsNavtree::AddHead (const hzString& parent, const hzString& refname, const hzString& title, bool bSlct) { // Add a heading to the tree. No article so the _navitem only has the article title
_hzfunc("hdsNavtree::AddHead(1)") ;
_navitem item ; // New tree item _navitem parItem ; // Parent item
// Qualify item if (!refname) return hzerr(E_ARGUMENT, "%s: No item refname supplied", *m_Groupname) ; if (!title) return hzerr(E_ARGUMENT, "%s: No item title supplied", *m_Groupname) ;
if (m_ItemsByName.Exists(refname)) hzexit(E_DUPLICATE, "%s: Heading %s (%s) already exists", *m_Groupname, *refname, *title) ;
if (parent) { if (!m_ItemsByName.Exists(parent)) return hzerr(E_CORRUPT, "%s: Heading %s (%s): Stated parent (%s) does not exist", *m_Groupname, *refname, *title, *parent) ;
parItem = m_ItemsByName[parent] ; }
item.m_Title = title ;
if (bSlct) item.m_bFlags |= HZ_TREEITEM_OPEN ; item.m_bFlags |= HZ_TREEITEM_LINK ;
if (!parent) item.m_nLevel = 0 ; else item.m_nLevel = parItem.m_nLevel + 1 ;
m_ItemsByParent.Insert(parent, refname) ; m_ItemsByName.Insert(refname, item) ;
return E_OK ; }
hzEcode hdsNavtree::AddItem (const hzString& parent, const hzString& refname, const hzString& title, hdsArticle* pArt, bool bSlct) { // Add an item. The first item should have a NULL parent // // Arguments: 1) parent Parent refname // 2) refname Reference name of new item // 3) title Title (how item appears in tree) // 4) pItem Tree item (if any) // 5) bSlct Show as open // // Returns: E_ARGUMENT If either the itemId or headline is not supplied // E_DUPLICATE If the supplied item id already exists
_hzfunc("hdsNavtree::AddItem") ;
_navitem item ; // New item _navitem parItem ; // Parent item hzEcode rc = E_OK ; // Return code
// Qualify item threadLog("Adding article %p %s\n", pArt, *refname) ; if (!refname) return hzerr(E_ARGUMENT, "%s: No item item id supplied", *m_Groupname) ; if (!title) return hzerr(E_ARGUMENT, "%s: No item headline supplied", *m_Groupname) ;
// Check item id (item id) is unique if (m_ItemsByName.Exists(refname)) return hzerr(E_DUPLICATE, "%s: Duplicate entry attempted: Item %s alredy exists", *m_Groupname, *refname) ;
// If parent is supplied, it must exist if (parent) { if (!m_ItemsByName.Count()) return hzerr(E_CORRUPT, "%s: Adding first item %s but with non-null parent", *m_Groupname, *title) ;
if (!m_ItemsByName.Exists(parent)) return hzerr(E_CORRUPT, "%s: Supplied parent (%s) does not exist", *m_Groupname, *parent) ;
parItem = m_ItemsByName[parent] ; }
// ADD the item m_Articles.Add(pArt) ; item.m_ItemId = m_Articles.Count() ; item.m_Title = title ;
if (bSlct) item.m_bFlags |= HZ_TREEITEM_OPEN ; item.m_bFlags |= HZ_TREEITEM_LINK ;
if (!parent) item.m_nLevel = 0 ; else item.m_nLevel = parItem.m_nLevel + 1 ;
rc = m_ItemsByParent.Insert(parent, refname) ; if (rc != E_OK) return hzerr(rc, "%s: Could not insert parent for article %s", *m_Groupname, *title) ;
rc = m_ItemsByName.Insert(refname, item) ; if (rc != E_OK) return hzerr(rc, "%s: Could not insert article %s", *m_Groupname, *title) ;
return rc ; }
void hdsNavtree::Clear (void) { _hzfunc("hdsNavtree::Clear") ;
hdsArticle* pArt ; // Current item uint32_t n ; // Article iterator
for (n = 0 ; n < m_Articles.Count() ; n++) { pArt = m_Articles[n] ; delete pArt ; }
m_ItemsByParent.Clear() ; m_ItemsByName.Clear() ; }
hzEcode hdsNavtree::_procArticle (hzChain& Z, const hzString& parent) const { // Support function for ExportArticleSet (see below) // // Adds tree item to supplied chain // // Arguments: 1) J Chain in which tree is being built // 2) pItem Tree item to process // // Returns: E_ARGUMENT If the tree item pointer is NULL // E_OK If the tree is exported to the supplied chain
_hzfunc("hdsNavtree::_procArticle") ;
hdsArticle* pArt ; // Article hdsArticleStd* pArtStd ; // Article _navitem item ; // Next tree item hzXDate now ; // Current time and date hzString refname ; // Refname of item hzString state ; // Open or closed int32_t nLo ; // Lowest position in m_AllItemsByParent int32_t nHi ; // Higest position in m_AllItemsByParent int32_t n ; // Item counter
nLo = m_ItemsByParent.First(parent) ; if (nLo < 0) return E_OK ; nHi = m_ItemsByParent.Last(parent) ;
now.SysDateTime() ;
// Print: Item is a folder. In the first instance (the only time the level is 1) for channel J we don't want to start with a comma, otherwise we do for (n = nLo ; n <= nHi ; n++) { refname = m_ItemsByParent.GetObj(n) ; item = m_ItemsByName[refname] ;
if (item.m_bFlags & HZ_TREEITEM_OPEN) state = "open" ; else state = "closed" ;
if (!item.m_ItemId) { if (item.m_bFlags & HZ_TREEITEM_LINK) Z.Printf("\n<xtreeItem parent=\"%s\" id=\"%s\" hdln=\"%s\" display=\"%s\"/>\n", *parent, *refname, *item.m_Title, *state) ; else Z.Printf("\n<xtreeHead parent=\"%s\" id=\"%s\" hdln=\"%s\" display=\"%s\"/>\n", *parent, *refname, *item.m_Title, *state) ; } else { pArt = m_Articles[item.m_ItemId - 1] ; pArtStd = dynamic_cast<hdsArticleStd*>(pArt) ;
if (item.m_bFlags & HZ_TREEITEM_LINK) { Z.Printf("\n<xtreeItem parent=\"%s\" id=\"%s\" tdstamp=\"%s\" hdln=\"%s\" display=\"%s\">\n", *parent, *refname, *now, *item.m_Title, *state) ; if (pArtStd) //Z << pArtStd->m_Content ; Z << pArtStd->m_rawHTML ; Z << "\n</xtreeItem>\n" ; } else { Z.Printf("\n<xtreeHead parent=\"%s\" id=\"%s\" hdln=\"%s\" display=\"%s\">\n", *parent, *refname, *item.m_Title, *state) ; if (pArtStd) //Z << pArtStd->m_Content ; Z << pArtStd->m_rawHTML ; Z << "\n</xtreeHead>\n" ; } }
_procArticle(Z, refname) ; }
return E_OK ; }
hzEcode hdsNavtree::ExportArticleSet (hzChain& Z) { // Purpose: Export tree as an article set // // Arguments: 1) J The chain in which tree is being built // // Returns: E_NODATA If the tree is empty // E_OK If the tree is exported to the supplied chain
_hzfunc("hdsNavtree::ExportArtcleSet") ;
if (!m_ItemsByName.Count()) return E_NODATA ;
hzString root ; // Blank string
_procArticle(Z, root) ; return E_OK ; }
hzEcode hdsNavtree::_procTreeitem (hzChain& J, const hzString& parent) const { // Support function for ExportDataScript (see below) // // Adds tree item to supplied chain // // Arguments: 1) J Chain in which tree is being built // 2) pItem Tree item to process // // Returns: E_ARGUMENT If the tree item pointer is NULL // E_OK If the tree is exported to the supplied chain
_hzfunc("hdsNavtree::_procTreeitem") ;
_navitem item ; // Tree item hzString refname ; // Refname of item int32_t nLo ; // Lowest position in m_AllItemsByParent int32_t nHi ; // Higest position in m_AllItemsByParent int32_t n ; // Item counter int32_t i ; // Indent counter int32_t nChild ; // True if link //uint32_t id ; // ID of item
nLo = m_ItemsByParent.First(parent) ; if (nLo < 0) return E_OK ; nHi = m_ItemsByParent.Last(parent) ;
for (n = nLo ; n <= nHi ; n++) { refname = m_ItemsByParent.GetObj(n) ; item = m_ItemsByName[refname] ;
nChild = m_ItemsByParent.First(refname) >= 0 ? 1 : 0 ; //nChild = 1 ;
if (item.m_nLevel || n > nLo) J.AddByte(CHAR_COMMA) ; J.AddByte(CHAR_NL) ; for (i = item.m_nLevel ; i ; i--) J.AddByte(CHAR_TAB) ;
if (item.m_bFlags & HZ_TREEITEM_LINK) J.Printf("[%d,%d,%d,\"%s\",\"%s\"]", item.m_nLevel, nChild, item.m_bFlags & HZ_TREEITEM_OPEN ? 1:0 , *item.m_Title, *refname) ; else J.Printf("[%d,%d,%d,\"%s\",\"%s\"]", item.m_nLevel, nChild, item.m_bFlags & HZ_TREEITEM_OPEN ? 1:0 , *item.m_Title, *refname) ;
if (nChild) _procTreeitem(J, refname) ; }
return E_OK ; }
hzEcode hdsNavtree::ExportDataScript (hzChain& J) { // Purpose: Build a HTML/JavaScript hierarchical tree. // // Generate data script for the tree. A data script for trees is always an array of treeitems which in turn comprise four values. These are the // level, a 0 or a 1 for either item/folder, the title and the URL (link to item). // // The data script is used in conjuction with the _dsmScript_navtree/makeTree script which uses the data script to effect the tree in HTML bu a series of // document.write operations. // // Arguments: 1) J The chain in which tree is being built // // Returns: E_NODATA If the tree is empty // E_OK If the tree is exported to the supplied chain
_hzfunc("hdsNavtree::ExportDataScript") ;
if (!this) hzexit(E_CORRUPT, "No instance") ;
if (!m_ItemsByName.Count()) return E_NODATA ;
hzString root ; // Blank start
J << "var ntX=new Array();\nntX=[" ;
_procTreeitem(J, root) ;
J << "\n\t];\n" ;
// threadLog("BEGIN NAV\n") ; // threadLog(J) ; // threadLog("ENDF NAV\n") ;
return E_OK ; }