Index: src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
===================================================================
--- src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp	(revision 14280)
+++ src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp	(working copy)
@@ -192,7 +192,13 @@
   QgsGraduatedSymbolRendererV2::Mode mode;
   if ( cboGraduatedMode->currentIndex() == 0 )
     mode = QgsGraduatedSymbolRendererV2::EqualInterval;
-  else
+  else if ( cboGraduatedMode->currentIndex() == 2 )
+    mode = QgsGraduatedSymbolRendererV2::Jenks;
+  else if ( cboGraduatedMode->currentIndex() == 3 )
+    mode = QgsGraduatedSymbolRendererV2::StdDev;
+  else if ( cboGraduatedMode->currentIndex() == 4 )
+    mode = QgsGraduatedSymbolRendererV2::Pretty;
+  else // default should be quantile for now
     mode = QgsGraduatedSymbolRendererV2::Quantile;
 
   // create and set new renderer
Index: src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h
===================================================================
--- src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h	(revision 14280)
+++ src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h	(working copy)
@@ -74,6 +74,9 @@
     {
       EqualInterval,
       Quantile,
+      Jenks,
+      StdDev,
+      Pretty,
       Custom
     };
 
Index: src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
===================================================================
--- src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp	(revision 14280)
+++ src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp	(working copy)
@@ -12,6 +12,8 @@
 #include <QDomDocument>
 #include <QDomElement>
 #include <QSettings> // for legend
+#include <limits> // for jenks classification
+#include "math.h" // for pretty classification
 
 QgsRendererRangeV2::QgsRendererRangeV2( double lowerValue, double upperValue, QgsSymbolV2* symbol, QString label )
     : mLowerValue( lowerValue ), mUpperValue( upperValue ), mSymbol( symbol ), mLabel( label )
