29#include <QApplication>
32#include <QDomDocument>
35#include <QRegularExpression>
40#include "moc_qgscptcityarchive.cpp"
42using namespace Qt::StringLiterals;
53 return *sArchiveRegistry();
64 const auto constEntryList = QDir( mBaseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name );
65 for (
const QString &path : constEntryList )
67 if ( path ==
"selections"_L1 )
72 mRootItems << dirItem;
79 const QDir seldir( mBaseDir +
'/' +
"selections" );
81 const QStringList fileList = seldir.entryList( QStringList() << u
"*.xml"_s, QDir::Files );
82 for (
const QString &selfile : fileList )
85 selItem =
new QgsCptCitySelectionItem(
nullptr, QFileInfo( selfile ).baseName(), seldir.dirName() +
'/' + selfile );
88 mSelectionItems << selItem;
96 mRootItems.prepend( allRampsItem );
98 mSelectionItems.prepend( allRampsItem );
103 const auto constMRootItems = mRootItems;
106 const auto constMSelectionItems = mSelectionItems;
110 mSelectionItems.clear();
117 if ( !mBaseDir.isNull() )
129 return archive->baseDir();
152 if ( startDir.isEmpty() || !startDir.startsWith(
baseDir ) )
155 QDir dir = QDir( startDir );
157 while ( !dir.exists( target ) && dir.path() !=
baseDir )
162 if ( !dir.exists( target ) )
165 return dir.path() +
'/' + target;
183 if ( fileName.isNull() )
186 if ( sCopyingInfoMap()->contains( fileName ) )
188 QgsDebugMsgLevel(
"found copying info in copyingInfoMap, file = " + fileName, 2 );
189 return sCopyingInfoMap()->value( fileName );
196 if ( !f.open( QFile::ReadOnly ) )
203 QDomDocument doc( u
"license"_s );
204 if ( !doc.setContent( &f ) )
213 const QDomElement docElem = doc.documentElement();
214 if ( docElem.tagName() !=
"copying"_L1 )
221 const QDomElement authorsElement = docElem.firstChildElement( u
"authors"_s );
222 if ( authorsElement.isNull() )
228 QDomElement e = authorsElement.firstChildElement();
230 while ( !e.isNull() )
232 if ( e.tagName() ==
"author"_L1 )
234 if ( !e.firstChildElement( u
"name"_s ).isNull() )
235 authors << e.firstChildElement( u
"name"_s ).text().simplified();
238 e = e.nextSiblingElement();
240 copyingMap[u
"authors"_s] = authors.join(
", "_L1 );
244 const QDomElement licenseElement = docElem.firstChildElement( u
"license"_s );
245 if ( licenseElement.isNull() )
251 QDomElement e = licenseElement.firstChildElement( u
"informal"_s );
253 copyingMap[u
"license/informal"_s] = e.text().simplified();
254 e = licenseElement.firstChildElement( u
"year"_s );
256 copyingMap[u
"license/year"_s] = e.text().simplified();
257 e = licenseElement.firstChildElement( u
"text"_s );
258 if ( !e.isNull() && e.attribute( u
"href"_s ) != QString() )
259 copyingMap[u
"license/url"_s] = e.attribute( u
"href"_s );
263 const QDomElement element = docElem.firstChildElement( u
"src"_s );
264 if ( element.isNull() )
270 const QDomElement e = element.firstChildElement( u
"link"_s );
271 if ( !e.isNull() && e.attribute( u
"href"_s ) != QString() )
272 copyingMap[u
"src/link"_s] = e.attribute( u
"href"_s );
276 ( *sCopyingInfoMap() )[fileName] = copyingMap;
287 if ( !f.open( QFile::ReadOnly ) )
289 QgsDebugMsgLevel(
"description file " + fileName +
" ] does not exist", 2 );
295 QDomDocument doc( u
"description"_s );
296 if ( !doc.setContent( &f, &errMsg ) )
299 QgsDebugError(
"Couldn't parse file " + fileName +
" : " + errMsg );
305 const QDomElement docElem = doc.documentElement();
306 if ( docElem.tagName() !=
"description"_L1 )
313 QDomElement e = docElem.firstChildElement( u
"name"_s );
318 descMap[u
"name"_s] = e.text().simplified();
319 e = docElem.firstChildElement( u
"full"_s );
324 descMap[u
"full"_s] = e.text().simplified();
331 QMap< double, QPair<QColor, QColor> > colorMap;
335 if ( !f.open( QFile::ReadOnly ) )
342 QDomDocument doc( u
"gradient"_s );
343 if ( !doc.setContent( &f ) )
351 const QDomElement docElem = doc.documentElement();
353 if ( docElem.tagName() !=
"svg"_L1 )
360 QDomElement rampsElement = docElem.firstChildElement( u
"linearGradient"_s );
361 if ( rampsElement.isNull() )
363 const QDomNodeList nodeList = docElem.elementsByTagName( u
"linearGradient"_s );
364 if ( !nodeList.isEmpty() )
365 rampsElement = nodeList.at( 0 ).toElement();
367 if ( rampsElement.isNull() )
374 QDomElement e = rampsElement.firstChildElement();
376 while ( !e.isNull() )
378 if ( e.tagName() ==
"stop"_L1 )
382 QString offsetStr = e.attribute( u
"offset"_s );
383 const QString colorStr = e.attribute( u
"stop-color"_s, QString() );
384 const QString opacityStr = e.attribute( u
"stop-opacity"_s, u
"1.0"_s );
385 if ( offsetStr.endsWith(
'%' ) )
386 offset = offsetStr.remove( offsetStr.size() - 1, 1 ).toDouble() / 100.0;
388 offset = offsetStr.toDouble();
391 if ( colorStr.isEmpty() )
394 color = QColor( 0, 0, 0 );
401 if ( color.isValid() )
403 const int alpha = opacityStr.toDouble() * 255;
404 color.setAlpha( alpha );
405 if ( colorMap.contains( offset ) )
406 colorMap[offset].second = color;
408 colorMap[offset] = qMakePair( color, color );
412 QgsDebugError( u
"at offset=%1 invalid color \"%2\""_s.arg( offset ).arg( colorStr ) );
420 e = e.nextSiblingElement();
428 return ( mRootItems.isEmpty() );
436 if ( sArchiveRegistry()->contains( *sDefaultArchiveName() ) )
437 return sArchiveRegistry()->value( *sDefaultArchiveName() );
459 if ( !sArchiveRegistry()->contains( defArchiveName ) )
466 QString
baseDir, defArchiveName;
478 const QStringList fileList = dir.entryList( QStringList() << u
"cpt-city*"_s, QDir::Dirs );
479 for (
const QString &entry : fileList )
481 if ( QFile::exists(
baseDir +
'/' + entry +
"/VERSION.xml" ) )
482 archivesMap[entry] =
baseDir +
'/' + entry;
487 archivesMap[defArchiveName] =
baseDir +
'/' + defArchiveName;
490 for ( QgsStringMap::iterator it = archivesMap.begin(); it != archivesMap.end(); ++it )
492 if ( QDir( it.value() ).exists() )
496 QgsDebugError( u
"not loading archive [%1] because dir %2 does not exist "_s.arg( it.key(), it.value() ) );
499 *sDefaultArchiveName() = defArchiveName;
504 qDeleteAll( *sArchiveRegistry() );
505 sArchiveRegistry()->clear();
521 QVector<QgsCptCityDataItem *>
children;
532 QApplication::setOverrideCursor( Qt::WaitCursor );
535 const auto constChildren =
children;
543 QApplication::restoreOverrideCursor();
563 count += child->leafCount();
592 if (
mChildren.at( i )->mName.localeAwareCompare( child->
mName ) >= 0 )
613 const int i =
mChildren.indexOf( child );
624 const int i =
mChildren.indexOf( child );
639 for (
int i = 0; i < items.size(); i++ )
642 if ( items[i]->
equal( item ) )
652 QApplication::setOverrideCursor( Qt::WaitCursor );
657 QVector<QgsCptCityDataItem *> remove;
661 if (
findItem( items, child ) >= 0 )
663 remove.append( child );
665 const auto constRemove = remove;
672 const auto constItems = items;
684 QApplication::restoreOverrideCursor();
689 return ( metaObject()->className() == other->metaObject()->className() &&
mPath == other->
path() );
708 ,
mRamp(
path, variantList, QString(), false )
726 QStringList variantList =
mRamp.variantList();
727 if (
mRamp.variantName().isNull() && !variantList.isEmpty() )
728 mRamp.setVariantName( variantList[variantList.count() / 2] );
733 if ( !QFile::exists(
mRamp.fileName() ) )
739 if (
mRamp.count() > 0 )
741 if ( variantList.isEmpty() )
743 int count =
mRamp.count();
744 if (
mRamp.isDiscrete() )
746 mInfo = QString::number( count ) +
' ' + tr(
"colors" ) +
" - ";
747 if (
mRamp.isDiscrete() )
748 mInfo += tr(
"discrete" );
751 if ( !
mRamp.hasMultiStops() )
752 mInfo += tr(
"continuous" );
754 mInfo += tr(
"continuous (multi)" );
760 mInfo = QString::number( variantList.count() ) +
' ' + tr(
"variants" );
785 return icon( QSize( 100, 15 ) );
790 const auto constMIcons =
mIcons;
791 for (
const QIcon &
icon : constMIcons )
793 if (
icon.availableSizes().contains( size ) )
807 QPixmap blankPixmap( size );
808 blankPixmap.fill( Qt::white );
809 icon = QIcon( blankPixmap );
829 QVector< QgsCptCityDataItem * > rampItems;
830 QVector< QgsCptCityDataItem * > deleteItems;
835 const auto constChildren =
children();
840 QgsDebugMsgLevel( u
"child path= %1 coll= %2 ramp = %3"_s.arg( childItem->path() ).arg(
nullptr != collectionItem ).arg(
nullptr != rampItem ), 2 );
841 if ( collectionItem && recursive )
851 rampItems << rampItem;
853 deleteItems << rampItem;
862 const auto constDeleteItems = deleteItems;
865 QgsDebugError( u
"item %1 is invalid, will be deleted"_s.arg( deleteItem->path() ) );
866 const int i =
mChildren.indexOf( deleteItem );
890 if ( descMap.contains( u
"name"_s ) )
891 mInfo = descMap.value( u
"name"_s );
899 return QVector<QgsCptCityDataItem *>();
901 QVector<QgsCptCityDataItem *>
children;
904 QMapIterator< QString, QStringList> it(
rampsMap() );
905 while ( it.hasNext() )
918 for (
const QString &childPath : constDirEntries )
935 QString curName, prevName, curVariant, curSep, schemeName;
936 QStringList listVariant;
937 QStringList schemeNamesAll, schemeNames;
938 bool prevAdd, curAdd;
941 schemeNamesAll = dir.entryList( QStringList( u
"*.svg"_s ), QDir::Files, QDir::Name );
944 for (
int i = 0; i < schemeNamesAll.count(); i++ )
947 schemeName = schemeNamesAll[i];
948 schemeName.chop( 4 );
950 curName = schemeName;
955 if ( schemeName.length() > 1 && schemeName.endsWith(
'a' ) && !listVariant.isEmpty() && ( ( prevName + listVariant.last() +
'a' ) == curName ) )
958 curVariant = listVariant.last() +
'a';
962 const thread_local QRegularExpression rxVariant(
"^(.*[^\\d])(\\d{1,3})$" );
963 const QRegularExpressionMatch match = rxVariant.match( schemeName );
964 if ( match.hasMatch() )
966 curName = match.captured( 1 );
967 curVariant = match.captured( 2 );
971 curSep = curName.right( 1 );
972 if ( curSep ==
"-"_L1 || curSep ==
"_"_L1 )
975 curVariant = curSep + curVariant;
978 if ( prevName.isEmpty() )
984 if ( curName.isEmpty() )
985 curName = u
"__empty__"_s;
987 if ( curName == prevName )
990 if ( i == schemeNamesAll.count() - 1 )
992 listVariant << curVariant;
996 if ( !prevName.isEmpty() )
1001 if ( i == schemeNamesAll.count() - 1 )
1010 if ( listVariant.isEmpty() )
1014 schemeNames << prevName;
1017 else if ( listVariant.count() <= 3 )
1020 for (
int j = 0; j < listVariant.count(); j++ )
1023 schemeNames << prevName + listVariant[j];
1024 mRampsMap[
mPath +
'/' + prevName + listVariant[j]] = QStringList();
1031 schemeNames << prevName;
1033 listVariant.clear();
1037 if ( !curVariant.isEmpty() )
1038 curName += curVariant;
1039 schemeNames << curName;
1043 if ( prevAdd || curAdd )
1046 if ( !curVariant.isEmpty() )
1047 listVariant << curVariant;
1053 mSchemeMap[
path ] = schemeNames;
1054 schemeCount += schemeName.count();
1055 schemeNames.clear();
1056 listVariant.clear();
1074 return (
path() == other->
path() );
1083 if ( dirItem && !dirItem->
isValid() )
1137 return QVector<QgsCptCityDataItem *>();
1140 QVector<QgsCptCityDataItem *>
children;
1147 QgsDebugMsgLevel(
"childPath = " + childPath +
" name= " + QFileInfo( childPath ).baseName(), 2 );
1148 if ( childPath.endsWith(
'/' ) )
1150 childPath.chop( 1 );
1163 if ( !QFile::exists( fileName ) )
1187 QFile f( filename );
1188 if ( !f.open( QFile::ReadOnly ) )
1196 QDomDocument doc( u
"selection"_s );
1197 if ( !doc.setContent( &f, &errMsg ) )
1200 QgsDebugError(
"Couldn't parse file " + filename +
" : " + errMsg );
1206 const QDomElement docElem = doc.documentElement();
1207 if ( docElem.tagName() !=
"selection"_L1 )
1209 QgsDebugError(
"Incorrect root tag: " + docElem.tagName() );
1212 QDomElement e = docElem.firstChildElement( u
"name"_s );
1213 if ( !e.isNull() && !e.text().isNull() )
1215 mInfo = docElem.firstChildElement( u
"synopsis"_s ).text().simplified();
1218 const QDomElement collectsElem = docElem.firstChildElement( u
"seealsocollects"_s );
1219 e = collectsElem.firstChildElement( u
"collect"_s );
1220 while ( !e.isNull() )
1222 if ( !e.attribute( u
"dir"_s ).isNull() )
1225 const QString dir = e.attribute( u
"dir"_s ) +
'/';
1231 e = e.nextSiblingElement();
1234 const QDomElement gradientsElem = docElem.firstChildElement( u
"gradients"_s );
1235 e = gradientsElem.firstChildElement( u
"gradient"_s );
1236 while ( !e.isNull() )
1238 if ( !e.attribute( u
"dir"_s ).isNull() )
1242 const QString dir = e.attribute( u
"dir"_s );
1248 e = e.nextSiblingElement();
1259 return (
path() == other->
path() );
1275 return QVector<QgsCptCityDataItem *>();
1277 QVector<QgsCptCityDataItem *>
children;
1280 const auto constMItems =
mItems;
1294 : QAbstractItemModel(
parent )
1299 QgsDebugMsgLevel(
"archiveName = "_L1 + archive->
archiveName() +
" viewType=" + QString::number(
static_cast< int >( viewType ) ), 2 );
1330 if ( !
index.isValid() )
1331 return Qt::ItemFlags();
1333 Qt::ItemFlags
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
1340 if ( !
index.isValid() )
1349 else if ( role == Qt::DisplayRole )
1351 if (
index.column() == 0 )
1352 return item->
name();
1353 if (
index.column() == 1 )
1355 return item->
info();
1358 else if ( role == Qt::ToolTipRole )
1361 return QString( item->
path() +
'\n' + item->
info() );
1369 else if ( role == Qt::FontRole && qobject_cast< QgsCptCityCollectionItem * >( item ) )
1373 font.setPointSize( 11 );
1374 font.setBold(
true );
1388 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
1391 return QVariant( tr(
"Name" ) );
1392 else if ( section == 1 )
1393 return QVariant( tr(
"Info" ) );
1411 return item ? item->
rowCount() : 0;
1433 QModelIndex rootIndex;
1434 bool foundParent =
false, foundChild =
true;
1440 if ( path.isEmpty() )
1442 for (
int i = 0; i <
rowCount( rootIndex ); i++ )
1444 QModelIndex idx =
index( i, 0, rootIndex );
1447 return QModelIndex();
1449 itemPath = item->
path();
1451 if ( itemPath == path )
1459 while ( foundChild )
1465 if ( itemPath.isEmpty() )
1467 for ( ; i <
rowCount( rootIndex ); i++ )
1469 QModelIndex idx =
index( i, 0, rootIndex );
1472 return QModelIndex();
1474 itemPath = item->
path();
1476 if ( itemPath == path )
1482 if ( !itemPath.endsWith(
'/' ) )
1485 foundParent =
false;
1496 for ( QString childPath : constSelectionsList )
1498 if ( childPath.endsWith(
'/' ) )
1499 childPath.chop( 1 );
1501 if ( path.startsWith( childPath ) )
1510 else if ( path.startsWith( itemPath ) )
1528 return QModelIndex();
1542 const QModelIndex idx =
findPath( path );
1543 if ( idx.isValid() )
1556 return item ? createIndex( row, column, item ) : QModelIndex();
1563 return QModelIndex();
1572 for (
int i = 0; i < items.size(); i++ )
1574 if ( items[i] == item )
1575 return createIndex( i, 0, item );
1577 QModelIndex childIndex =
findItem( item, items[i] );
1578 if ( childIndex.isValid() )
1582 return QModelIndex();
1600 if ( !idx.isValid() )
1603 beginInsertRows( idx, first, last );
1614 if ( !idx.isValid() )
1616 beginRemoveRows( idx, first, last );
1660 void *v = idx.internalPointer();
1662 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)
QString archiveName() const
static QgsCptCityArchive * defaultArchive()
QString copyingFileName(const QString &dirName) const
bool isEmpty() const
Returns true if archive is empty.
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
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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)