3030#include " docparser.h"
3131#include " docnode.h"
3232#include " debug.h"
33+ #include " regex.h"
3334
3435inline QCString compileOptions (const QCString &def)
3536{
@@ -262,8 +263,18 @@ class LayoutParser
262263 }
263264 }
264265
265- void startLayout (const std::string &,const XMLHandlers::Attributes &)
266+ void startLayout (const std::string &,const XMLHandlers::Attributes &attrib )
266267 {
268+ // extract and store version number
269+ QCString version = XMLHandlers::value (attrib," version" );
270+ static const reg::Ex re (R"( (\d+)\.(\d+))" );
271+ reg::Match match;
272+ if (reg::match (version.view (),match,re))
273+ {
274+ m_majorVersion = atoi (match[1 ].str ().c_str ());
275+ m_minorVersion = atoi (match[2 ].str ().c_str ());
276+ // printf("layout version %d.%d\n",m_versionMajor,m_versionMinor);
277+ }
267278 }
268279
269280 void startNavIndex (const std::string &,const XMLHandlers::Attributes &)
@@ -689,6 +700,9 @@ class LayoutParser
689700 }
690701 }
691702
703+ int majorVersion () const { return m_majorVersion; }
704+ int minorVersion () const { return m_minorVersion; }
705+
692706 private:
693707 QCString m_scope;
694708 LayoutDocManager &m_layoutDocManager;
@@ -698,6 +712,8 @@ class LayoutParser
698712 bool m_visible = true ;
699713 static int m_userGroupCount;
700714 const XMLLocator *m_locator = nullptr ;
715+ int m_majorVersion = 1 ;
716+ int m_minorVersion = 0 ;
701717};
702718
703719// ---------------------------------------------------------------------------------
@@ -1384,6 +1400,8 @@ class LayoutDocManager::Private
13841400 public:
13851401 std::array<LayoutDocEntryList,LayoutDocManager::NrParts> docEntries;
13861402 LayoutNavEntry rootNav;
1403+ int majorVersion;
1404+ int minorVersion;
13871405};
13881406
13891407LayoutDocManager::LayoutDocManager () : d(std::make_unique<Private>())
@@ -1410,6 +1428,8 @@ void LayoutDocManager::init()
14101428 [&]() { DebugLex::print (Debug::Lex_xml," Finished" , " libxml/xml.l" ,layoutFile); }
14111429 );
14121430 removeInvisibleDocEntries ();
1431+ d->majorVersion = layoutParser.majorVersion ();
1432+ d->minorVersion = layoutParser.minorVersion ();
14131433}
14141434
14151435LayoutDocManager & LayoutDocManager::instance ()
@@ -1463,12 +1483,21 @@ void LayoutDocManager::parse(const QCString &fileName, const char *data)
14631483 [&]() { DebugLex::print (Debug::Lex_xml," Finished" , " libxml/xml.l" ,qPrint (fileName)); },
14641484 transcodeCharacterStringToUTF8
14651485 );
1466- // merge missing parts of the default layout into the user defined layout
14671486
1487+ // version in the user defined layout overrides default one
1488+ d->majorVersion = layoutParser.majorVersion ();
1489+ d->minorVersion = layoutParser.minorVersion ();
1490+
1491+ // merge missing parts of the default layout into the user defined layout
14681492 // For now merging in defaults has been disabled for navigation entries
14691493 // to avoid "extra entries" for projects that work with partial layout files.
14701494 // mergeNavEntries(layoutDocManager);
1471- mergeDocEntries (layoutDocManager);
1495+
1496+ // for compatibility reasons we only merge defaults when the user defined layout has at least version 2.0 or higher
1497+ if (d->majorVersion >=2 )
1498+ {
1499+ mergeDocEntries (fileName,layoutDocManager);
1500+ }
14721501
14731502 layoutDocManager.removeInvisibleDocEntries ();
14741503
@@ -1497,6 +1526,16 @@ void LayoutDocManager::removeInvisibleDocEntries()
14971526 }
14981527}
14991528
1529+ int LayoutDocManager::majorVersion () const
1530+ {
1531+ return d->majorVersion ;
1532+ }
1533+
1534+ int LayoutDocManager::minorVersion () const
1535+ {
1536+ return d->minorVersion ;
1537+ }
1538+
15001539// search for candidate node in tree with root target. Returns the match target node if found, or nullptr otherwise.
15011540static LayoutNavEntry *findNavEntryRec (LayoutNavEntry *root, const std::string &id)
15021541{
@@ -1596,7 +1635,7 @@ void LayoutDocManager::mergeNavEntries(LayoutDocManager &other)
15961635 mergeNavTreeNodesRec (other.rootNavEntry (),rootNavEntry ());
15971636}
15981637
1599- static void mergeDocEntryLists (LayoutDocEntryList &targetList,LayoutDocEntryList &sourceList)
1638+ static void mergeDocEntryLists (const QCString &fileName, LayoutDocEntryList &targetList,LayoutDocEntryList &sourceList)
16001639{
16011640 using IdSet = std::unordered_set<std::string>;
16021641 using IdMap = std::unordered_map<std::string,size_t >;
@@ -1672,18 +1711,19 @@ static void mergeDocEntryLists(LayoutDocEntryList &targetList,LayoutDocEntryList
16721711 {
16731712 // for efficiency we move the elements from the source list to the target list, thus modifying the source list!
16741713 // printf("--> insert at %zu before %s\n",*it,qPrint(*it<targetList.size()?targetList[*it]->id():"none"));
1714+ warn (fileName,1 ," User defined layout misses entry '%s'. Using default value." ,qPrint (id));
16751715 targetList.insert (targetList.begin ()+*it, std::move (sourceList[idx]));
16761716 }
16771717 }
16781718
16791719}
16801720
1681- void LayoutDocManager::mergeDocEntries (LayoutDocManager &other)
1721+ void LayoutDocManager::mergeDocEntries (const QCString &fileName, LayoutDocManager &other)
16821722{
16831723 for (size_t i=0 ; i<d->docEntries .size (); i++)
16841724 {
16851725 // printf("========= part %zu\n",i);
1686- mergeDocEntryLists (other.d ->docEntries [i],d->docEntries [i]);
1726+ mergeDocEntryLists (fileName, other.d ->docEntries [i],d->docEntries [i]);
16871727 }
16881728}
16891729
@@ -1760,6 +1800,70 @@ QCString LayoutDocEntryMemberDef::title(SrcLangExt lang) const
17601800 return extractLanguageSpecificTitle (m_title,lang);
17611801}
17621802
1803+ // ----------------------------------------------------------------------------------
1804+
1805+ static void printNavLayout (LayoutNavEntry *root,int indent)
1806+ {
1807+ if (Debug::isFlagSet (Debug::Layout))
1808+ {
1809+ QCString indentStr;
1810+ indentStr.fill (' ' ,indent);
1811+ Debug::print (Debug::Layout,0 ," %skind=%s visible=%d title='%s'\n " ,
1812+ indentStr.isEmpty ()?" " :qPrint (indentStr),
1813+ qPrint (root->navToString ()),
1814+ root->visible (),
1815+ qPrint (root->title ())
1816+ );
1817+ for (const auto &e : root->children ())
1818+ {
1819+ printNavLayout (e.get (),indent+2 );
1820+ }
1821+ }
1822+ }
1823+
1824+ void printLayout ()
1825+ {
1826+ bool extraIndent = false ;
1827+
1828+ auto &mgr = LayoutDocManager::instance ();
1829+ Debug::print (Debug::Layout,0 ," Layout version %d.%d\n " ,mgr.majorVersion (),mgr.minorVersion ());
1830+
1831+ Debug::print (Debug::Layout,0 ," Part: Navigation index\n " );
1832+ for (const auto &e : mgr.rootNavEntry ()->children ())
1833+ {
1834+ printNavLayout (e.get (),2 );
1835+ }
1836+
1837+ for (int i = 0 ; i < LayoutDocManager::NrParts; i++)
1838+ {
1839+ Debug::print (Debug::Layout,0 ," \n Part: %s\n " , qPrint (LayoutDocManager::partToString (i)));
1840+ for (const auto &lde : mgr.docEntries (static_cast <LayoutDocManager::LayoutPart>(i)))
1841+ {
1842+ if (const LayoutDocEntrySimple *ldes = dynamic_cast <const LayoutDocEntrySimple*>(lde.get ()))
1843+ {
1844+ if (lde->kind () == LayoutDocEntry::MemberDeclEnd || lde->kind () == LayoutDocEntry::MemberDefEnd) extraIndent = false ;
1845+ Debug::print (Debug::Layout,0 ," %skind: %s, visible=%d\n " ,
1846+ extraIndent? " " : " " ,qPrint (lde->entryToString ()), ldes->visible ());
1847+ if (lde->kind () == LayoutDocEntry::MemberDeclStart || lde->kind () == LayoutDocEntry::MemberDefStart) extraIndent = true ;
1848+ }
1849+ else if (const LayoutDocEntryMemberDecl *lmdecl = dynamic_cast <const LayoutDocEntryMemberDecl*>(lde.get ()))
1850+ {
1851+ Debug::print (Debug::Layout,0 ," %scomplex kind: %s, visible=%d, type: %s\n " ,
1852+ extraIndent? " " : " " ,qPrint (lde->entryToString ()),lmdecl->visible (),qPrint (lmdecl->type .to_string ()));
1853+ }
1854+ else if (const LayoutDocEntryMemberDef *lmdef = dynamic_cast <const LayoutDocEntryMemberDef*>(lde.get ()))
1855+ {
1856+ Debug::print (Debug::Layout,0 ," %scomplex kind: %s, visible=%d, type: %s\n " ,
1857+ extraIndent? " " : " " ,qPrint (lde->entryToString ()),lmdef->visible (),qPrint (lmdef->type .to_string ()));
1858+ }
1859+ else
1860+ {
1861+ // should not happen
1862+ Debug::print (Debug::Layout,0 ," %snot handled kind: %s\n " ,extraIndent? " " : " " ,qPrint (lde->entryToString ()));
1863+ }
1864+ }
1865+ }
1866+ }
17631867
17641868
17651869
0 commit comments