@@ -273,6 +275,12 @@
 
 static QList<double> _calcEqualIntervalBreaks( double minimum, double maximum, int classes )
 {
+
+  // Equal interval algorithm
+  //
+  // Returns breaks based on dividing the range ('minimum' to 'maximum')
+  // into 'classes' parts.
+
   double step = ( maximum - minimum ) / classes;
 
   QList<double> breaks;
@@ -287,11 +295,7 @@
 
 static QList<double> _calcQuantileBreaks( QList<double> values, int classes )
 {
-  // sort the values first
-  qSort( values );
 
-  QList<double> breaks;
-
   // q-th quantile of a data set:
   // value where q fraction of data is below and (1-q) fraction is above this value
   // Xq = (1 - r) * X_NI1 + r * X_NI2
@@ -300,6 +304,11 @@
   //   r = q * (n+1) - (int) (q * (n+1))
   // (indices of X: 1...n)
 
+  // sort the values first
+  qSort( values );
+
+  QList<double> breaks;
+
   int n = values.count();
   double q, a, aa, r, Xq;
   for ( int i = 0; i < ( classes - 1 ); i++ )
@@ -319,6 +328,332 @@
   return breaks;
 }
 
+static QList<double> _calcPrettyBreaks( double minimum, double maximum, int classes )
+{
+
+  // C++ implementation of R's pretty algorithm
+  // Based on code for determining optimal tick placement for statistical graphics
+  // from the R statistical programming language.
+  // Code ported from R implementation from 'labeling' R package
+  //
+  // Computes a sequence of about 'classes' equally spaced 'round' values
+  // which cover the range of of values from 'minimum' to 'maximum'.
+  // The values are chosen so that they are 1, 2 or 5 times a power of 10.
+
+  QList<double> breaks;
+  if ( classes < 1 )
+  {
+      breaks.append( maximum );
+      return breaks;
+  }
+
+  int min_n = (int) classes / 3;
+  double shrink_sml = 0.75;
+  double high_u_bias = 1.5;
+  double u5_bias = 0.5 + 1.5 * high_u_bias;
+  int ndiv = classes;
+  double h = high_u_bias;
+  double h5 = u5_bias;
+  double cell;
+  int U;
+  bool i_small = false;
+  double dx = maximum - minimum;
+
+  if ( dx == 0 and maximum == 0 )
+  {
+    cell = 1.0;
+    i_small = true;
+    U = 1;
+  }
+  else
+  {
+    cell = qMax( qAbs( minimum ), qAbs( maximum ) );
+    if ( h5 >= 1.5 * h + 0.5 )
+    {
+      U = 1 + (1.0/(1 + h));
+    }
+    else
+    {
+      U = 1 + (1.5 / (1 + h5));
+    }
+    i_small = dx < ( cell * U * qMax( 1, ndiv ) * 1e-07 * 3.0 );
+  }
+
+  if ( i_small )
+  {
+    if ( cell > 10 )
+    {
+      cell = 9 + cell / 10;
+      cell = cell * shrink_sml;
+    }
+    if ( min_n > 1 )
+    {
+      cell = cell / min_n;
+    }
+  }
+  else
+  {
+    cell = dx;
+    if ( ndiv > 1 )
+    {
+      cell = cell / ndiv;
+    }
+  }
+  if ( cell < 20 * 1e-07 )
+  {
+    cell = 20 * 1e-07;
+  }
+
+  double base = pow( 10.0, floor( log10( cell ) ) );
+  double unit = base;
+  if ( ( 2 * base ) - cell < h * ( cell - unit ) )
+  {
+    unit = 2.0 * base;
+    if ( ( 5 * base ) - cell < h5 * ( cell - unit ) )
+    {
+      unit = 5.0 * base;
+      if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
+      {
+        unit = 10.0 * base;
+      }
+    }
+  }
+  // Maybe used to correct for the epsilon here??
+  int ns = floor( minimum / unit + 1e-07 );
+  int nu = ceil( maximum / unit - 1e-07 );
+
+  // Extend the range out beyond the data. Does this ever happen??
+  while ( ns * unit > minimum + ( 1e-07 * unit ) )
+  {
+    ns = ns - 1;
+  }
+  while ( nu * unit < maximum - ( 1e-07 * unit ) )
+  {
+    nu = nu + 1;
+  }
+  QgsDebugMsg( QString( "pretty classes: %1" ).arg( nu ) );
+  // If we don't have quite enough labels, extend the range out
+  // to make more (these labels are beyond the data :( )
+  int k = floor( 0.5 + nu - ns );
+  if ( k < min_n )
+  {
+    k = min_n - k;
+    if ( ns >= 0 )
+    {
+      nu = nu + k / 2;
+      ns = ns - k / 2 + k % 2;
+    }
+    else
+    {
+      ns = ns - k / 2;
+      nu = nu + k / 2 + k % 2;
+    }
+    ndiv = min_n;
+  }
+  else
+  {
+    ndiv = k;
+  }
+  double graphmin = ns * unit;
+  double graphmax = nu * unit;
+  int count = ceil( graphmax - graphmin ) / unit;
+
+  for ( int i = 1; i < count+1; i++ )
+  {
+    breaks.append( graphmin + i * unit );
+  }
+
+  if ( breaks.first() < minimum )
+  {
+    breaks[0] = minimum;
+  }
+  if ( breaks.last() > maximum )
+  {
+    breaks[breaks.count()-1] = maximum;
+  }
+  return breaks;
+}
+
+
+static QList<double> _calcStdDevBreaks( QList<double> values, int classes )
+{
+
+  // C++ implementation of the standard deviation class interval algorithm
+  // as implemented in the 'classInt' package available for the R statistical
+  // prgramming language.
+
+  // Returns breaks based on '_calcPrettyBreaks' of the centred and scaled
+  // values of 'values', and may have a number of classes different from 'classes'.
+
+  double mean = 0.0;
+  double sd2 = 0.0;
+  int n = values.count();
+  double min = values[0];
+  double max = values[0];
+
+  for ( int i = 0; i < n; i++ )
+  {
+    mean += values[i];
+    min = qMin( values[i], min ); // could use precomputed max and min
+    max = qMax( values[i], max ); // but have to go through entire list anyway
+  }
+  mean = mean / (double) n;
+
+  double sd;
+  for ( int i = 0; i < n; i++ )
+  {
+    sd = values[i] - mean;
+    sd2 += sd * sd;
+  }
+  sd2 = sqrt( sd2 / n );
+
+  QList<double> breaks = _calcPrettyBreaks( ( min - mean ) / sd2, ( max - mean ) / sd2, classes );
+  for ( int i = 0; i < breaks.count(); i++ )
+  {
+    breaks[i] = ( breaks[i] * sd2 ) + mean;
+  }
+
+  return breaks;
+}
+
+static QList<double> _calcJenksBreaks( QList<double> values, int classes,
+                                       double minimum, double maximum,
+                                       int maxsize = 1000 )
+{
+
+  // Jenks Optimal (Natural Breaks) algorithm
+  // Based on the Jenks algorithm from the 'classInt' package available for
+  // the R statistical prgramming language, and from Python code from here:
+  // http://danieljlewis.org/2010/06/07/jenks-natural-breaks-algorithm-in-python/
+  // and is based on a JAVA and Fortran code available here:
+  // https://stat.ethz.ch/pipermail/r-sig-geo/2006-March/000811.html
+
+  // Returns class breaks such that classes are internally homogeneous while
+  // assuring heterogeneity among classes.
+
+  QList<double> breaks;
+  if ( classes < 1 )
+  {
+      breaks.append( maximum );
+      return breaks;
+  }
+
+  int n = values.count();
+  QList<double> sample;
+
+  // if we have lots of values, we need to take a random sample
+  if ( n > maxsize )
+  {
+      n = qMin( maxsize, qMax( maxsize, (int) ((double) n*0.10 )) );
+      QgsDebugMsg( QString( "natural breaks (jenks) sample size: %1" ).arg( n ) );
+    sample.append( minimum );
+    sample.append( maximum );
+    for ( int i = 0; i < n-2; i++ )
+    {
+      int c = (int) ( (double) rand() / ( (double) RAND_MAX + 1 ) * n-1 );
+//      double t = values[i];
+//      values[i] = values[i+c];
+//      values[i+c] = t;	/* swap */
+      sample.append( values[i] );
+    }
+
+  }
+  else
+  {
+      sample = values;
+  }
+
+  // sort the values
+  qSort( sample );
+
+  QList< QList<double> > mat1;
+  QList< QList<double> > mat2;
+
+  double v, s1, s2, w, i3, i4, val;
+
+  for ( int i = 0; i < n + 1; i++ )
+  {
+    QList<double > temp1;
+    QList<double > temp2;
+    for (int j = 0; j < classes + 1; j++)
+    {
+      temp1.append(0.0);
+      temp2.append(0.0);
+    }
+    mat1.append(temp1);
+    mat2.append(temp2);
+  }
+
+  for ( int i = 1; i < classes + 1; i++ )
+  {
+    mat1[1][i] = 1.0;
+    mat2[1][i] = 0.0;
+    for ( int j = 2; j < n + 1; j++ )
+    {
+      mat2[j][i] = std::numeric_limits<qreal>::max();
+    }
+  }
+
+  v = 0.0;
+  for ( int l = 2; l < n + 1; l++ )
+  {
+    s1 = 0.0;
+    s2 = 0.0;
+    w = 0.0;
+    for ( int m = 1; m < l + 1; m++ )
+    {
+      i3 = l - m + 1;
+
+      val = sample[ i3 - 1 ];
+
+      s2 += val * val;
+      s1 += val;
+
+      w += 1.0;
+      v = s2 - (s1 * s1) / w;
+      i4 = i3 - 1;
+
+      if ( i4 != 0.0 )
+      {
+        for ( int j = 2; j < classes + 1; j++ )
+        {
+          if ( mat2[l][j] >= v + mat2[i4][j - 1] )
+          {
+            mat1[l][j] = i3;
+            mat2[l][j] = v + mat2[i4][j - 1];
+          }
+        }
+      }
+    }
+    mat1[l][1] = 1.0;
+    mat2[l][1] = v;
+  }
+
+  for ( int i = 0; i < classes; i++ )
+  {
+    breaks.append(0.0);
+  }
+
+  breaks[classes - 1] = sample[sample.length() - 1];
+//  breaks[0] = values[0];
+
+  int k = n;
+  int count = classes;
+  while ( count >= 2 )
+  {
+    //print "rank = " + str(mat1[k][countNum])
+    int id = mat1[k][count] - 2;
+    //print "val = " + str(dataList[id])
+
+    breaks[count - 2] = sample[id];
+    k = mat1[k][count] - 1;
+    count -= 1;
+  }
+
+  return breaks;
+}
+
+
 #include "qgsvectordataprovider.h"
 #include "qgsvectorcolorrampv2.h"
 
@@ -343,8 +678,12 @@
   {
     breaks = _calcEqualIntervalBreaks( minimum, maximum, classes );
   }
-  else if ( mode == Quantile )
+  else if ( mode == Pretty )
   {
+    breaks = _calcPrettyBreaks( minimum, maximum, classes );
+  }
+  else if ( mode == Quantile || mode == Jenks || mode == StdDev )
+  {
     // get values from layer
     QList<double> values;
     QgsFeature f;
@@ -354,7 +693,18 @@
     while ( provider->nextFeature( f ) )
       values.append( f.attributeMap()[attrNum].toDouble() );
     // calculate the breaks
-    breaks = _calcQuantileBreaks( values, classes );
+    if ( mode == Quantile )
+    {
+        breaks = _calcQuantileBreaks( values, classes );
+    }
+    else if ( mode == Jenks )
+    {
+        breaks = _calcJenksBreaks( values, classes, minimum, maximum );
+    }
+    else if ( mode == StdDev )
+    {
+        breaks = _calcStdDevBreaks( values, classes );
+    }
   }
   else
   {
@@ -374,7 +724,7 @@
     label = QString::number( lower, 'f', 4 ) + " - " + QString::number( upper, 'f', 4 );
 
     QgsSymbolV2* newSymbol = symbol->clone();
-    newSymbol->setColor( ramp->color(( double ) i / ( classes - 1 ) ) ); // color from (0 / cl-1) to (cl-1 / cl-1)
+    newSymbol->setColor( ramp->color(( double ) i / ( breaks.count() - 1 ) ) ); // color from (0 / cl-1) to (cl-1 / cl-1)
 
     ranges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
   }
@@ -454,6 +804,12 @@
       r->setMode( EqualInterval );
     else if ( modeString == "quantile" )
       r->setMode( Quantile );
+    else if ( modeString == "jenks" )
+      r->setMode( Jenks );
+    else if ( modeString == "stddev" )
+      r->setMode( StdDev );
+    else if ( modeString == "pretty" )
+      r->setMode( Pretty );
   }
 
   QDomElement rotationElem = element.firstChildElement( "rotation" );
@@ -523,6 +879,12 @@
     modeString = "equal";
   else if ( mMode == Quantile )
     modeString = "quantile";
+  else if ( mMode == Jenks )
+    modeString = "jenks";
+  else if ( mMode == StdDev )
+    modeString = "stddev";
+  else if ( mMode == Pretty )
+    modeString = "pretty";
   if ( !modeString.isEmpty() )
   {
     QDomElement modeElem = doc.createElement( "mode" );
Index: src/ui/qgsgraduatedsymbolrendererv2widget.ui
===================================================================
--- src/ui/qgsgraduatedsymbolrendererv2widget.ui	(revision 14280)
+++ src/ui/qgsgraduatedsymbolrendererv2widget.ui	(working copy)
@@ -113,6 +113,21 @@
          <string>Quantile</string>
         </property>
        </item>
+       <item>
+        <property name="text">
+         <string>Natural Breaks (Jenks)</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>Standard Deviation</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>Pretty Breaks</string>
+        </property>
+       </item>
       </widget>
      </item>
      <item row="1" column="2" rowspan="2">
