Merge branch 'coloramp' of ../qgis-etiennesky

This commit is contained in:
Etienne Tourigny 2012-08-02 23:50:08 -03:00
commit f8f034ca9c
20 changed files with 2245 additions and 22 deletions

View File

@ -410,7 +410,7 @@ SET(QGIS_CORE_HDRS
symbology/qgssymbologyutils.h
symbology-ng/qgscategorizedsymbolrendererv2.h
symbology-ng/qgscolorbrewerpalette.h
symbology-ng/qgscolorrampv2data.h
symbology-ng/qgsellipsesymbollayerv2.h
symbology-ng/qgsfillsymbollayerv2.h
symbology-ng/qgsgraduatedsymbolrendererv2.h

View File

@ -33,7 +33,7 @@ class CORE_EXPORT QgsColorBrewerPalette
continue;
QStringList colors = items[2].split( QChar( ' ' ) );
foreach( QString clr, colors )
pal << parseColor( clr );
pal << QgsSymbolLayerV2Utils::parseColor( clr );
}
return pal;
}
@ -72,14 +72,6 @@ class CORE_EXPORT QgsColorBrewerPalette
return variants;
}
static QColor parseColor( QString color )
{
QStringList p = color.split( QChar( ',' ) );
if ( p.count() != 3 )
return QColor();
return QColor( p[0].toInt(), p[1].toInt(), p[2].toInt() );
}
};
/*
@ -359,4 +351,441 @@ const char* brewerString =
"PuBuGn-8-255,247,251 236,226,240 208,209,230 166,189,219 103,169,207 54,144,192 2,129,138 1,100,80\n"
"PuBuGn-9-255,247,251 236,226,240 208,209,230 166,189,219 103,169,207 54,144,192 2,129,138 1,108,89 1,70,54";
/*
The following tables were taken from the cpt-city website http://soliton.vm.bytemark.co.uk/pub/cpt-city/
*/
/*
Copyright for cpt-city gradients
The gradients on cpt-city are copyrighted by their authors. In all cases the gradients in the archive are included with the permission of the author, either explicitly or where the licence under which they were distributed allows it.
The original gradients are converted to the other formats available on cpt-city these generated gradients are offered under the same licence as the original.
Please respect the authors' copyright.
Free to use
All gradients in the archive are free for you to download and use in your own maps, illustrations and so on. Some authors request or require that attribution be given.
Free use does not include the further distribution of the gradients, modified or unmodified.
Distribution
You should not distribute the gradients on cpt-city unless the licence permits it: gradients contributed to the public domain, those under GPL, Apache-like, Creative commons or MIT licences allow distribution (under some conditions).
If the author has not specified a licence then you do not have permission to distribute the gradients.
*/
/* name mappings - by author*/
static const char* cptCityNames [] = {
#if 0
// these defs are now in DESC.xml files
"bhw","Art gradients by Blackheartedwolf",
"cb","Colour schemes by Cynthia Brewer",
"cl","Obesity scales from CalorieLab",
"colo","Selected five-colour palettes from COLOURlovers",
"cw","Subtle gradients from Crumblingwalls ",
"dca","Palettes for positive functions by Duncan Agnew",
"dg","Dave Green's cubehelix for astronomical intensity images",
"ds","Gradients by Diane Simoni",
"ds9","DS9 colour scales for astronomical visualisation ",
"em","A DEM palette by Erika Mackay",
"erj","Toning samples by Eric R. Jeschke",
"es","Themed art gradients by ElvenSword",
"esdb","Selected legends from the European Soil Database",
"esri","ESRI colour ramp collection ",
"fg","Vista login button gradients by Fused Graphics",
"fme","The DEM palettes from drawmap, by Fred M. Erickson",
"fvl","Felix von Luschan skin-colour scales",
"gery","A seismic amplitude scheme by Gery",
"ggr","GIMP gradients",
"gist","Palettes from the graphics packages GIST and Yorick",
"gmt","Generic Mapping Tools palettes ",
"go2","Two-colour glossy gradients from GoSquared",
"gps","Gradients from GIMP Paint Studio",
"grass","GRASS colour ramps",
"h5","Colour tables from the h5utils package",
"hult","Spectral gradients by Hult",
"ibcao","The IBCAO scheme for arctic bathymetry",
"ing","Gradients by Ingerlise",
"jjg","Technical gradients by J.J. Green",
"jm","The ShadeMax palettes by Jim Mossman",
"jmn","James McNames' monotonic luminance ColorSpiral",
"km","Diverging colour-maps by Kenneth Moreland",
"kst","KST colour tables",
"lb","Loadboy's gradients for graphic design",
"ma","Gradients by Michele Arnold",
"mby","A topo-bathymetric scheme by M. Burak Yikilmaz",
"mjf","Precipitation palettes by Mark J. Fenbers",
"ncl","Colour maps from NCL (NCAR command language) ",
"ncdc","The NCDC's scheme for probability of a white Christmas ",
"nd","Nevit Dilmen's extra gradients for the GIMP",
"neota","Pixel-art gradients by Neota",
"ngdc","The NGDC's global relief palette for ETOPO1",
"njgs","Legends for geospatial data by the NJGS ",
"oc","Colour scales from NASA's OceanColor site",
"ocal","Gradients from the Open Clip Art Library",
"occ","Digital art gradients by Onecoldcanadian",
"os","Ordnance Survey 1:250,000 elevation scale ",
"pd","Piecrust Design's natural gradients ",
"pj","Gradients by Peggy Jentoft",
"pm","Gnuplot pm3d example scales by Petr Mikulik",
"rc","Gradients from Restless Concepts",
"rf","Rich Franzen's pseudogrey",
"saga","SAGA preset colour tables",
"sd","Web 2.0 gradients from Sarah Davison",
"td","DEM palettes by Thomas Dewez",
"tl","Nonlinear greyscales by Thomas Lotze",
"tp","Tom Patterson's topographic scales",
"ukmo","Meteorological schemes from the UK Met Office",
"vh","Victor Huerfano's Caribbean DEM palette",
"wkp","Wikipedia schemes",
"xkcd","Bathymetry from XKCD 1040",
#endif
//views
"bath","Palettes for bathymetry",
"blues","A selection of blues",
"topo","Palettes for topography",
"topobath","Mixed palettes for topography & bathymetry",
"temp","Schemes for temperature",
"rain","Schemes for precipitation",
"greys","Various greys and near-greys",
"reds","A selection of reds",
"div","Schemes for diverging data",
"transparency","Palettes with transparency",
"discord","Gradients of discordance",
"popular","The most popular palettes",
#if 0
//views/div
"jjg/cbcont/div","continuous",
"jjg/cbac/div","almost continuous",
"jjg/polarity","polarity",
#endif
NULL, NULL
};
/* Selections from the archive */
/* format: "", <section>, <item_1>,...,<item_n>,"",... */
static const char* cptCitySelections [] = {
"",
"bath",
"gmt/GMT_ocean",
"gmt/GMT_gebco",
"jjg/dem/gebco-shelf",
"jm/ad/ad-a",
"njgs/njbath",
"esri/hypsometry/bath/bath_110",
"esri/hypsometry/bath/bath_111",
"esri/hypsometry/bath/bath_112",
"tp/tpsfhm",
"xkcd/xkcd-bath",
"",
"blues",
"es/skywalker/",
"es/sea_dreams/",
"cb/seq/Blues_09",
"cb/seq/GnBu_09",
"cb/seq/PuBu_09",
"cb/seq/YlGnBu_09",
"erj/misc/cyanotype_01",
"erj/misc/cyanotype_02",
"erj/multiple/cyanotype_01",
"ggr/Deep_Sea",
"neota/base/sky-blue",
"neota/clth/purplish-blue",
"neota/clth/jeans",
"neota/elem/crisp-ice",
"neota/elem/rain",
"neota/face/eyes/blue",
"neota/liht/twilight",
"ocal/blues",
"ocal/pastel-purple-blue",
"occ/1/occ019",
"occ/2/occ079",
"",
"topo",
"td/DEM_poster",
"td/DEM_print",
"td/DEM_screen",
"jjg/dem/c3t1",
"jjg/dem/c3t3",
"jjg/dem/garish14",
"fme/feet/natural",
"fme/feet/neutral",
"fme/feet/textbook",
"jm/tv/tv-a",
"jm/o2/o2-a",
"jm/db/db-a",
"jm/ao/ao-a",
"jm/wt/wt-a",
"jm/ws/ws-a",
"jm/cd/cd-a",
"jm/sd/sd-a",
"grass/elevation",
"njgs/njdem100",
"esri/hypsometry/na/palm_springs_4",
"esri/hypsometry/na/pnw_1113",
"esri/hypsometry/na/utah_1",
"esri/hypsometry/eu/europe_3",
"esri/hypsometry/eu/iceland",
"esri/hypsometry/eu/spain",
"os/os250k-feet",
"tp/tpushuf",
"wkp/schwarzwald/wiki-schwarzwald-cont",
"wkp/schwarzwald/wiki-schwarzwald-d050",
"wkp/knutux/wiki-knutux",
"wkp/tubs/nrwc",
"",
"topobath",
"em/NZ_blue",
"wkp/template/wiki-2.0",
"wkp/country/wiki-scotland",
"wkp/country/wiki-france",
"gmt/GMT_globe",
"gmt/GMT_relief",
/* "gmt/GMT_sealand", */
/* "gmt/GMT_topo", */
"vh/Caribbean",
"grass/etopo2",
"grass/srtm",
"grass/terrain",
"ngdc/ETOPO1",
"ibcao/ibcao",
"wkp/plumbago/wiki-plumbago",
"ncl/topo_15lev",
"wkp/encyclopedia/meyers",
"wkp/encyclopedia/nordisk-familjebok",
"mby/mby",
"wkp/lilleskut/afrikakarte",
"",
"temp",
"oc/sst",
"jjg/misc/temperature",
"grass/celsius",
"ukmo/wow/temp-c",
"ncl/temp_19lev",
"",
"rain",
"grass/precipitation",
"jjg/misc/rainfall",
"mjf/departure",
"mjf/s3pcpnScale",
"ncdc/white-christmas",
"wkp/ice/wiki-ice-greenland",
"ukmo/wow/rain-mmh",
"ukmo/wow/humidity",
"ncl/precip_11lev",
"wkp/precip/wiki-precip-mm",
"",
"greys",
"tl/",
"erj/",
"ma/gray/",
"es/platinum/",
"cb/seq/Greys_09",
"cb/div/RdGy_11",
"erj/bw/silver_01",
"erj/browns/platinum_palladium_01",
"erj/browns/selenium_brown_01",
"ing/general/ib12",
"rf/pseudogrey",
"ma/gray/grayscale02",
"ma/gray/grayscale02a",
"ma/gray/grayscale10",
"nd/atmospheric/GreyOClock",
"ocal/stripes-six",
"tl/power-0.50",
"go2/webtwo/grey-g2-3",
"es/platinum/es_platinum_16",
"",
"reds",
"nd/red/",
"es/rosa/",
"cb/seq/Reds_09",
"cb/seq/YlOrRd_09",
"colo/angelafaye/scent_of_spring",
"colo/sugar/Colours_Are_Evil",
"colo/sugar/October_Sky",
"colo/evad/Sandy_Scars_Aus",
"colo/hana/M_a_i_k_o",
"colo/katiekat013/Raspberries_Creme",
"colo/lightningmccarl/so_close_to_you",
"colo/lightningmccarl/you_cheater",
"colo/rphnick/Emo_Barbie_Playmate",
"colo/rphnick/To_My_1st_100_Loves",
"colo/tvr/l_o_v_e",
"cw/1/cw1-003",
"cw/5/cw5-068",
"ds9/red",
"ggr/German_flag_smooth",
"gist/heat",
"gmt/GMT_hot",
"jjg/neo10/base/red-pink",
"jjg/neo10/clth/pink-red",
"jjg/neo10/clth/violent-pink-red",
"jjg/neo10/food/red-candy",
"ma/gray/grayscale08",
"ma/gray/grayscale09",
"rc/autumnrose",
"",
"div",
"km/",
"cb/div/",
"jjg/cbcont/div/",
"jjg/cbac/div/",
"jjg/polarity/",
"bhw/bhw2/bhw2_39",
"cb/div/BrBG_11",
"cw/1/cw1-002",
"es/landscape/es_landscape_90",
"es/landscape/es_landscape_76",
"esri/events/fire_active_2",
"gery/seismic",
"ggr/French_flag_smooth",
"ggr/Mexican_flag_smooth",
"ggr/Romanian_flag_smooth",
"grass/curvature",
"h5/dkbluered",
"jjg/misc/voxpop",
"jjg/cbcont/div/cbcBrBG",
"jjg/cbac/div/cbacBrBG11",
"jjg/polarity/BrBG",
"jjg/ccolo/evad/Andy_GIlmore_2",
"jjg/ccolo/sugar/Need_I_Say_More",
"jjg/ccolo/vredeling/Grand_Boucle",
"jjg/ccolo/vredeling/Optimus_Prime",
"jjg/ccolo/vredeling/British_Cheer",
"/jjg/ccolo/vredeling/Tubular_Bells",
"ma/xmas/xmas_22",
"ma/postcard/ha_14",
"mjf/departure",
"nd/vermillion/Split_02",
"nd/vermillion/Tertiary_01",
"nd/turanj/Analogous_12b",
"nd/red/Primary_3",
"occ/2/occ100",
"occ/2/occ083",
"rc/wildwinds",
"ncl/temp_19lev",
"ncl/sunshine_diff_12lev",
"ncl/GreenYellow",
"ncl/BlueYellowRed",
"ncl/BlueWhiteOrangeRed",
"ncl/BlueDarkRed18",
"ncl/BlWhRe",
"km/blue-tan-d14",
"km/cool-warm-d07",
"km/green-purple",
"",
"transparency",
"tl/",
"ocal/",
"ggr/",
"es/platinum/es_platinum_01",
"es/sea_dreams/es_seadreams_14",
"ggr/Aneurism",
"ggr/Flare_Glow_Radial_1",
"ggr/Radial_Rainbow_Hoop",
"nd/other/Neon_Orange",
"ocal/beer-lager",
"ocal/stripes-three",
"ocal/spectrums-rainbow-002",
"tl/power-0.80",
"gps/GPS-Haze-and-Atmosphere",
"gps/GPS-Simple-Smoke",
"",
"discord",
"rc/teabearrose",
"pj/3/grand-old-flag",
"pj/5/vampirelips",
"pj/6/nunoftheabove",
"pd/food/curry_house",
"ocal/christmas-candy",
"nd/strips/Wood_Green",
"nd/atmospheric/Sunset_Real",
"ing/general2/ib63",
"hult/gr41_hult",
"ggr/Nauseating_Headache",
"ds/rgi/rgi_15",
"",
"popular",
"ngdc/ETOPO1",
"ibcao/ibcao",
"wkp/template/wiki-2.0",
"oc/sst",
"td/DEM_print",
"em/NZ_blue",
"td/DEM_screen",
"grass/elevation",
"gmt/GMT_globe",
"ds9/b",
"gmt/GMT_panoply",
"gmt/GMT_haxby",
"td/DEM_poster",
"wkp/schwarzwald/wiki-schwarzwald-d100",
"wkp/schwarzwald/wiki-schwarzwald-d050",
"gmt/GMT_ocean",
"jjg/polarity/RdYlBu",
"xkcd/xkcd-bath",
"esri/hypsometry/eu/europe_8",
"wkp/encyclopedia/nordisk-familjebok",
"gmt/GMT_relief",
"grass/bgyr",
"h5/dkbluered",
"grass/bcyr",
"jjg/polarity/Spectral",
"cl/fs2010",
"wkp/country/wiki-scotland",
"gist/earth",
"bhw/bhw1/bhw1_w00t",
"erj/browns/platinum_01",
"cb/div/RdBu_11",
"cb/seq/Blues_03",
"jjg/physics/visspec",
"cb/seq/GnBu_04",
"esri/hypsometry/eu/spain",
"gmt/GMT_polar",
"ggr/Full_saturation_spectrum_CW",
"km/purple-orange",
"cb/seq/YlOrRd_06",
"ngdc/ETOPO1-Reed",
"wkp/schwarzwald/wiki-schwarzwald-d020",
"grass/terrain",
"oc/ndvi",
"dg/ch05m151010",
"dg/ch05m151008",
"fme/metres/natural",
"km/green-purple",
"os/os250k-feet",
"ds9/sls",
"gmt/GMT_wysiwyg",
"wkp/schwarzwald/wiki-schwarzwald-cont",
"km/cool-warm",
"wkp/encyclopedia/meyers",
"gmt/GMT_drywet",
"ukmo/wow/humidity",
"grass/differences",
"jm/cd/cd-a",
"esri/hypsometry/eu/europe_4",
"ukmo/wow/rain-mmh",
"wkp/template/wiki-1.02",
"cb/div/Spectral_08",
"grass/celsius",
"km/cool-warm-d08",
"gery/seismic",
"oc/rainbow",
"wkp/template/wiki-1.03",
"km/cool-warm-d07",
"jjg/misc/temperature",
"km/blue-tan-d10",
"km/cyan-mauve-d08",
"km/purple-orange-d05",
"ds9/red",
"cb/seq/OrRd_04",
"jjg/dem/c3t3",
"km/blue-yellow-d13",
NULL, NULL
};
#endif // QGSCOLORBREWERPALETTE_H

