31#include <QApplication>
34#include <QDomDocument>
37#include <QRegularExpression>
42#include "moc_qgscptcityarchive.cpp"
44using namespace Qt::StringLiterals;
60 return *sArchiveRegistry();
71 const auto constEntryList = QDir( mBaseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name );
72 for (
const QString &path : constEntryList )
74 if ( path ==
"selections"_L1 )
79 mRootItems << dirItem;
86 const QDir seldir( mBaseDir +
'/' +
"selections" );
88 const QStringList fileList = seldir.entryList( QStringList() << u
"*.xml"_s, QDir::Files );
89 for (
const QString &selfile : fileList )
92 selItem =
new QgsCptCitySelectionItem(
nullptr, QFileInfo( selfile ).baseName(), seldir.dirName() +
'/' + selfile );
95 mSelectionItems << selItem;
103 mRootItems.prepend( allRampsItem );
105 mSelectionItems.prepend( allRampsItem );
110 const auto constMRootItems = mRootItems;
113 const auto constMSelectionItems = mSelectionItems;
117 mSelectionItems.clear();
124 if ( !mBaseDir.isNull() )
136 return archive->baseDir();
158 if ( startDir.isEmpty() || !startDir.startsWith(
baseDir ) )
161 QDir dir = QDir( startDir );
163 while ( !dir.exists( target ) && dir.path() !=
baseDir )
168 if ( !dir.exists( target ) )
171 return dir.path() +
'/' + target;
189 if ( fileName.isNull() )
192 if ( sCopyingInfoMap()->contains( fileName ) )
194 QgsDebugMsgLevel(
"found copying info in copyingInfoMap, file = " + fileName, 2 );
195 return sCopyingInfoMap()->value( fileName );
202 if ( !f.open( QFile::ReadOnly ) )
209 QDomDocument doc( u
"license"_s );
210 if ( !doc.setContent( &f ) )
219 const QDomElement docElem = doc.documentElement();
220 if ( docElem.tagName() !=
"copying"_L1 )
227 const QDomElement authorsElement = docElem.firstChildElement( u
"authors"_s );
228 if ( authorsElement.isNull() )
234 QDomElement e = authorsElement.firstChildElement();
236 while ( !e.isNull() )
238 if ( e.tagName() ==
"author"_L1 )
240 if ( !e.firstChildElement( u
"name"_s ).isNull() )
241 authors << e.firstChildElement( u
"name"_s ).text().simplified();
244 e = e.nextSiblingElement();
246 copyingMap[u
"authors"_s] = authors.join(
", "_L1 );
250 const QDomElement licenseElement = docElem.firstChildElement( u
"license"_s );
251 if ( licenseElement.isNull() )
257 QDomElement e = licenseElement.firstChildElement( u
"informal"_s );
259 copyingMap[u
"license/informal"_s] = e.text().simplified();
260 e = licenseElement.firstChildElement( u
"year"_s );
262 copyingMap[u
"license/year"_s] = e.text().simplified();
263 e = licenseElement.firstChildElement( u
"text"_s );
264 if ( !e.isNull() && e.attribute( u
"href"_s ) != QString() )
265 copyingMap[u
"license/url"_s] = e.attribute( u
"href"_s );
269 const QDomElement element = docElem.firstChildElement( u
"src"_s );
270 if ( element.isNull() )
276 const QDomElement e = element.firstChildElement( u
"link"_s );
277 if ( !e.isNull() && e.attribute( u
"href"_s ) != QString() )
278 copyingMap[u
"src/link"_s] = e.attribute( u
"href"_s );
282 ( *sCopyingInfoMap() )[fileName] = copyingMap;
293 if ( !f.open( QFile::ReadOnly ) )
295 QgsDebugMsgLevel(
"description file " + fileName +
" ] does not exist", 2 );
301 QDomDocument doc( u
"description"_s );
302 if ( !doc.setContent( &f, &errMsg ) )
305 QgsDebugError(
"Couldn't parse file " + fileName +
" : " + errMsg );
311 const QDomElement docElem = doc.documentElement();
312 if ( docElem.tagName() !=
"description"_L1 )
319 QDomElement e = docElem.firstChildElement( u
"name"_s );
324 descMap[u
"name"_s] = e.text().simplified();
325 e = docElem.firstChildElement( u
"full"_s );
330 descMap[u
"full"_s] = e.text().simplified();
337 QMap< double, QPair<QColor, QColor> > colorMap;
341 if ( !f.open( QFile::ReadOnly ) )
348 QDomDocument doc( u
"gradient"_s );
349 if ( !doc.setContent( &f ) )
357 const QDomElement docElem = doc.documentElement();
359 if ( docElem.tagName() !=
"svg"_L1 )
366 QDomElement rampsElement = docElem.firstChildElement( u
"linearGradient"_s );
367 if ( rampsElement.isNull() )
369 const QDomNodeList nodeList = docElem.elementsByTagName( u
"linearGradient"_s );
370 if ( !nodeList.isEmpty() )
371 rampsElement = nodeList.at( 0 ).toElement();
373 if ( rampsElement.isNull() )
380 QDomElement e = rampsElement.firstChildElement();
382 while ( !e.isNull() )
384 if ( e.tagName() ==
"stop"_L1 )
388 QString offsetStr = e.attribute( u
"offset"_s );
389 const QString colorStr = e.attribute( u
"stop-color"_s, QString() );
390 const QString opacityStr = e.attribute( u
"stop-opacity"_s, u
"1.0"_s );
391 if ( offsetStr.endsWith(
'%' ) )
392 offset = offsetStr.remove( offsetStr.size() - 1, 1 ).toDouble() / 100.0;
394 offset = offsetStr.toDouble();
397 if ( colorStr.isEmpty() )
400 color = QColor( 0, 0, 0 );
407 if ( color.isValid() )
409 const int alpha = opacityStr.toDouble() * 255;
410 color.setAlpha( alpha );
411 if ( colorMap.contains( offset ) )
412 colorMap[offset].second = color;
414 colorMap[offset] = qMakePair( color, color );
418 QgsDebugError( u
"at offset=%1 invalid color \"%2\""_s.arg( offset ).arg( colorStr ) );
426 e = e.nextSiblingElement();
434 return ( mRootItems.isEmpty() );
441 if ( sArchiveRegistry()->contains( *sDefaultArchiveName() ) )
442 return sArchiveRegistry()->value( *sDefaultArchiveName() );
465 if ( !sArchiveRegistry()->contains( defArchiveName ) )
472 QString
baseDir, defArchiveName;
485 const QStringList fileList = dir.entryList( QStringList() << u
"cpt-city*"_s, QDir::Dirs );
486 for (
const QString &entry : fileList )
488 if ( QFile::exists(
baseDir +
'/' + entry +
"/VERSION.xml" ) )
489 archivesMap[entry] =
baseDir +
'/' + entry;
494 archivesMap[defArchiveName] =
baseDir +
'/' + defArchiveName;
497 for ( QgsStringMap::iterator it = archivesMap.begin(); it != archivesMap.end(); ++it )
499 if ( QDir( it.value() ).exists() )
503 QgsDebugError( u
"not loading archive [%1] because dir %2 does not exist "_s.arg( it.key(), it.value() ) );
506 *sDefaultArchiveName() = defArchiveName;
511 qDeleteAll( *sArchiveRegistry() );
512 sArchiveRegistry()->clear();
528 QVector<QgsCptCityDataItem *>
children;
539 QApplication::setOverrideCursor( Qt::WaitCursor );
542 const auto constChildren =
children;
550 QApplication::restoreOverrideCursor();
570 count += child->leafCount();
599 if (
mChildren.at( i )->mName.localeAwareCompare( child->
mName ) >= 0 )
620 const int i =
mChildren.indexOf( child );
631 const int i =
mChildren.indexOf( child );
646 for (
int i = 0; i < items.size(); i++ )
649 if ( items[i]->
equal( item ) )
659 QApplication::setOverrideCursor( Qt::WaitCursor );
664 QVector<QgsCptCityDataItem *> remove;
668 if (
findItem( items, child ) >= 0 )
670 remove.append( child );
672 const auto constRemove = remove;
679 const auto constItems = items;
691 QApplication::restoreOverrideCursor();
696 return ( metaObject()->className() == other->metaObject()->className() &&
mPath == other->
path() );
715 ,
mRamp(
path, variantList, QString(), false )
733 QStringList variantList =
mRamp.variantList();
734 if (
mRamp.variantName().isNull() && !variantList.isEmpty() )
735 mRamp.setVariantName( variantList[variantList.count() / 2] );
740 if ( !QFile::exists(
mRamp.fileName() ) )
746 if (
mRamp.count() > 0 )
748 if ( variantList.isEmpty() )
750 int count =
mRamp.count();
751 if (
mRamp.isDiscrete() )
753 mInfo = QString::number( count ) +
' ' + tr(
"colors" ) +
" - ";
754 if (
mRamp.isDiscrete() )
755 mInfo += tr(
"discrete" );
758 if ( !
mRamp.hasMultiStops() )
759 mInfo += tr(
"continuous" );
761 mInfo += tr(
"continuous (multi)" );
767 mInfo = QString::number( variantList.count() ) +
' ' + tr(
"variants" );
792 return icon( QSize( 100, 15 ) );
797 const auto constMIcons =
mIcons;
798 for (
const QIcon &
icon : constMIcons )
800 if (
icon.availableSizes().contains( size ) )
814 QPixmap blankPixmap( size );
815 blankPixmap.fill( Qt::white );
816 icon = QIcon( blankPixmap );
836 QVector< QgsCptCityDataItem * > rampItems;
837 QVector< QgsCptCityDataItem * > deleteItems;
842 const auto constChildren =
children();
847 QgsDebugMsgLevel( u
"child path= %1 coll= %2 ramp = %3"_s.arg( childItem->path() ).arg(
nullptr != collectionItem ).arg(
nullptr != rampItem ), 2 );
848 if ( collectionItem && recursive )
858 rampItems << rampItem;
860 deleteItems << rampItem;
869 const auto constDeleteItems = deleteItems;
872 QgsDebugError( u
"item %1 is invalid, will be deleted"_s.arg( deleteItem->path() ) );
873 const int i =
mChildren.indexOf( deleteItem );
897 if ( descMap.contains( u
"name"_s ) )
898 mInfo = descMap.value( u
"name"_s );
906 return QVector<QgsCptCityDataItem *>();
908 QVector<QgsCptCityDataItem *>
children;
911 QMapIterator< QString, QStringList> it(
rampsMap() );
912 while ( it.hasNext() )
925 for (
const QString &childPath : constDirEntries )
942 QString curName, prevName, curVariant, curSep, schemeName;
943 QStringList listVariant;
944 QStringList schemeNamesAll, schemeNames;
945 bool prevAdd, curAdd;
948 schemeNamesAll = dir.entryList( QStringList( u
"*.svg"_s ), QDir::Files, QDir::Name );
951 for (
int i = 0; i < schemeNamesAll.count(); i++ )
954 schemeName = schemeNamesAll[i];
955 schemeName.chop( 4 );
957 curName = schemeName;
962 if ( schemeName.length() > 1 && schemeName.endsWith(
'a' ) && !listVariant.isEmpty() && ( ( prevName + listVariant.last() +
'a' ) == curName ) )
965 curVariant = listVariant.last() +
'a';
969 const thread_local QRegularExpression rxVariant(
"^(.*[^\\d])(\\d{1,3})$" );
970 const QRegularExpressionMatch match = rxVariant.match( schemeName );
971 if ( match.hasMatch() )
973 curName = match.captured( 1 );
974 curVariant = match.captured( 2 );
978 curSep = curName.right( 1 );
979 if ( curSep ==
"-"_L1 || curSep ==
"_"_L1 )
982 curVariant = curSep + curVariant;
985 if ( prevName.isEmpty() )
991 if ( curName.isEmpty() )
992 curName = u
"__empty__"_s;
994 if ( curName == prevName )
997 if ( i == schemeNamesAll.count() - 1 )
999 listVariant << curVariant;
1003 if ( !prevName.isEmpty() )
1008 if ( i == schemeNamesAll.count() - 1 )
1017 if ( listVariant.isEmpty() )
1021 schemeNames << prevName;
1024 else if ( listVariant.count() <= 3 )
1027 for (
int j = 0; j < listVariant.count(); j++ )
1030 schemeNames << prevName + listVariant[j];
1031 mRampsMap[
mPath +
'/' + prevName + listVariant[j]] = QStringList();
1038 schemeNames << prevName;
1040 listVariant.clear();
1044 if ( !curVariant.isEmpty() )
1045 curName += curVariant;
1046 schemeNames << curName;
1050 if ( prevAdd || curAdd )
1053 if ( !curVariant.isEmpty() )
1054 listVariant << curVariant;
1060 mSchemeMap[
path ] = schemeNames;
1061 schemeCount += schemeName.count();
1062 schemeNames.clear();
1063 listVariant.clear();
1081 return (
path() == other->
path() );
1090 if ( dirItem && !dirItem->
isValid() )
1144 return QVector<QgsCptCityDataItem *>();
1147 QVector<QgsCptCityDataItem *>
children;
1154 QgsDebugMsgLevel(
"childPath = " + childPath +
" name= " + QFileInfo( childPath ).baseName(), 2 );
1155 if ( childPath.endsWith(
'/' ) )
1157 childPath.chop( 1 );
1170 if ( !QFile::exists( fileName ) )
1194 QFile f( filename );
1195 if ( !f.open( QFile::ReadOnly ) )
1203 QDomDocument doc( u
"selection"_s );
1204 if ( !doc.setContent( &f, &errMsg ) )
1207 QgsDebugError(
"Couldn't parse file " + filename +
" : " + errMsg );
1213 const QDomElement docElem = doc.documentElement();
1214 if ( docElem.tagName() !=
"selection"_L1 )
1216 QgsDebugError(
"Incorrect root tag: " + docElem.tagName() );
1219 QDomElement e = docElem.firstChildElement( u
"name"_s );
1220 if ( !e.isNull() && !e.text().isNull() )
1222 mInfo = docElem.firstChildElement( u
"synopsis"_s ).text().simplified();
1225 const QDomElement collectsElem = docElem.firstChildElement( u
"seealsocollects"_s );
1226 e = collectsElem.firstChildElement( u
"collect"_s );
1227 while ( !e.isNull() )
1229 if ( !e.attribute( u
"dir"_s ).isNull() )
1232 const QString dir = e.attribute( u
"dir"_s ) +
'/';
1238 e = e.nextSiblingElement();
1241 const QDomElement gradientsElem = docElem.firstChildElement( u
"gradients"_s );
1242 e = gradientsElem.firstChildElement( u
"gradient"_s );
1243 while ( !e.isNull() )
1245 if ( !e.attribute( u
"dir"_s ).isNull() )
1249 const QString dir = e.attribute( u
"dir"_s );
1255 e = e.nextSiblingElement();
1266 return (
path() == other->
path() );
1282 return QVector<QgsCptCityDataItem *>();
1284 QVector<QgsCptCityDataItem *>
children;
1287 const auto constMItems =
mItems;
1301 : QAbstractItemModel(
parent )
1306 QgsDebugMsgLevel(
"archiveName = "_L1 + archive->
archiveName() +
" viewType=" + QString::number(
static_cast< int >( viewType ) ), 2 );
1337 if ( !
index.isValid() )
1338 return Qt::ItemFlags();
1340 Qt::ItemFlags
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
1347 if ( !
index.isValid() )
1356 else if ( role == Qt::DisplayRole )
1358 if (
index.column() == 0 )
1359 return item->
name();
1360 if (
index.column() == 1 )
1362 return item->
info();
1365 else if ( role == Qt::ToolTipRole )
1368 return QString( item->
path() +
'\n' + item->
info() );
1376 else if ( role == Qt::FontRole && qobject_cast< QgsCptCityCollectionItem * >( item ) )
1380 font.setPointSize( 11 );
1381 font.setBold(
true );
1395 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
1398 return QVariant( tr(
"Name" ) );
1399 else if ( section == 1 )
1400 return QVariant( tr(
"Info" ) );
1418 return item ? item->
rowCount() : 0;
1440 QModelIndex rootIndex;
1441 bool foundParent =
false, foundChild =
true;
1447 if ( path.isEmpty() )
1449 for (
int i = 0; i <
rowCount( rootIndex ); i++ )
1451 QModelIndex idx =
index( i, 0, rootIndex );
1454 return QModelIndex();
1456 itemPath = item->
path();
1458 if ( itemPath == path )
1466 while ( foundChild )
1472 if ( itemPath.isEmpty() )
1474 for ( ; i <
rowCount( rootIndex ); i++ )
1476 QModelIndex idx =
index( i, 0, rootIndex );
1479 return QModelIndex();
1481 itemPath = item->
path();
1483 if ( itemPath == path )
1489 if ( !itemPath.endsWith(
'/' ) )
1492 foundParent =
false;
1503 for ( QString childPath : constSelectionsList )
1505 if ( childPath.endsWith(
'/' ) )
1506 childPath.chop( 1 );
1508 if ( path.startsWith( childPath ) )
1517 else if ( path.startsWith( itemPath ) )
1535 return QModelIndex();
1549 const QModelIndex idx =
findPath( path );
1550 if ( idx.isValid() )
1563 return item ? createIndex( row, column, item ) : QModelIndex();
1570 return QModelIndex();
1579 for (
int i = 0; i < items.size(); i++ )
1581 if ( items[i] == item )
1582 return createIndex( i, 0, item );
1584 QModelIndex childIndex =
findItem( item, items[i] );
1585 if ( childIndex.isValid() )
1589 return QModelIndex();
1607 if ( !idx.isValid() )
1610 beginInsertRows( idx, first, last );
1621 if ( !idx.isValid() )
1623 beginRemoveRows( idx, first, last );
1667 void *v = idx.internalPointer();
1669 Q_ASSERT( !v || d );
static QString pkgDataPath()
Returns the common root path of all application data directories.
An "All ramps item", which contains all items in a flat hierarchy.
QgsCptCityAllRampsItem(QgsCptCityDataItem *parent, const QString &name, const QVector< QgsCptCityDataItem * > &items)
QVector< QgsCptCityDataItem * > mItems
QVector< QgsCptCityDataItem * > createChildren() override
Returns a vector of children items.
Represents a CPT City color scheme.
static void clearArchives()
static void initArchive(const QString &archiveName, const QString &archiveBaseDir)
QString descFileName(const QString &dirName) const
static QString defaultBaseDir()
static QMap< QString, QString > copyingInfo(const QString &fileName)
static const QgsSettingsEntryString * settingsCptCityArchiveName
QString archiveName() const
static QgsCptCityArchive * defaultArchive()
QString copyingFileName(const QString &dirName) const
bool isEmpty() const
Returns true if archive is empty.
static const QgsSettingsEntryString * settingsCptCityBaseDir
static void initDefaultArchive()
QgsCptCityArchive(const QString &archiveName=DEFAULT_CPTCITY_ARCHIVE, const QString &baseDir=QString())
static QString findFileName(const QString &target, const QString &startDir, const QString &baseDir)
static QMap< QString, QString > description(const QString &fileName)
static void initArchives(bool loadAll=false)
static QMap< QString, QgsCptCityArchive * > archiveRegistry()
static QMap< double, QPair< QColor, QColor > > gradientColorMap(const QString &fileName)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void refresh(const QString &path)
Refresh the item specified by path.
void beginRemoveItems(QgsCptCityDataItem *parent, int first, int last)
QModelIndex findPath(const QString &path)
Returns index of a path.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QgsCptCityDataItem * dataItem(const QModelIndex &idx) const
Returns the data item corresponding to the given index.
void reload()
Reload the whole model.
void connectItem(QgsCptCityDataItem *item)
QgsCptCityArchive * mArchive
QModelIndex parent(const QModelIndex &index) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QgsCptCityBrowserModel(QObject *parent=nullptr, QgsCptCityArchive *archive=QgsCptCityArchive::defaultArchive(), ViewType Type=Authors)
void beginInsertItems(QgsCptCityDataItem *parent, int first, int last)
void fetchMore(const QModelIndex &parent) override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
~QgsCptCityBrowserModel() override
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
bool canFetchMore(const QModelIndex &parent) const override
QModelIndex findItem(QgsCptCityDataItem *item, QgsCptCityDataItem *parent=nullptr) const
QVector< QgsCptCityDataItem * > mRootItems
~QgsCptCityCollectionItem() override
QgsCptCityCollectionItem(QgsCptCityDataItem *parent, const QString &name, const QString &path)
QVector< QgsCptCityDataItem * > childrenRamps(bool recursive)
An item that represents a layer that can be opened with one of the providers for a QgsCptCityBrowserM...
const QgsCptCityColorRamp & ramp() const
bool equal(const QgsCptCityDataItem *other) override
Returns true if this item is equal to an other item.
QgsCptCityColorRampItem(QgsCptCityDataItem *parent, const QString &name, const QString &path, const QString &variantName=QString(), bool initialize=false)
QgsCptCityColorRamp mRamp
static QString fileNameForVariant(const QString &schema, const QString &variant)
Returns the source file name for a CPT schema and variant.
QString variantName() const
Base class for all items in a QgsCptCityBrowserModel model.
QgsCptCityDataItem * parent() const
virtual void addChildItem(QgsCptCityDataItem *child, bool refresh=false)
Inserts a new child using alphabetical order based on mName, emits necessary signal to model before a...
void beginRemoveItems(QgsCptCityDataItem *parent, int first, int last)
Emitted before child items are removed from this data item.
virtual QVector< QgsCptCityDataItem * > createChildren()
Returns a vector of children items.
virtual QgsCptCityDataItem * removeChildItem(QgsCptCityDataItem *child)
Removes a child item but doesn't delete it, signals to browser are emitted.
void endRemoveItems()
Emitted after child items have been removed from this data item.
bool isPopulated()
Returns true if the item is already populated.
static int findItem(QVector< QgsCptCityDataItem * > items, QgsCptCityDataItem *item)
Finds a child index in vector of items using '==' operator.
QVector< QgsCptCityDataItem * > mChildren
void endInsertItems()
Emitted after child items have been added to this data item.
void setParent(QgsCptCityDataItem *parent)
virtual void populate()
Populates children using children vector created by createChildren().
virtual void deleteChildItem(QgsCptCityDataItem *child)
Removes and deletes a child item, signals to browser are emitted.
virtual bool equal(const QgsCptCityDataItem *other)
Returns true if this item is equal to an other item.
QgsCptCityDataItem * mParent
QgsCptCityDataItem(QgsCptCityDataItem::Type type, QgsCptCityDataItem *parent, const QString &name, const QString &path)
QVector< QgsCptCityDataItem * > children() const
void beginInsertItems(QgsCptCityDataItem *parent, int first, int last)
Emitted before child items are added to this item.
virtual int leafCount() const
Returns the total count of "leaf" items (all children which are end nodes).
A directory which contains subdirectories and color ramps for use in QgsCptCityBrowserModel.
QStringList dirEntries() const
static QgsCptCityDataItem * dataItem(QgsCptCityDataItem *parent, const QString &name, const QString &path)
QVector< QgsCptCityDataItem * > createChildren() override
Returns a vector of children items.
QgsCptCityDirectoryItem(QgsCptCityDataItem *parent, const QString &name, const QString &path)
QMap< QString, QStringList > mRampsMap
bool equal(const QgsCptCityDataItem *other) override
Returns true if this item is equal to an other item.
QMap< QString, QStringList > rampsMap()
A selection which contains subdirectories and color ramps for use in QgsCptCityBrowserModel.
QVector< QgsCptCityDataItem * > createChildren() override
Returns a vector of children items.
QgsCptCitySelectionItem(QgsCptCityDataItem *parent, const QString &name, const QString &path)
bool equal(const QgsCptCityDataItem *other) override
Returns true if this item is equal to an other item.
QStringList mSelectionsList
QStringList selectionsList() const
static QgsSettingsTreeNode * sTreeColors
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static QIcon colorRampPreviewIcon(QgsColorRamp *ramp, QSize size, int padding=0)
Returns an icon preview for a color ramp.
QMap< QString, QString > QgsStringMap
QMap< QString, QMap< QString, QString > > CopyingInfoMap
QMap< QString, QgsCptCityArchive * > ArchiveRegistry
#define DEFAULT_CPTCITY_ARCHIVE
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)