View File

@ -2299,6 +2299,8 @@ QgsVectorColorRampV2* QgsSymbolLayerV2Utils::loadColorRamp( QDomElement& element
return QgsVectorRandomColorRampV2::create( props );
else if ( rampType == "colorbrewer" )
return QgsVectorColorBrewerColorRampV2::create( props );
else if ( rampType == "cpt-city" )
return QgsCptCityColorRampV2::create( props );
else
{
QgsDebugMsg( "unknown colorramp type " + rampType );
@ -2317,6 +2319,20 @@ QDomElement QgsSymbolLayerV2Utils::saveColorRamp( QString name, QgsVectorColorRa
return rampEl;
}
// parse color definition with format "rgb(0,0,0)" or "0,0,0"
// should support other formats like FFFFFF
QColor QgsSymbolLayerV2Utils::parseColor( QString colorStr )
{
if ( colorStr.startsWith( "rgb(" ) )
{
colorStr = colorStr.mid( 4, colorStr.size() - 5 ).trimmed();
}
QStringList p = colorStr.split( QChar( ',' ) );
if ( p.count() != 3 )
return QColor();
return QColor( p[0].toInt(), p[1].toInt(), p[2].toInt() );
}
double QgsSymbolLayerV2Utils::lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
{

View File

@ -193,6 +193,9 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
static QgsVectorColorRampV2* loadColorRamp( QDomElement& element );
static QDomElement saveColorRamp( QString name, QgsVectorColorRampV2* ramp, QDomDocument& doc );
/** parse color definition with format "rgb(0,0,0)" or "0,0,0" */
static QColor parseColor( QString colorStr );
/**Returns the line width scale factor depending on the unit and the paint device*/
static double lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
/**Returns scale factor painter units -> pixel dimensions*/

View File

@ -14,8 +14,11 @@
***************************************************************************/
#include "qgsvectorcolorrampv2.h"
#include "qgscolorrampv2data.h"
#include "qgssymbollayerv2utils.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include <stdlib.h> // for random()
@ -208,8 +211,6 @@ QgsVectorColorRampV2* QgsVectorColorBrewerColorRampV2::create( const QgsStringMa
return new QgsVectorColorBrewerColorRampV2( schemeName, colors );
}
#include "qgscolorbrewerpalette.h"
void QgsVectorColorBrewerColorRampV2::loadPalette()
{
mPalette = QgsColorBrewerPalette::listSchemeColors( mSchemeName, mColors );
@ -248,3 +249,536 @@ QgsStringMap QgsVectorColorBrewerColorRampV2::properties() const
map["colors"] = QString::number( mColors );
return map;
}
////////////
/*
TODO
- return a suitable name (scheme_variant)
- use model/view for the treewidget
- fix ocal file parsing
- re-organize and rename colorramp classes and widgets
*/
QString QgsCptCityColorRampV2::mBaseDir;
QStringList QgsCptCityColorRampV2::mCollections;
QMap< QString, QStringList > QgsCptCityColorRampV2::mSchemeMap;
// QMap< QString, int > QgsCptCityColorRampV2::mSchemeNumColors;
QMap< QString, QStringList > QgsCptCityColorRampV2::mSchemeVariants;
QMap< QString, QString > QgsCptCityColorRampV2::mCollectionNames;
QMap< QString, QStringList > QgsCptCityColorRampV2::mCollectionSelections;
QgsCptCityColorRampV2::QgsCptCityColorRampV2( QString schemeName, QString variantName )
: mSchemeName( schemeName ), mVariantName( variantName ), mContinuous( false )
{
// TODO replace this with hard-coded data in the default case
loadFile();
}
QgsVectorColorRampV2* QgsCptCityColorRampV2::create( const QgsStringMap& props )
{
QString schemeName = DEFAULT_CPTCITY_SCHEMENAME;
QString variantName = DEFAULT_CPTCITY_VARIANTNAME;
if ( props.contains( "schemeName" ) )
schemeName = props["schemeName"];
if ( props.contains( "variantName" ) )
variantName = props["variantName"];
return new QgsCptCityColorRampV2( schemeName, variantName );
}
QColor QgsCptCityColorRampV2::color( double value ) const
{
if ( mPalette.isEmpty() || value < 0 || value > 1 )
return QColor( 255, 0, 0 ); // red color as a warning :)
if ( ! mContinuous )
{
int paletteEntry = ( int )( value * mPalette.count() );
if ( paletteEntry >= mPalette.count() )
paletteEntry = mPalette.count() - 1;
return mPalette.at( paletteEntry );
}
else
{
int numStops = mPalette.count();
if ( numStops < 2 )
return QColor( 255, 0, 0 ); // red color as a warning :)
StopsMap mStops; // TODO integrate in main class
for ( int i = 0; i < numStops; i++ )
mStops[ mPaletteStops[i] ] = mPalette[i];
double lower = 0, upper;
QColor c1 = mPalette[1], c2;
for ( StopsMap::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
{
if ( it.key() >= value )
{
upper = it.key();
c2 = it.value();
return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
}
lower = it.key();
c1 = it.value();
}
upper = 1;
c2 = mPalette[ numStops - 1 ];
return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
}
}
QgsVectorColorRampV2* QgsCptCityColorRampV2::clone() const
{
return new QgsCptCityColorRampV2( mSchemeName, mVariantName );
}
QgsStringMap QgsCptCityColorRampV2::properties() const
{
QgsStringMap map;
map["schemeName"] = mSchemeName;
map["variantName"] = mVariantName;
return map;
}
QStringList QgsCptCityColorRampV2::listSchemeCollections( QString collectionName, bool recursive )
{
QDir dir = QDir( QgsCptCityColorRampV2::getBaseDir() + "/" + collectionName );
if ( ! dir.exists() )
return QStringList();
QStringList entries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name );
if ( collectionName != "" )
{
for ( int i = 0; i < entries.count(); i++ )
{
entries[i] = collectionName + "/" + entries[i];
}
}
// recurse
if ( recursive )
{
QStringList entries2 = entries;
foreach( QString entry, entries2 )
{
entries.append( listSchemeCollections( entry, true ) );
}
}
return entries;
}
QStringList QgsCptCityColorRampV2::listSchemeNames( QString collectionName )
{
QDir dir = QDir( QgsCptCityColorRampV2::getBaseDir() + "/" + collectionName );
if ( ! dir.exists() )
{
QgsDebugMsg( "dir " + dir.dirName() + " does not exist" );
return QStringList();
}
QStringList entries = dir.entryList( QStringList( "*.svg" ), QDir::Files, QDir::Name );
for ( int i = 0; i < entries.count(); i++ )
entries[i] = entries[i].left( entries[i].length() - 4 );
return entries;
}
QList<int> QgsCptCityColorRampV2::listSchemeVariants( QString schemeName )
{
QList<int> variants;
QString palette( brewerString );
QStringList list = palette.split( QChar( '\n' ) );
foreach( QString entry, list )
{
QStringList items = entry.split( QChar( '-' ) );
if ( items.count() != 3 || items[0] != schemeName )
continue;
variants << items[1].toInt();
}
return variants;
}
QString QgsCptCityColorRampV2::getBaseDir()
{
// currently hard-coded, but could be also in QGis install path and/or configurable
if ( mBaseDir.isNull() )
return QgsApplication::qgisSettingsDirPath() + "/" + "cpt-city";
else
return mBaseDir;
}
QString QgsCptCityColorRampV2::getFilename() const
{
if ( mSchemeName == "" )
return QString();
else
return QgsCptCityColorRampV2::getBaseDir() + "/" + mSchemeName + mVariantName + ".svg";
}
bool QgsCptCityColorRampV2::loadFile( QString filename )
{
if ( filename == "" )
{
filename = getFilename();
if ( filename.isNull() )
return false;
}
// QgsDebugMsg("filename= "+filename);
mPalette.clear();
mPaletteStops.clear();
QString mErrorString = QString();
// import xml file
QFile f( filename );
if ( !f.open( QFile::ReadOnly ) )
{
mErrorString = "Couldn't open the SVG file: " + filename;
QgsDebugMsg( mErrorString );
return false;
}
// parse the document
QDomDocument doc( "gradient" );
if ( !doc.setContent( &f ) )
{
mErrorString = "Couldn't parse the SVG file: " + filename;
f.close();
QgsDebugMsg( mErrorString );
return false;
}
f.close();
QDomElement docElem = doc.documentElement();
if ( docElem.tagName() != "svg" )
{
mErrorString = "Incorrect root tag: " + docElem.tagName();
QgsDebugMsg( mErrorString );
return false;
}
// load color ramp
QDomElement rampsElement = docElem.firstChildElement( "linearGradient" );
if ( rampsElement.isNull() )
{
mErrorString = "linearGradient tag missing";
QgsDebugMsg( mErrorString );
return false;
}
// initialize self
mContinuous = true; // we will detect later if there are overlapping stops
mPalette.clear();
mPaletteStops.clear();
// loop for all stop tags
QDomElement e = rampsElement.firstChildElement();
// int i = 0;
QMap< double, QColor > map;
while ( !e.isNull() )
{
// QgsDebugMsg("read "+e.tagName());
if ( e.tagName() == "stop" )
{
//todo integrate this into symbollayerutils, keep here for now...
double offset;
QString offsetStr = e.attribute( "offset" ); // offset="50.00%" | offset="0.5"
if ( offsetStr.endsWith( "%" ) )
offset = offsetStr.remove( offsetStr.size() - 1, 1 ).toDouble() / 100.0;
else
offset = offsetStr.toDouble();
QString colorStr = e.attribute( "stop-color", "" ); // stop-color="rgb(222,235,247)"
QString opacityStr = e.attribute( "stop-opacity", "1.0" ); // stop-opacity="1.0000"
// QColor color( 255, 0, 0 ); // red color as a warning :)
QColor color = QgsSymbolLayerV2Utils::parseColor( colorStr );
if ( color != QColor() )
{
int alpha = opacityStr.toDouble() * 255; // test
color.setAlpha( alpha );
if ( map.contains( offset ) )
mContinuous = false; // assume discrete if at least one stop is repeated
map[offset] = color;
}
}
else
{
QgsDebugMsg( "unknown tag: " + e.tagName() );
}
e = e.nextSiblingElement();
}
// if this is a discrete gradient, remove last stop
if ( ! mContinuous )
{
if ( map.contains( 1 ) )
map.remove( 1 );
}
// add colors to palette
QMap<double, QColor>::const_iterator it = map.constBegin();
while ( it != map.constEnd() )
{
mPaletteStops << it.key();
mPalette << it.value();
++it;
}
return true;
}
bool QgsCptCityColorRampV2::hasBasicSchemes()
{
// Currently returns hasAllSchemes, because we don't have a minimal set yet
return hasAllSchemes();
}
bool QgsCptCityColorRampV2::hasAllSchemes()
{
// if we have no collections loaded yet, just make sure we have at least one collection
// ideally we should test for a few schemes we know should be present
if ( mCollections.isEmpty() )
{
return ( ! QgsCptCityColorRampV2::listSchemeCollections( "", false ).isEmpty() );
}
return true;
}
// currently this methos takes some time, so it must be explicitly requested
bool QgsCptCityColorRampV2::loadSchemes( QString rootDir, bool reset )
{
// TODO should keep the name of the previously loaded, or see if the first element is inside rootDir
if ( ! reset && ! mCollections.isEmpty() )
{
QgsDebugMsg( QString( "not loading schemes, rootDir=%1 reset=%2 empty=%3" ).arg( rootDir ).arg( reset ).arg( mCollections.isEmpty() ) );
return true;
}
QString curName, prevName, prevPath, curVariant, curSep, schemeName;
QStringList listVariant;
QStringList schemeNamesAll, schemeNames;
int num;
bool ok, prevAdd, curAdd;
if ( reset )
{
mCollections.clear();
mSchemeMap.clear();
// mSchemeNumColors.clear();
mSchemeVariants.clear();
mCollectionNames.clear();
mCollectionSelections.clear();
}
mCollections = listSchemeCollections( rootDir, true );
qSort( mCollections.begin(), mCollections.end() );
foreach( QString path, mCollections )
{
// QgsDebugMsg("================================");
// QgsDebugMsg("collection = "+path);
schemeNamesAll = QgsCptCityColorRampV2::listSchemeNames( path );
// TODO detect if there are duplicate names with different variant counts, combine in 1
for ( int i = 0; i < schemeNamesAll.count(); i++ )
{
// schemeName = QFileInfo( schemeNamesAll[i] ).baseName();
schemeName = schemeNamesAll[i];
// QgsDebugMsg("=============");
// QgsDebugMsg("scheme = "+schemeName);
curName = schemeName;
curVariant = "";
// stupid code to find if name ends with 1-3 digit number - should use regexp
// TODO need to detect if ends with b/c also
if ( schemeName.length() > 1 && schemeName.endsWith( "a" ) && ! listVariant.isEmpty() &&
(( prevName + listVariant.last() + "a" ) == curName ) )
{
curName = prevName;
curVariant = listVariant.last() + "a";
}
else
{
num = schemeName.right( 3 ).toInt( &ok );
Q_UNUSED( num );
if ( ok )
{
curName = schemeName.left( schemeName.size() - 3 );
curVariant = schemeName.right( 3 );
}
else
{
num = schemeName.right( 2 ).toInt( &ok );
if ( ok )
{
curName = schemeName.left( schemeName.size() - 2 );
curVariant = schemeName.right( 2 );
}
else
{
num = schemeName.right( 1 ).toInt( &ok );
if ( ok )
{
curName = schemeName.left( schemeName.size() - 1 );
curVariant = schemeName.right( 1 );
}
}
}
}
curSep = curName.right( 1 );
if ( curSep == "-" || curSep == "_" )
{
curName.chop( 1 );
curVariant = curSep + curVariant;
}
if ( prevName == "" )
prevName = curName;
// add element, unless it is empty, or a variant of last element
prevAdd = false;
curAdd = false;
if ( curName == "" )
curName = "__empty__";
// if current is a variant of last, don't add previous and append current variant
if ( curName == prevName )
{
// add current element if it is the last one in the collection
if ( i == schemeNamesAll.count() - 1 )
prevAdd = true;
listVariant << curVariant;
}
else
{
if ( prevName != "" )
{
prevAdd = true;
}
// add current element if it is the last one in the collection
if ( i == schemeNamesAll.count() - 1 )
curAdd = true;
}
// QgsDebugMsg(QString("prevAdd=%1 curAdd=%2 prevName=%3 curName=%4 count=%5").arg(prevAdd).arg(curAdd).arg(prevName).arg(curName).arg(listVariant.count()));
if ( prevAdd )
{
// depending on number of variants, make one or more items
if ( listVariant.count() == 0 )
{
// set num colors=-1 to parse file on request only
// mSchemeNumColors[ prevName ] = -1;
schemeNames << prevName;
}
else if ( listVariant.count() <= 2 )
{
// for 1-2 items, create independent items
for ( int j = 0; j < listVariant.count(); j++ )
{
// mSchemeNumColors[ prevName + listVariant[j] ] = -1;
schemeNames << prevName + listVariant[j];
}
}
else
{
mSchemeVariants[ path + "/" + prevName ] = listVariant;
schemeNames << prevName;
}
listVariant.clear();
}
if ( curAdd )
{
if ( curVariant != "" )
curName += curVariant;
schemeNames << curName;
}
// save current to compare next
if ( prevAdd || curAdd )
{
prevName = curName;
if ( curVariant != "" )
listVariant << curVariant;
}
}
// add schemes to collection
mSchemeMap[ path ] = schemeNames;
schemeNames.clear();
listVariant.clear();
prevName = "";
}
// populate mCollectionNames
foreach( QString path, mCollections )
{
QString filename = QgsCptCityColorRampV2::getBaseDir() + "/" + path + "/" + "DESC.xml";
QFile f( filename );
if ( ! f.open( QFile::ReadOnly ) )
{
QgsDebugMsg( "description file for path " + path + " [ " + filename + " ] does not exist" );
continue;
}
// parse the document
QString errMsg;
QDomDocument doc( "description" );
if ( !doc.setContent( &f, &errMsg ) )
{
f.close();
QgsDebugMsg( "Couldn't parse file " + filename + " : " + errMsg );
continue;
}
f.close();
// read description
QDomElement docElem = doc.documentElement();
if ( docElem.tagName() != "description" )
{
QgsDebugMsg( "Incorrect root tag: " + docElem.tagName() );
continue;
}
// should we make sure the <dir> tag is ok?
QDomElement nameElement = docElem.firstChildElement( "name" );
if ( nameElement.isNull() )
{
QgsDebugMsg( "name tag missing" );
continue;
}
// add info to mapping
mCollectionNames[ path ] = nameElement.text();
}
// add any elements that are missing from DESC.xml (views)
for ( int i = 0; cptCityNames[i] != NULL; i = i + 2 )
{
mCollectionNames[ cptCityNames[i] ] = cptCityNames[i+1];
}
// populate mCollectionSelections
QString viewName;
for ( int i = 0; cptCitySelections[i] != NULL; i++ )
{
curName = QString( cptCitySelections[i] );
if ( curName == "" )
{
viewName = QString( cptCitySelections[i+1] );
curName = QString( cptCitySelections[i+2] );
i = i + 2;
}
mCollectionSelections[ viewName ] << curName;
}
return ( ! mCollections.isEmpty() );
}

View File

@ -158,4 +158,86 @@ class CORE_EXPORT QgsVectorColorBrewerColorRampV2 : public QgsVectorColorRampV2
QList<QColor> mPalette;
};
#define DEFAULT_CPTCITY_SCHEMENAME "cb/div/BrBG_" //change this
#define DEFAULT_CPTCITY_VARIANTNAME "05"
class CORE_EXPORT QgsCptCityColorRampV2 : public QgsVectorColorRampV2
{
public:
QgsCptCityColorRampV2( QString schemeName = DEFAULT_CPTCITY_SCHEMENAME,
QString variantName = DEFAULT_CPTCITY_VARIANTNAME );
static QgsVectorColorRampV2* create( const QgsStringMap& properties = QgsStringMap() );
virtual QColor color( double value ) const;
virtual QString type() const { return "cpt-city"; }
virtual QgsVectorColorRampV2* clone() const;
virtual QgsStringMap properties() const;
int count() const { return mPalette.count(); }
QString schemeName() const { return mSchemeName; }
QString variantName() const { return mVariantName; }
/* void setSchemeName( QString schemeName ) { mSchemeName = schemeName; loadPalette(); } */
/* void setVariantName( QString variantName ) { mVariantName = variantName; loadPalette(); } */
/* lazy loading - have to call loadPalette() explicitly */
void setSchemeName( QString schemeName ) { mSchemeName = schemeName; }
void setVariantName( QString variantName ) { mVariantName = variantName; }
void setName( QString schemeName, QString variantName = "" )
{ mSchemeName = schemeName; mVariantName = variantName; loadPalette(); }
void loadPalette();
bool isContinuous() const { return mContinuous; }
QString getFilename() const;
bool loadFile( QString filename = "" );
/* static QList<QColor> listSchemeColors( QString schemeName, int colors ); */
static QList<int> listSchemeVariants( QString schemeName );
static QString getBaseDir();
static void setBaseDir( QString dirName ) { mBaseDir = dirName; }
static bool loadSchemes( QString rootDir = "", bool reset = false );
/** Is the minimal (free to distribute) set of schemes available? Currently returns hasAllSchemes, because we don't have a minimal set yet. */
static bool hasBasicSchemes();
/** Is the entire archive available? Currently tests that there is at least one scheme. */
static bool hasAllSchemes();
static QStringList listSchemeCollections( QString collectionName = "", bool recursive = false );
static QStringList listSchemeNames( QString collectionName );
static QgsCptCityColorRampV2* colorRampFromSVGFile( QString svgFile );
static QgsCptCityColorRampV2* colorRampFromSVGString( QString svgString );
static const QMap< QString, QStringList > schemeMap() { return mSchemeMap; }
/* static const QMap< QString, int > schemeNumColors() { return mSchemeNumColors; } */
static const QMap< QString, QStringList > schemeVariants() { return mSchemeVariants; }
static const QMap< QString, QString > collectionNames() { return mCollectionNames; }
static const QMap< QString, QStringList > collectionSelections() { return mCollectionSelections; }
protected:
typedef QMap<double, QColor> StopsMap;
QString mSchemeName;
QString mVariantName;
bool mContinuous;
QList< QColor > mPalette;
QList< double > mPaletteStops;
/* QMap< double, QColor > mPalette; */
static QString mBaseDir;
static QStringList mCollections;
static QMap< QString, QStringList > mSchemeMap; //key is collection, value is schemes
/* mSchemeNumColors removed, instead read on demand */
/* static QMap< QString, int > mSchemeNumColors; //key is scheme, value is # colors (if no variants) */
static QMap< QString, QStringList > mSchemeVariants; //key is scheme, value is variants
static QMap< QString, QString > mCollectionNames; //key is name, value is description
static QMap< QString, QStringList > mCollectionSelections;
};
#endif

View File

@ -27,6 +27,7 @@ symbology-ng/qgssymbolv2selectordialog.cpp
symbology-ng/qgsvectorgradientcolorrampv2dialog.cpp
symbology-ng/qgsvectorrandomcolorrampv2dialog.cpp
symbology-ng/qgsvectorcolorbrewercolorrampv2dialog.cpp
symbology-ng/qgscptcitycolorrampv2dialog.cpp
symbology-ng/characterwidget.cpp
symbology-ng/qgsstylev2exportimportdialog.cpp
symbology-ng/qgsellipsesymbollayerv2widget.cpp
@ -123,6 +124,7 @@ symbology-ng/qgssymbolv2selectordialog.h
symbology-ng/qgsvectorgradientcolorrampv2dialog.h
symbology-ng/qgsvectorrandomcolorrampv2dialog.h
symbology-ng/qgsvectorcolorbrewercolorrampv2dialog.h
symbology-ng/qgscptcitycolorrampv2dialog.h
symbology-ng/qgscolorrampcombobox.h
symbology-ng/characterwidget.h
symbology-ng/qgspenstylecombobox.h

View File

@ -18,6 +18,11 @@
#include "qgssinglebandpseudocolorrendererwidget.h"
#include "qgssinglebandpseudocolorrenderer.h"
#include "qgsrasterlayer.h"
// for color ramps - todo add rasterStyle and refactor raster vs. vector ramps
#include "qgsstylev2.h"
#include "qgsvectorcolorrampv2.h"
#include <QColorDialog>
#include <QFileDialog>
#include <QMessageBox>
@ -29,6 +34,8 @@ QgsSingleBandPseudoColorRendererWidget::QgsSingleBandPseudoColorRendererWidget(
{
setupUi( this );
mColorRampComboBox->populate( QgsStyleV2::defaultStyle() );
if ( !mRasterLayer )
{
return;
@ -213,19 +220,45 @@ void QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
}
}
#if 0
//hard code color range from blue -> red for now. Allow choice of ramps in future
int colorDiff = 0;
if ( numberOfEntries != 0 )
{
colorDiff = ( int )( 255 / numberOfEntries );
}
for ( int i = 0; i < numberOfEntries; ++i )
{
QColor currentColor;
currentColor.setRgb( colorDiff*i, 0, 255 - colorDiff * i );
entryColors.push_back( currentColor );
}
#endif
QgsVectorColorRampV2* colorRamp = mColorRampComboBox->currentColorRamp();
if ( ! colorRamp )
{
//hard code color range from blue -> red (previous default)
int colorDiff = 0;
if ( numberOfEntries != 0 )
{
colorDiff = ( int )( 255 / numberOfEntries );
}
for ( int i = 0; i < numberOfEntries; ++i )
{
QColor currentColor;
currentColor.setRgb( colorDiff*i, 0, 255 - colorDiff * i );
entryColors.push_back( currentColor );
}
}
else
{
for ( int i = 0; i < numberOfEntries; ++i )
{
entryColors.push_back( colorRamp->color( ( ( double ) i ) / numberOfEntries ) );
}
}
mColormapTreeWidget->clear();

View File

@ -0,0 +1,385 @@
/***************************************************************************
qgscptcitycolorrampv2dialog.cpp
---------------------
begin : July 2012
copyright : (C) 2012 by Etienne Tourigny
email : etourigny dot dev at gmail.com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgscptcitycolorrampv2dialog.h"
#include "qgsvectorcolorrampv2.h"
#include "qgslogger.h"
#include "qgsapplication.h"
#include <QPushButton>
#include <QTextEdit>
#if 0 // unused
static void updateColorButton( QAbstractButton* button, QColor color )
{
QPixmap p( 20, 20 );
p.fill( color );
button->setIcon( QIcon( p ) );
}
#endif
/////////
QgsCptCityColorRampV2Dialog::QgsCptCityColorRampV2Dialog( QgsCptCityColorRampV2* ramp, QWidget* parent )
: QDialog( parent ), mRamp( ramp )
{
setupUi( this );
QgsCptCityColorRampV2::loadSchemes( "" );
// QgsCptCityColorRampV2::loadSchemes( "cb" );
// show information on how to install cpt-city files if none are found
if ( ! QgsCptCityColorRampV2::hasAllSchemes() )
{
QTextEdit *edit = new QTextEdit();
edit->setReadOnly( true );
// not sure if we want this long string to be translated
QString helpText = tr( "Error - cpt-city gradient files not found.\n\n"
"Please download the complete collection (in svg format) "
"and unzip it to your QGis settings directory [%1] .\n\n"
"This file can be found at [%2]\nand current file is [%3]"
).arg( QgsApplication::qgisSettingsDirPath()
).arg( "http://soliton.vm.bytemark.co.uk/pub/cpt-city/pkg/"
).arg( "http://soliton.vm.bytemark.co.uk/pub/cpt-city/pkg/cpt-city-svg-2.02.zip" );
edit->setText( helpText );
stackedWidget->addWidget( edit );
stackedWidget->setCurrentIndex( 1 );
buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
return;
}
populateSchemes( "author" );
treeWidget->setCurrentItem( findPath( ramp->schemeName() ) );
populateVariants();
cboVariantName->setCurrentIndex( cboVariantName->findData( ramp->variantName(), Qt::UserRole ) );
connect( cboVariantName, SIGNAL( currentIndexChanged( int ) ), this, SLOT( setVariantName() ) );
updatePreview();
}
// inspired from QgsBrowserModel::findPath( QString path )
// but using a QTreeWidget instead of QgsBrowserModel
// would be simpler if we used the model/view framework
QTreeWidgetItem* QgsCptCityColorRampV2Dialog::findPath( QString path )
{
QTreeWidgetItem *item = 0, *childItem = 0;
QString itemPath, childPath;
for ( int i = 0; i < treeWidget->topLevelItemCount(); i++ )
{
item = treeWidget->topLevelItem( i );
if ( !item )
return 0; // an error occurred
itemPath = item->data( 0, Qt::UserRole ).toString();
if ( itemPath == path )
{
QgsDebugMsg( "Arrived " + itemPath );
return item; // we have found the item we have been looking for
}
if ( itemPath.endsWith( "/" ) && path.startsWith( itemPath ) )
{
// we have found a preceding item: stop searching on this level and go deeper
bool foundChild = true;
while ( foundChild )
{
foundChild = false; // assume that the next child item will not be found
for ( int j = 0; j < item->childCount(); j++ )
{
childItem = item->child( j );
if ( !childItem )
return 0; // an error occurred
childPath = childItem->data( 0, Qt::UserRole ).toString();
if ( childPath == path )
{
return childItem; // we have found the item we have been looking for
}
if ( childPath.endsWith( "/" ) && path.startsWith( childPath ) )
{
// we have found a preceding item: stop searching on this level and go deeper
foundChild = true;
item = childItem;
break;
}
}
}
break;
}
}
return 0; // not found
}
void QgsCptCityColorRampV2Dialog::populateSchemes( QString view )
{
QStringList collections;
QTreeWidgetItem *item, *childItem;
if ( view == "author" )
{
treeWidget->blockSignals( true );
treeWidget->clear();
foreach( QString collectionName, QgsCptCityColorRampV2::listSchemeCollections() )
{
item = makeCollectionItem( collectionName );
treeWidget->addTopLevelItem( item );
}
treeWidget->blockSignals( false );
}
else if ( view == "selections" )
{
treeWidget->blockSignals( true );
treeWidget->clear();
QMapIterator< QString, QStringList> it( QgsCptCityColorRampV2::collectionSelections() );
while ( it.hasNext() )
{
it.next();
QString path = it.key();
QString descStr = QgsCptCityColorRampV2::collectionNames().value( path );
// TODO shorten child names and fix / at beginning of name
// TODO when collection has only 1 item (e.g. es_skywalker), bring up one level
item = new QTreeWidgetItem( QStringList() << path << descStr << QString() );
QFont font;
font.setBold( true );
item->setData( 0, Qt::FontRole, QVariant( font ) );
item->setData( 1, Qt::FontRole, QVariant( font ) );
// add children schemes and collections
foreach( QString childPath, it.value() )
{
if ( childPath.endsWith( "/" ) )
{
childPath.chop( 1 );
childItem = makeCollectionItem( childPath );
childItem->setText( 0, childPath ); //make sure full path is visible
item->addChild( childItem );
}
else
{
makeSchemeItem( item, "", childPath );
}
}
treeWidget->addTopLevelItem( item );
}
treeWidget->blockSignals( false );
}
else
{
QgsDebugMsg( "invalid view " + view );
return;
}
treeWidget->setColumnWidth( 0, 250 );
}
void QgsCptCityColorRampV2Dialog::populateVariants()
{
if ( ! treeWidget->currentItem() )
return;
cboVariantName->blockSignals( true );
QString oldVariant = cboVariantName->currentText();
cboVariantName->clear();
foreach( QString variant, treeWidget->currentItem()->data( 1, Qt::UserRole ).toString().split( " ", QString::SkipEmptyParts ) )
{
QString variantStr = variant;
if ( variantStr.startsWith( "-" ) || variantStr.startsWith( "_" ) )
variantStr.remove( 0, 1 );
cboVariantName->addItem( variantStr );
cboVariantName->setItemData( cboVariantName->count() - 1, variant, Qt::UserRole );
}
cboVariantName->blockSignals( false );
if ( cboVariantName->count() > 0 )
{
cboVariantName->setEnabled( true );
// try to set the original variant again (if exists)
// TODO - is this really necessary?
int idx = cboVariantName->findText( oldVariant );
if ( idx == -1 ) // not found?
{
// use the item in the middle
idx = cboVariantName->count() / 2;
}
cboVariantName->setCurrentIndex( idx );
}
else
{
cboVariantName->setEnabled( false );
setVariantName();
}
}
void QgsCptCityColorRampV2Dialog::on_treeWidget_currentItemChanged( QTreeWidgetItem * current, QTreeWidgetItem * previous )
{
Q_UNUSED( previous );
// directories have name data that ends with /
if ( ! current->data( 0, Qt::UserRole ).toString().endsWith( "/" ) )
{
lblSchemeName->setText( current->data( 0, Qt::UserRole ).toString() );
setSchemeName();
// populateVariants();
}
}
void QgsCptCityColorRampV2Dialog::on_treeWidget_itemExpanded( QTreeWidgetItem * item )
{
// set color count when item is expanded
QgsCptCityColorRampV2 ramp( "", "" );
QTreeWidgetItem* childItem = 0;
QString itemPath, itemDesc;
for ( int i = 0; i < item->childCount(); i++ )
{
childItem = item->child( i );
// items with null description need information, those with "" (i.e. unnamed collections) not be checked
// TODO set type when there are variants - based on the first file
if ( childItem && childItem->text( 1 ).isNull() )
{
itemPath = childItem->data( 0, Qt::UserRole ).toString();
itemDesc = "";
ramp.setSchemeName( itemPath );
if ( ramp.loadFile() )
{
itemDesc = QString::number( ramp.count() ) + " " + tr( "colors" ) + " - ";
if ( ramp.isContinuous() )
itemDesc += tr( "continuous" );
else
itemDesc += tr( "discrete" );
}
childItem->setText( 1, " " + itemDesc );
}
}
}
void QgsCptCityColorRampV2Dialog::on_buttonGroupView_buttonClicked( QAbstractButton * button )
{
if ( button->objectName() == "rbtnAuthor" )
{
populateSchemes( "author" );
}
else if ( button->objectName() == "rbtnSelections" )
{
populateSchemes( "selections" );
}
else
{
QgsDebugMsg( "invalid button " + button->objectName() );
}
}
void QgsCptCityColorRampV2Dialog::updatePreview()
{
QSize size( 300, 40 );
mRamp->loadFile();
lblPreview->setPixmap( QgsSymbolLayerV2Utils::colorRampPreviewPixmap( mRamp, size ) );
}
void QgsCptCityColorRampV2Dialog::setSchemeName()
{
if ( treeWidget->currentItem() )
{
mRamp->setSchemeName( treeWidget->currentItem()->data( 0, Qt::UserRole ).toString() );
// setVariantName();
// populate list of variants
populateVariants();
// updatePreview();
}
}
void QgsCptCityColorRampV2Dialog::setVariantName()
{
mRamp->setVariantName( cboVariantName->itemData( cboVariantName->currentIndex(), Qt::UserRole ).toString() );
updatePreview();
}
/* collection items have columns name / path/ and desc/null */
QTreeWidgetItem * QgsCptCityColorRampV2Dialog::makeCollectionItem( const QString& path )
{
// add root item
QString descStr = QgsCptCityColorRampV2::collectionNames().value( path );
if ( descStr.isNull() )
descStr = "";
QTreeWidgetItem *item = new QTreeWidgetItem( QStringList() << QFileInfo( path ).baseName() << descStr );
item->setData( 0, Qt::UserRole, QString( path ) + "/" ); // add / to end to identify it as a collection item
//set collections bold to identify them
QFont font;
font.setBold( true );
item->setData( 0, Qt::FontRole, QVariant( font ) );
item->setData( 1, Qt::FontRole, QVariant( font ) );
// add children collections
QTreeWidgetItem *childItem;
foreach( QString childPath, QgsCptCityColorRampV2::listSchemeCollections( path ) )
{
childItem = makeCollectionItem( childPath );
item->addChild( childItem );
}
// add children schemes
foreach( QString schemeName, QgsCptCityColorRampV2::schemeMap().value( path ) )
{
makeSchemeItem( item, path, schemeName );
}
return item;
}
/* scheme items have columns 0 = ( name / path ) and
[if has variants] 1 = ( #variants / variants )
[if has colors] 1 = ( null / null ) which becomes ( <info> / null ) after populating
*/
void QgsCptCityColorRampV2Dialog::makeSchemeItem( QTreeWidgetItem *item, const QString& path, const QString& schemeName )
{
QString descStr, descData;//, variantStr;
QString curName, curVariant;
QStringList listVariant;
QTreeWidgetItem *childItem;
// // descStr = schemeName;
listVariant = QgsCptCityColorRampV2::schemeVariants().value( path + "/" + schemeName );
if ( listVariant.count() > 1 )
{
// variantStr = QString::number( listVariant.count() ) + " " + tr( "variants" );
descStr = " " + QString::number( listVariant.count() ) + " " + tr( "variants" );
descData = listVariant.join( " " );
}
childItem = new QTreeWidgetItem( QStringList() << schemeName << descStr );
childItem->setData( 0, Qt::UserRole, path + "/" + schemeName );
if ( ! descData.isNull() )
childItem->setData( 1, Qt::UserRole, descData );
item->addChild( childItem );
// create a preview icon using five color variant
// QgsCptCityColorRampV2* r = new QgsCptCityColorRampV2( schemeName, 5 );
// QIcon icon = QgsSymbolLayerV2Utils::colorRampPreviewIcon( r, iconSize );
// delete r;
}

View File

@ -0,0 +1,53 @@
/***************************************************************************
qgscptcitycolorrampv2dialog.h
---------------------
begin : July 2012
copyright : (C) 2012 by Etienne Tourigny
email : etourigny dot dev at gmail.com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSCPTCITYCOLORRAMPV2DIALOG_H
#define QGSCPTCITYCOLORRAMPV2DIALOG_H
#include <QDialog>
#include "ui_qgscptcitycolorrampv2dialogbase.h"
class QgsCptCityColorRampV2;
class GUI_EXPORT QgsCptCityColorRampV2Dialog : public QDialog, private Ui::QgsCptCityColorRampV2DialogBase
{
Q_OBJECT
public:
QgsCptCityColorRampV2Dialog( QgsCptCityColorRampV2* ramp, QWidget* parent = NULL );
public slots:
void setSchemeName();
void setVariantName();
void populateSchemes( QString view = "author" );
void populateVariants();
void on_treeWidget_currentItemChanged( QTreeWidgetItem * current, QTreeWidgetItem * previous );
void on_treeWidget_itemExpanded( QTreeWidgetItem * item );
void on_buttonGroupView_buttonClicked ( QAbstractButton * button );
protected:
void updatePreview();
QTreeWidgetItem* findPath( QString path );
QTreeWidgetItem * makeCollectionItem( const QString& path );
// TODO rename Scheme to something else, maybe data
void makeSchemeItem( QTreeWidgetItem *item, const QString& path, const QString& schemeName );
QgsCptCityColorRampV2* mRamp;
};
#endif

View File

@ -24,6 +24,7 @@
#include "qgsvectorgradientcolorrampv2dialog.h"
#include "qgsvectorrandomcolorrampv2dialog.h"
#include "qgsvectorcolorbrewercolorrampv2dialog.h"
#include "qgscptcitycolorrampv2dialog.h"
#include "qgsstylev2exportimportdialog.h"
#include <QFile>
@ -302,6 +303,7 @@ QString QgsStyleV2ManagerDialog::addColorRampStatic( QWidget* parent, QgsStyleV2
// let the user choose the color ramp type
QStringList rampTypes;
rampTypes << tr( "Gradient" ) << tr( "Random" ) << tr( "ColorBrewer" );
rampTypes << tr( "cpt-city" ); // todo, only for rasters?
bool ok;
QString rampType = QInputDialog::getItem( parent, tr( "Color ramp type" ),
tr( "Please select color ramp type:" ), rampTypes, 0, false, &ok );
@ -342,9 +344,23 @@ QString QgsStyleV2ManagerDialog::addColorRampStatic( QWidget* parent, QgsStyleV2
}
ramp = brewerRamp;
}
else if ( rampType == tr( "cpt-city" ) )
{
QgsCptCityColorRampV2* cptCityRamp = new QgsCptCityColorRampV2();
QgsCptCityColorRampV2Dialog dlg( cptCityRamp, parent );
if ( !dlg.exec() )
{
delete cptCityRamp;
return QString();
}
ramp = cptCityRamp;
}
else
{
Q_ASSERT( 0 && "invalid ramp type" );
// Q_ASSERT( 0 && "invalid ramp type" );
// bailing out is rather harsh!
QgsDebugMsg( "invalid ramp type " + rampType );
return QString();
}
// get name
@ -456,6 +472,16 @@ bool QgsStyleV2ManagerDialog::editColorRamp()
return false;
}
}
else if ( ramp->type() == "cpt-city" )
{
QgsCptCityColorRampV2* cptCityRamp = static_cast<QgsCptCityColorRampV2*>( ramp );
QgsCptCityColorRampV2Dialog dlg( cptCityRamp, this );
if ( !dlg.exec() )
{
delete ramp;
return false;
}
}
else
{
Q_ASSERT( 0 && "invalid ramp type" );

View File

@ -0,0 +1,298 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsCptCityColorRampV2DialogBase</class>
<widget class="QDialog" name="QgsCptCityColorRampV2DialogBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>807</width>
<height>503</height>
</rect>
</property>
<property name="windowTitle">
<string>cpt-city color ramp</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>View</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="rbtnAuthor">
<property name="text">
<string>All by author</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroupView</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbtnSelections">
<property name="text">
<string>Selections by theme</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroupView</string>
</attribute>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTreeWidget" name="treeWidget">
<attribute name="headerStretchLastSection">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Info</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QGridLayout" name="_2">
<item row="1" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Variant</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Scheme name</string>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>71</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QLabel" name="lblSchemeName">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QComboBox" name="cboVariantName">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Preview</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="lblPreview">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QgsCptCityColorRampV2DialogBase</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>258</x>
<y>281</y>
</hint>
<hint type="destinationlabel">
<x>168</x>
<y>256</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QgsCptCityColorRampV2DialogBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>363</x>
<y>273</y>
</hint>
<hint type="destinationlabel">
<x>371</x>
<y>259</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="buttonGroupView"/>
</buttongroups>
</ui>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>505</width>
<width>584</width>
<height>400</height>
</rect>
</property>
@ -146,7 +146,7 @@
<item row="0" column="0">
<widget class="QLabel" name="mNumberOfEntriesLabel">
<property name="text">
<string>Number of entries</string>
<string>Classes</string>
</property>
</widget>
</item>
@ -163,28 +163,84 @@
</property>
</widget>
</item>
<item row="0" column="2">
<item row="0" column="3">
<widget class="QLabel" name="mClassificationModeLabel">
<property name="text">
<string>Classification mode</string>
<string>Mode</string>
</property>
</widget>
</item>
<item row="0" column="3">
<item row="0" column="4">
<widget class="QComboBox" name="mClassificationModeComboBox"/>
</item>
<item row="0" column="4">
<item row="0" column="9">
<widget class="QPushButton" name="mClassifyButton">
<property name="text">
<string>Classify</string>
</property>
</widget>
</item>
<item row="0" column="5">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="6">
<widget class="QLabel" name="label">
<property name="text">
<string>Color ramp</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="7">
<widget class="QgsColorRampComboBox" name="mColorRampComboBox"/>
</item>
<item row="0" column="8">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsColorRampComboBox</class>
<extends>QComboBox</extends>
<header>qgscolorrampcombobox.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../images/images.qrc"/>
</resources>

View File

@ -97,3 +97,4 @@ ADD_QGIS_TEST(rulebasedrenderertest testqgsrulebasedrenderer.cpp)
ADD_QGIS_TEST(ziplayertest testziplayer.cpp)
ADD_QGIS_TEST(dataitemtest testqgsdataitem.cpp)
ADD_QGIS_TEST(composermaptest testqgscomposermap.cpp)
ADD_QGIS_TEST(stylev2test testqgsstylev2.cpp)

View File

@ -35,6 +35,7 @@
#include <qgsmaprenderer.h>
#include <qgsmaplayerregistry.h>
#include "qgssinglebandpseudocolorrenderer.h"
#include "qgsvectorcolorrampv2.h"
//qgis unit test includes
#include <qgsrenderchecker.h>
@ -54,6 +55,9 @@ class TestQgsRasterLayer: public QObject
void isValid();
void pseudoColor();
void colorRamp1();
void colorRamp2();
void colorRamp3();
void landsatBasic();
void landsatBasic875Qml();
void checkDimensions();
@ -63,6 +67,11 @@ class TestQgsRasterLayer: public QObject
private:
bool render( QString theFileName );
bool setQml( QString theType );
void populateColorRampShader( QgsColorRampShader* colorRampShader,
QgsVectorColorRampV2* colorRamp,
int numberOfEntries );
bool testColorRamp( QString name, QgsVectorColorRampV2* colorRamp,
QgsColorRampShader::ColorRamp_TYPE type, int numberOfEntries );
QString mTestDataDir;
QgsRasterLayer * mpRasterLayer;
QgsRasterLayer * mpLandsatRasterLayer;
@ -162,6 +171,95 @@ void TestQgsRasterLayer::pseudoColor()
QVERIFY( render( "raster_pseudo" ) );
}
void TestQgsRasterLayer::populateColorRampShader( QgsColorRampShader* colorRampShader,
QgsVectorColorRampV2* colorRamp,
int numberOfEntries )
{
// adapted from QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
// and TestQgsRasterLayer::pseudoColor()
// would be better to add a more generic function to api that does this
int bandNr = 1;
QgsRasterBandStats myRasterBandStats = mpRasterLayer->dataProvider()->bandStatistics( bandNr );
QList<double> entryValues;
QList<QColor> entryColors;
double currentValue = myRasterBandStats.minimumValue;
double intervalDiff;
if ( numberOfEntries > 1 )
{
//because the highest value is also an entry, there are (numberOfEntries - 1)
//intervals
intervalDiff = ( myRasterBandStats.maximumValue - myRasterBandStats.minimumValue ) /
( numberOfEntries - 1 );
}
else
{
intervalDiff = myRasterBandStats.maximumValue - myRasterBandStats.minimumValue;
}
for ( int i = 0; i < numberOfEntries; ++i )
{
entryValues.push_back( currentValue );
currentValue += intervalDiff;
entryColors.push_back( colorRamp->color((( double ) i ) / numberOfEntries ) );
}
//items to imitate old pseudo color renderer
QList<QgsColorRampShader::ColorRampItem> colorRampItems;
QList<double>::const_iterator value_it = entryValues.begin();
QList<QColor>::const_iterator color_it = entryColors.begin();
for ( ; value_it != entryValues.end(); ++value_it, ++color_it )
{
colorRampItems.append( QgsColorRampShader::ColorRampItem( *value_it, *color_it ) );
}
colorRampShader->setColorRampItemList( colorRampItems );
}
bool TestQgsRasterLayer::testColorRamp( QString name, QgsVectorColorRampV2* colorRamp,
QgsColorRampShader::ColorRamp_TYPE type, int numberOfEntries )
{
QgsRasterShader* rasterShader = new QgsRasterShader();
QgsColorRampShader* colorRampShader = new QgsColorRampShader();
colorRampShader->setColorRampType( type );
populateColorRampShader( colorRampShader, colorRamp, numberOfEntries );
rasterShader->setRasterShaderFunction( colorRampShader );
QgsSingleBandPseudoColorRenderer* r = new QgsSingleBandPseudoColorRenderer( mpRasterLayer->dataProvider(), 1, rasterShader );
mpRasterLayer->setRenderer( r );
mpMapRenderer->setExtent( mpRasterLayer->extent() );
return render( name );
}
void TestQgsRasterLayer::colorRamp1()
{
// gradient ramp
QgsVectorGradientColorRampV2* colorRamp = new QgsVectorGradientColorRampV2( QColor( Qt::red ), QColor( Qt::black ) );
QgsVectorGradientColorRampV2::StopsMap stops;
stops[ 0.5 ] = QColor( Qt::white );
colorRamp->setStops( stops );
// QVERIFY( testColorRamp( "raster_colorRamp1", colorRamp, QgsColorRampShader::INTERPOLATED, 5 ) );
QVERIFY( testColorRamp( "raster_colorRamp1", colorRamp, QgsColorRampShader::DISCRETE, 10 ) );
}
void TestQgsRasterLayer::colorRamp2()
{
// ColorBrewer ramp
QVERIFY( testColorRamp( "raster_colorRamp2",
new QgsVectorColorBrewerColorRampV2( "BrBG", 10 ),
QgsColorRampShader::DISCRETE, 10 ) );
}
void TestQgsRasterLayer::colorRamp3()
{
// cpt-city ramp
QVERIFY( testColorRamp( "raster_colorRamp3",
new QgsCptCityColorRampV2( "gmt/GMT_panoply", "" ),
QgsColorRampShader::DISCRETE, 10 ) );
}
void TestQgsRasterLayer::landsatBasic()
{
mpLandsatRasterLayer->setContrastEnhancementAlgorithm( QgsContrastEnhancement::StretchToMinimumMaximum, false );

View File

@ -0,0 +1,209 @@
/***************************************************************************
testqgsstylev2.cpp
--------------------------------------
Date : Wed Aug 1 12:13:24 BRT 2012
Copyright : (C) 2012 Etienne Tourigny and Tim Sutton
Email : etourigny dot dev at gmail.com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QtTest>
#include <QObject>
#include <QStringList>
#include <QObject>
#include <QApplication>
#include <QFileInfo>
//qgis includes...
#include <qgsapplication.h>
#include "qgsconfig.h"
#include "qgslogger.h"
#include "qgsvectorcolorrampv2.h"
#include "qgsstylev2.h"
/** \ingroup UnitTests
* This is a unit test to verify that styles are working correctly
*/
class TestStyleV2: public QObject
{
Q_OBJECT;
private:
QgsStyleV2 *mStyle;
bool testValidColor( QgsVectorColorRampV2 *ramp, double value, QColor expected );
private slots:
// init / cleanup
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init() {};// will be called before each testfunction is executed.
void cleanup() {};// will be called after every testfunction.
// void initStyles();
void testCreateColorRamps();
void testLoadColorRamps();
void testSaveLoad();
};
// slots
void TestStyleV2::initTestCase()
{
// initialize with test directory so we don't mess with user's stuff
QgsApplication::init( QDir::homePath() + QString( "/.qgis_test" ) );
QgsApplication::initQgis();
// output test environment
QgsApplication::showSettings();
// Set up the QSettings environment
QCoreApplication::setOrganizationName( "QuantumGIS" );
QCoreApplication::setOrganizationDomain( "qgis.org" );
QCoreApplication::setApplicationName( "QGIS-TEST" );
// initialize with a clean style
QFile styleFile( QgsApplication::userStyleV2Path() );
if ( styleFile.exists() )
{
styleFile.remove();
QgsDebugMsg( "removed user style file " + styleFile.fileName() );
}
mStyle = QgsStyleV2::defaultStyle();
// mStyle->clear();
}
void TestStyleV2::cleanupTestCase()
{
// don't save
// mStyle->save();
delete mStyle;
}
bool TestStyleV2::testValidColor( QgsVectorColorRampV2 *ramp, double value, QColor expected )
{
QColor result = ramp->color( value );
if ( result != expected )
{
QWARN( QString( "value = %1 result = %2 expected = %3" ).arg( value ).arg(
result.name() ).arg( expected.name() ).toLocal8Bit().data() );
return false;
}
return true;
}
void TestStyleV2::testCreateColorRamps()
{
// gradient ramp
QgsVectorGradientColorRampV2* gradientRamp = new QgsVectorGradientColorRampV2( QColor( Qt::red ), QColor( Qt::blue ) );
QgsVectorGradientColorRampV2::StopsMap stops;
stops[ 0.5 ] = QColor( Qt::white );
gradientRamp->setStops( stops );
QVERIFY( mStyle->addColorRamp( "test_gradient", gradientRamp ) == true );
// random ramp
QgsVectorRandomColorRampV2* randomRamp = new QgsVectorRandomColorRampV2();
QVERIFY( mStyle->addColorRamp( "test_random", randomRamp ) == true );
// color brewer ramp
QgsVectorColorBrewerColorRampV2* cb1Ramp = new QgsVectorColorBrewerColorRampV2();
QVERIFY( mStyle->addColorRamp( "test_cb1", cb1Ramp ) == true );
QgsVectorColorBrewerColorRampV2* cb2Ramp = new QgsVectorColorBrewerColorRampV2( "RdYlGn", 6 );
QVERIFY( mStyle->addColorRamp( "test_cb2", cb2Ramp ) == true );
// cpt-city ramp - use gradients that are free to distribute
// set base dir because we are using a test home path - change this if we distribute a minimal set with qgis
QgsCptCityColorRampV2::setBaseDir( QDir::homePath() + QString( "/.qgis/cpt-city" ) );
QgsCptCityColorRampV2::loadSchemes( "" );
if ( QgsCptCityColorRampV2::hasBasicSchemes() )
{
QgsCptCityColorRampV2* cc1Ramp = new QgsCptCityColorRampV2( "jjg/misc/temperature", "" );
QVERIFY( mStyle->addColorRamp( "test_cc1", cc1Ramp ) == true );
QgsCptCityColorRampV2* cc2Ramp = new QgsCptCityColorRampV2( "cb/div/PiYG", "_10" );
QVERIFY( mStyle->addColorRamp( "test_cc2", cc2Ramp ) == true );
}
else
{
QWARN( "cpt-city support files not found - skipping cpt-city color ramp tests" );
}
}
void TestStyleV2::testLoadColorRamps()
{
QStringList colorRamps = mStyle->colorRampNames();
QStringList colorRampsTest = QStringList() << "BrBG" << "Spectral"
<< "test_gradient" << "test_random"
<< "test_cb1" << "test_cb2";
// values for color tests
QMultiMap< QString, QPair< double, QColor> > colorTests;
colorTests.insert( "test_gradient", qMakePair( 0.25, QColor( "#ff7f7f" ) ) );
colorTests.insert( "test_gradient", qMakePair( 0.66, QColor( "#adadff" ) ) );
// cannot test random colors!
colorTests.insert( "test_cb1", qMakePair( 0.25, QColor( "#fdae61" ) ) );
colorTests.insert( "test_cb1", qMakePair( 0.66, QColor( "#abdda4" ) ) );
colorTests.insert( "test_cb2", qMakePair( 0.25, QColor( "#fc8d59" ) ) );
colorTests.insert( "test_cb2", qMakePair( 0.66, QColor( "#d9ef8b" ) ) );
// cpt-city
if ( QgsCptCityColorRampV2::hasAllSchemes() )
{
colorRampsTest << "test_cc1";
colorTests.insert( "test_cc1", qMakePair( 0.25, QColor( "#466fcf" ) ) );
colorTests.insert( "test_cc1", qMakePair( 0.66, QColor( "#dbc85b" ) ) );
colorRampsTest << "test_cc2";
colorTests.insert( "test_cc2", qMakePair( 0.25, QColor( "#de77ae" ) ) );
colorTests.insert( "test_cc2", qMakePair( 0.66, QColor( "#b8e186" ) ) );
}
foreach( QString name, colorRampsTest )
{
QgsDebugMsg( "colorRamp " + name );
QVERIFY( colorRamps.contains( name ) );
QgsVectorColorRampV2* ramp = mStyle->colorRamp( name );
QVERIFY( ramp != 0 );
// test colors
if ( colorTests.contains( name ) )
{
QList< QPair< double, QColor> > values = colorTests.values( name );
for ( int i = 0; i < values.size(); ++i )
{
QVERIFY( testValidColor( ramp, values.at( i ).first, values.at( i ).second ) );
}
}
if ( ramp )
delete ramp;
}
}
void TestStyleV2::testSaveLoad()
{
mStyle->save();
mStyle->clear();
mStyle->load( QgsApplication::userStyleV2Path() );
QStringList colorRamps = mStyle->colorRampNames();
QStringList colorRampsTest = QStringList() << "test_gradient";
foreach( QString name, colorRampsTest )
{
QgsDebugMsg( "colorRamp " + name );
QVERIFY( colorRamps.contains( name ) );
QgsVectorColorRampV2* ramp = mStyle->colorRamp( name );
QVERIFY( ramp != 0 );
if ( ramp )
delete ramp;
}
}
QTEST_MAIN( TestStyleV2 )
#include "moc_testqgsstylev2.cxx"

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,2 +0,0 @@
compressed_size=660
uncompressed_size=3328