32,248 changes: 19,519 additions & 12,729 deletions i18n/qgis_da_DK.ts

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion python/gui/qgscomposerview.sip
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ class QgsComposerView: QGraphicsView
void mouseDoubleClickEvent( QMouseEvent* e );

void keyPressEvent( QKeyEvent * e );
void keyReleaseEvent( QKeyEvent * e );

void wheelEvent( QWheelEvent* event );

Expand Down
53 changes: 53 additions & 0 deletions python/plugins/sextante/gdalwarp.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
diff --git a/gdal/warp.py b/gdal/warp.py
index 5dac040..b4f1eee 100644
--- a/gdal/warp.py
+++ b/gdal/warp.py
@@ -23,14 +23,16 @@
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

+import os
+from qgis.core import *
from PyQt4 import QtGui
from sextante.core.GeoAlgorithm import GeoAlgorithm
from sextante.parameters.ParameterRaster import ParameterRaster
from sextante.outputs.OutputRaster import OutputRaster
-import os
-from qgis.core import *
from sextante.parameters.ParameterSelection import ParameterSelection
from sextante.parameters.ParameterCrs import ParameterCrs
+from sextante.parameters.ParameterString import ParameterString
+from sextante.parameters.ParameterNumber import ParameterNumber
from sextante.gdal.GdalUtils import GdalUtils

class warp(GeoAlgorithm):
@@ -41,6 +43,8 @@
DEST_SRS = "DEST_SRS "
METHOD = "METHOD"
METHOD_OPTIONS = ["near", "bilinear", "cubic", "cubicspline", "lanczos"]
+ EXTRA = "EXTRA"
+ TR = "TR"

def getIcon(self):
filepath = os.path.dirname(__file__) + "/icons/warp.png"
@@ -52,7 +56,9 @@
self.addParameter(ParameterRaster(warp.INPUT, "Input layer", False))
self.addParameter(ParameterCrs(warp.SOURCE_SRS, "Source SRS (EPSG Code)", "4326"))
self.addParameter(ParameterCrs(warp.DEST_SRS, "Destination SRS (EPSG Code)", "4326"))
+ self.addParameter(ParameterNumber(warp.TR, "Output file resolution in target georeferenced units (leave 0 for no change)", 0.0, None, 0.0))
self.addParameter(ParameterSelection(warp.METHOD, "Resampling method", warp.METHOD_OPTIONS))
+ self.addParameter(ParameterString(warp.EXTRA, "Additional creation parameters"))
self.addOutput(OutputRaster(warp.OUTPUT, "Output layer"))

def processAlgorithm(self, progress):
@@ -68,6 +74,10 @@
commands.append("-of")
out = self.getOutputValue(warp.OUTPUT)
commands.append(GdalUtils.getFormatShortNameFromFilename(out))
+ if str(self.getParameterValue(warp.TR)) != "0":
+ trStr = "-tr "+str(self.getParameterValue(warp.TR))+" "+str(self.getParameterValue(warp.TR))
+ commands.append(trStr)
+ commands.append(str(self.getParameterValue(warp.EXTRA)))
commands.append(self.getParameterValue(warp.INPUT))
commands.append(out)

Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ r.reclass.area
r.reclass.area.greater - Reclassifies a raster layer, selecting areas larger than a user specified size
Raster (r.*)
ParameterRaster|input|Input raster layer|False
ParameterNumber|greater|Area threshold [hectares]|0|None|1
ParameterNumber|greater|Area threshold [hectares]|0|None|1.0
OutputRaster|output|Output raster layer
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ r.reclass.area
r.reclass.area.lesser - Reclassifies a raster layer, selecting areas lower than a user specified size
Raster (r.*)
ParameterRaster|input|Input raster layer|False
ParameterNumber|lesser|Area threshold [hectares]|0|None|1
ParameterNumber|lesser|Area threshold [hectares]|0|None|1.0
OutputRaster|output|Output raster layer
13 changes: 8 additions & 5 deletions python/plugins/sextante/gui/SextanteToolbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
from sextante.gui.ParametersDialog import ParametersDialog
from sextante.gui.BatchProcessingDialog import BatchProcessingDialog
from sextante.gui.EditRenderingStylesDialog import EditRenderingStylesDialog

from sextante.ui.ui_SextanteToolbox import Ui_SextanteToolbox

try:
Expand Down Expand Up @@ -135,7 +134,7 @@ def executeAlgorithm(self):
if dlg.executed:
showRecent = SextanteConfig.getSetting(SextanteConfig.SHOW_RECENT_ALGORITHMS)
if showRecent:
self.fillTree()
self.addRecentAlgorithms()
if isinstance(item, TreeActionItem):
action = item.action
action.setData(self)
Expand All @@ -147,11 +146,15 @@ def fillTree(self):
self.fillTreeUsingCategories()
else:
self.fillTreeUsingProviders()

self.algorithmTree.sortItems(0, Qt.AscendingOrder)

self.algorithmTree.sortItems(0, Qt.AscendingOrder)
self.addRecentAlgorithms()

def addRecentAlgorithms(self):
showRecent = SextanteConfig.getSetting(SextanteConfig.SHOW_RECENT_ALGORITHMS)
if showRecent:
first = self.algorithmTree.topLevelItem(0)
if first.text(0) == "Recently used algorithms":
self.algorithmTree.removeItemWidget(first, 0)
recent = SextanteLog.getRecentAlgorithms()
if len(recent) != 0:
found = False
Expand Down
7 changes: 6 additions & 1 deletion python/plugins/sextante/r/RAlgorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,10 @@ def defineCharacteristicsFromFile(self):
filename = os.path.basename(self.descriptionFile)
self.name = filename[:filename.rfind(".")].replace("_", " ")
self.group = "User R scripts"
ender = 0
lines = open(self.descriptionFile)
line = lines.readline().strip("\n").strip("\r")
while line != "":
while ender < 10:
if line.startswith("##"):
try:
self.processParameterLine(line)
Expand All @@ -112,6 +113,10 @@ def defineCharacteristicsFromFile(self):
self.addOutput(OutputHTML(RAlgorithm.R_CONSOLE_OUTPUT, "R Console Output"))
self.showConsoleOutput = True
else:
if line == '':
ender += 1
else:
ender=0
self.commands.append(line)
self.script += line + "\n"
line = lines.readline().strip("\n").strip("\r")
Expand Down
12 changes: 12 additions & 0 deletions python/plugins/sextante/r_local_library.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
diff --git a/r/RAlgorithm.py b/r/RAlgorithm.py
index 8b2ea4b..b8e9b35 100644
--- a/r/RAlgorithm.py
+++ b/r/RAlgorithm.py
@@ -276,6 +276,7 @@
commands.append('options("repos"="http://cran.us.r-project.org")')
rLibDir = "%s/rlibs" % SextanteUtils.userFolder().replace("\\","/")
if not os.path.isdir(rLibDir): os.mkdir(rLibDir)
+ commands.append('.libPaths("%s")' % rLibDir )
commands.append(
'tryCatch(find.package("rgdal"), error=function(e) install.packages("rgdal", lib="%s"))' % rLibDir)
commands.append("library(\"rgdal\")");
21 changes: 21 additions & 0 deletions python/plugins/sextante/tests/GeoAlgorithmTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from sextante.core.Sextante import Sextante
from sextante.modeler.ModelerAlgorithm import ModelerAlgorithm

def testAlg(algname, *args):

#test simple execution
alg = Sextante.runAlgorithm(algname, None, *args)
assert alg is not None

out = alg.getOutputValuesAsDictionary()

return out

#test execution in a model

#===========================================================================
# model = ModelerAlgorithm()
# model.addAlgorithm(alg, parametersMap, valuesMap, outputsMap, dependencies)
#===========================================================================

#test
Empty file.
55 changes: 55 additions & 0 deletions python/plugins/sextante/tests/ParametersTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import unittest
from sextante.parameters.ParameterNumber import ParameterNumber
from sextante.parameters.ParameterCrs import ParameterCrs

class ParametersTest(unittest.TestCase):

def testParameterNumbert(self):
param = ParameterNumber("name", "desc", 0, 10)
assert not param.setValue("wrongvalue")
assert param.value is None
assert not param.setValue(25)
assert param.value is None
assert param.setValue(5)
assert param.value == 5
assert param.setValue(None)
assert param.value == param.default
s = param.serialize()
param2 = ParameterNumber()
param2.deserialize(s)
assert param.default == param2.default
assert param.max == param2.max
assert param.min == param2.min
assert param.description == param2.description
assert param.name == param2.name

def testParameterCRS(self):
param = ParameterCrs("name", "desc")
assert not param.setValue("EPSG:12003")
assert param.value == "EPSG:12003"
assert param.setValue(None)
assert param.value == param.default
s = param.serialize()
param2 = ParameterCrs()
param2.deserialize(s)
assert param.default == param2.default
assert param.description == param2.description
assert param.name == param2.name

def testParameterExtent(self):
param = ParameterCrs("name", "desc")
assert not param.setValue("EPSG:12003")
assert param.value == "EPSG:12003"
assert param.setValue(None)
assert param.value == param.default
s = param.serialize()
param2 = ParameterCrs()
param2.deserialize(s)
assert param.default == param2.default
assert param.description == param2.description
assert param.name == param2.name



if __name__ == '__main__':
unittest.main()
7 changes: 7 additions & 0 deletions python/plugins/sextante/tests/TestData.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os.path

dataFolder = os.path.join(os.path.dirname(__file__), 'data')
raster = os.path.join(dataFolder, "raster.tif")
points = os.path.join(dataFolder, "points.shp")
lines = os.path.join(dataFolder, "lines.shp")
polygons = os.path.join(dataFolder, "polygons.shp")
5 changes: 5 additions & 0 deletions python/plugins/sextante/tests/WritersTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'''
Created on 08/02/2013
@author: Volaya
'''
Binary file added python/plugins/sextante/tests/data/lines.dbf
Binary file not shown.
1 change: 1 addition & 0 deletions python/plugins/sextante/tests/data/lines.prj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROJCS["ED50_UTM_zone_30N",GEOGCS["GCS_European_1950",DATUM["D_European_1950",SPHEROID["International_1924",6378388,297]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Meter",1]]
1 change: 1 addition & 0 deletions python/plugins/sextante/tests/data/lines.qpj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROJCS["ED50 / UTM zone 30N",GEOGCS["ED50",DATUM["European_Datum_1950",SPHEROID["International 1924",6378388,297,AUTHORITY["EPSG","7022"]],TOWGS84[-87,-98,-121,0,0,0,0],AUTHORITY["EPSG","6230"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4230"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","23030"]]
Binary file added python/plugins/sextante/tests/data/lines.shp
Binary file not shown.
Binary file added python/plugins/sextante/tests/data/lines.shx
Binary file not shown.
Binary file added python/plugins/sextante/tests/data/points.dbf
Binary file not shown.
1 change: 1 addition & 0 deletions python/plugins/sextante/tests/data/points.prj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROJCS["ED50_UTM_zone_30N",GEOGCS["GCS_European_1950",DATUM["D_European_1950",SPHEROID["International_1924",6378388,297]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Meter",1]]
1 change: 1 addition & 0 deletions python/plugins/sextante/tests/data/points.qpj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROJCS["ED50 / UTM zone 30N",GEOGCS["ED50",DATUM["European_Datum_1950",SPHEROID["International 1924",6378388,297,AUTHORITY["EPSG","7022"]],TOWGS84[-87,-98,-121,0,0,0,0],AUTHORITY["EPSG","6230"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4230"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","23030"]]
Binary file added python/plugins/sextante/tests/data/points.shp
Binary file not shown.
Binary file added python/plugins/sextante/tests/data/points.shx
Binary file not shown.
Binary file added python/plugins/sextante/tests/data/polygons.dbf
Binary file not shown.
1 change: 1 addition & 0 deletions python/plugins/sextante/tests/data/polygons.prj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROJCS["ED50_UTM_zone_30N",GEOGCS["GCS_European_1950",DATUM["D_European_1950",SPHEROID["International_1924",6378388,297]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Meter",1]]
1 change: 1 addition & 0 deletions python/plugins/sextante/tests/data/polygons.qpj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROJCS["ED50 / UTM zone 30N",GEOGCS["ED50",DATUM["European_Datum_1950",SPHEROID["International 1924",6378388,297,AUTHORITY["EPSG","7022"]],TOWGS84[-87,-98,-121,0,0,0,0],AUTHORITY["EPSG","6230"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4230"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","23030"]]
Binary file added python/plugins/sextante/tests/data/polygons.shp
Binary file not shown.
Binary file added python/plugins/sextante/tests/data/polygons.shx
Binary file not shown.
Binary file added python/plugins/sextante/tests/data/raster.tif
Binary file not shown.
62 changes: 62 additions & 0 deletions python/plugins/sextante/tools/help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from sextante.core.Sextante import Sextante
import os
from sextante.core.SextanteUtils import mkdir
from sextante.parameters.ParameterSelection import ParameterSelection

def createBaseHelpFile(alg, folder):
folder = os.path.join(folder, alg.provider.getName().lower())
mkdir(folder)
cmdLineName = alg.commandLineName()[alg.commandLineName().find(":") + 1:].lower()
validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
safeFilename = ''.join(c for c in cmdLineName if c in validChars)
filepath = os.path.join(folder, safeFilename + ".rst")
file = open(filepath, "w")
file.write(alg.name.upper())
file.write("\n")
file.write("=" * len(alg.name))
file.write("\n\n")
file.write("Description\n")
file.write("-----------\n\n")
file.write("Parameters\n")
file.write("----------\n\n")
for param in alg.parameters:
file.write("- ``" + param.description + "[" + param.parameterName()[9:] + "]``:\n")
file.write("\nOutputs\n")
file.write("-------\n\n")
for out in alg.outputs:
file.write("- ``" + out.description + "[" + out.outputTypeName()[6:] + "]``:\n")
file.write("\nSee also\n")
file.write("---------\n\n")
file.write("\nConsole usage\n")
file.write("-------------\n\n")
file.write("\n::\n\n")
s = "\tsextante.runalg('" + alg.commandLineName() + "', "
for param in alg.parameters:
s+= str(param.name.lower().strip()) + ", "
for out in alg.outputs:
if not out.hidden:
s+=str(out.name.lower().strip()) + ", "
s = s[:-2] +")\n"
file.write(s)

s =""
hasSelection = False
for param in alg.parameters:
if isinstance(param, ParameterSelection):
hasSelection = True
s+="\n\t" + param.name.lower() + "(" + param.description + ")\n"
i=0
for option in param.options:
s+= "\t\t" + str(i) + " - " + str(option) + "\n"
i+=1
if hasSelection:
file.write("\n\tAvailable options for selection parameters:\n")
file.write(s)
file.close()


def createBaseHelpFiles(folder):
for provider in Sextante.providers:
for alg in provider.algs:
createBaseHelpFile(alg, folder)

49 changes: 49 additions & 0 deletions python/plugins/sextante/ui/DlgConfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'DlgConfig.ui'
#
# Created: Tue Dec 04 00:31:31 2012
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s

class Ui_DlgConfig(object):
def setupUi(self, DlgConfig):
DlgConfig.setObjectName(_fromUtf8("DlgConfig"))
DlgConfig.resize(640, 450)
self.verticalLayout = QtGui.QVBoxLayout(DlgConfig)
self.verticalLayout.setSpacing(2)
self.verticalLayout.setMargin(0)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.searchBox = QgsFilterLineEdit(DlgConfig)
self.searchBox.setObjectName(_fromUtf8("searchBox"))
self.verticalLayout.addWidget(self.searchBox)
self.tree = QtGui.QTreeWidget(DlgConfig)
self.tree.setAlternatingRowColors(True)
self.tree.setObjectName(_fromUtf8("tree"))
self.verticalLayout.addWidget(self.tree)
self.buttonBox = QtGui.QDialogButtonBox(DlgConfig)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.verticalLayout.addWidget(self.buttonBox)

self.retranslateUi(DlgConfig)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), DlgConfig.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), DlgConfig.reject)
QtCore.QMetaObject.connectSlotsByName(DlgConfig)

def retranslateUi(self, DlgConfig):
DlgConfig.setWindowTitle(QtGui.QApplication.translate("DlgConfig", "SEXTANTE options", None, QtGui.QApplication.UnicodeUTF8))
self.searchBox.setToolTip(QtGui.QApplication.translate("DlgConfig", "Enter setting name to filter list", None, QtGui.QApplication.UnicodeUTF8))
self.tree.headerItem().setText(0, QtGui.QApplication.translate("DlgConfig", "Setting", None, QtGui.QApplication.UnicodeUTF8))
self.tree.headerItem().setText(1, QtGui.QApplication.translate("DlgConfig", "Value", None, QtGui.QApplication.UnicodeUTF8))

from qgis.gui import QgsFilterLineEdit
1 change: 1 addition & 0 deletions python/plugins/sextante/ui/pyuic4.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@"C:\Python27\python" "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py" %1 %2 %3 %4 %5 %6 %7 %8 %9
2 changes: 1 addition & 1 deletion scripts/tsstat.pl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
bg => 'Захари Савов, Jordan Tzvetkov',
ca_ES => 'Xavier Roijals',
cs_CZ => 'Martin Landa, Peter Antolik, Martin Dzurov, Jan Helebrant',
da_DK => 'Preben Lisby',
da_DK => 'Jacob Overgaard Madsen, Preben Lisby',
de => 'JĂĽrgen E. Fischer, Stephan Holl, Otto Dassau, Werner Macho',
es => 'Carlos Dávila, Javier César Aldariz, Gabriela Awad, Edwin Amado, Mayeul Kauffmann, Diana Galindo',
el_GR => 'Evripidis Argyropoulos, Mike Pegnigiannis, Nikos Ves',
Expand Down
30 changes: 24 additions & 6 deletions src/app/composer/qgscomposer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@
#include <QProgressDialog>


// sort function for QList<QAction*>, e.g. menu listings
static bool cmpByText_( QAction* a, QAction* b )
{
return QString::localeAwareCompare( a->text(), b->text() ) < 0;
}

QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
: QMainWindow()
, mTitle( title )
Expand Down Expand Up @@ -161,6 +167,8 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
mActionAddArrow->setCheckable( true );

#ifdef Q_WS_MAC
mActionQuit->setText( tr( "Close" ) );
mActionQuit->setShortcut( QKeySequence::Close );
QMenu *appMenu = menuBar()->addMenu( tr( "QGIS" ) );
appMenu->addAction( mQgis->actionAbout() );
appMenu->addAction( mQgis->actionOptions() );
Expand Down Expand Up @@ -244,7 +252,7 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
connect( mWindowMenu, SIGNAL( aboutToShow() ), this, SLOT( populateWindowMenu() ) );
menuBar()->addMenu( mWindowMenu );

mHelpMenu = new QMenu( tr( "Help" ) );
mHelpMenu = new QMenu( tr( "Help" ), this );
mHelpMenu->setObjectName( "mHelpMenu" );
connect( mHelpMenu, SIGNAL( aboutToShow() ), this, SLOT( populateHelpMenu() ) );
menuBar()->addMenu( mHelpMenu );
Expand Down Expand Up @@ -748,12 +756,16 @@ void QgsComposer::on_mActionExportAsPDF_triggered()
}
if ( !atlasOnASingleFile )
{
// bugs #7263 and #6856
// QPrinter does not seem to be reset correctly and may cause generated PDFs (all except the first) corrupted
// when transparent objects are rendered. We thus use a new QPrinter object here
QPrinter multiFilePrinter;
outputFileName = QDir( outputDir ).filePath( atlasMap->currentFilename() ) + ".pdf";
mComposition->beginPrintAsPDF( printer, outputFileName );
mComposition->beginPrintAsPDF( multiFilePrinter, outputFileName );
// set the correct resolution
mComposition->beginPrint( printer );
painter.begin( &printer );
mComposition->doPrint( printer, painter );
mComposition->beginPrint( multiFilePrinter );
painter.begin( &multiFilePrinter );
mComposition->doPrint( multiFilePrinter, painter );
painter.end();
}
else
Expand Down Expand Up @@ -2116,7 +2128,13 @@ void QgsComposer::initialiseComposerPicturePreviews()
void QgsComposer::populatePrintComposersMenu()
{
mPrintComposersMenu->clear();
mPrintComposersMenu->addActions( mQgis->printComposersMenu()->actions() );
QList<QAction*> acts = mQgis->printComposersMenu()->actions();
if ( acts.size() > 1 )
{
// sort actions in case main app's aboutToShow slot has not yet
qSort( acts.begin(), acts.end(), cmpByText_ );
}
mPrintComposersMenu->addActions( acts );
}

void QgsComposer::populateWindowMenu()
Expand Down
6 changes: 6 additions & 0 deletions src/app/composer/qgscomposermanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ void QgsComposerManager::initialize()
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );
mItemComposerMap.insert( item, *it );
}
mComposerListWidget->sortItems();

mTemplate->addItem( tr( "Empty composer" ) );
mTemplate->addItem( tr( "Specific" ) );
Expand Down Expand Up @@ -198,6 +199,8 @@ void QgsComposerManager::on_mAddButton_clicked()
QListWidgetItem* item = new QListWidgetItem( newComposer->title(), mComposerListWidget );
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );
mItemComposerMap.insert( item, newComposer );

mComposerListWidget->sortItems();
mComposerListWidget->setCurrentItem( item );
mComposerListWidget->setFocus();
}
Expand Down Expand Up @@ -429,6 +432,8 @@ void QgsComposerManager::rename_clicked()
}
currentComposer->setTitle( newTitle );
item->setText( newTitle );

mComposerListWidget->sortItems();
}

void QgsComposerManager::on_mComposerListWidget_itemChanged( QListWidgetItem * item )
Expand All @@ -438,4 +443,5 @@ void QgsComposerManager::on_mComposerListWidget_itemChanged( QListWidgetItem * i
{
it.value()->setTitle( item->text() );
}
mComposerListWidget->sortItems();
}
12 changes: 12 additions & 0 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4800,6 +4800,18 @@ void QgisApp::deletePrintComposers()
markDirty();
}

void QgisApp::on_mPrintComposersMenu_aboutToShow()
{
QList<QAction*> acts = mPrintComposersMenu->actions();
mPrintComposersMenu->clear();
if ( acts.size() > 1 )
{
// sort actions by text
qSort( acts.begin(), acts.end(), cmpByText_ );
}
mPrintComposersMenu->addActions( acts );
}

bool QgisApp::loadAnnotationItemsFromProject( const QDomDocument& doc )
{
if ( !mMapCanvas )
Expand Down
5 changes: 5 additions & 0 deletions src/app/qgisapp.h
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,11 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
/**Creates the composer instances in a project file and adds them to the menu*/
bool loadComposersFromProject( const QDomDocument& doc );

/** Slot to handle display of composers menu, e.g. sorting
* @note added in 1.9
*/
void on_mPrintComposersMenu_aboutToShow();

bool loadAnnotationItemsFromProject( const QDomDocument& doc );

//! Toggles whether to show pinned labels
Expand Down
87 changes: 78 additions & 9 deletions src/core/composer/qgscomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,13 @@ bool QgsComposition::loadFromTemplate( const QDomDocument& doc, QMap<QString, QS
}

void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocument& doc, QMap< QgsComposerMap*, int >* mapsToRestore,
bool addUndoCommands, QPointF* pos )
bool addUndoCommands, QPointF* pos, bool pasteInPlace )
{
QPointF* pasteInPlacePt;
if( pasteInPlace )
{
pasteInPlacePt = new QPointF(0, pageNumberAt( *pos ) * (mPageHeight+mSpaceBetweenPages) );
}
QDomNodeList composerLabelList = elem.elementsByTagName( "ComposerLabel" );
for ( int i = 0; i < composerLabelList.size(); ++i )
{
Expand All @@ -456,7 +461,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newLabel->readXML( currentComposerLabelElem, doc );
if ( pos )
{
newLabel->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newLabel->setItemPosition( newLabel->transform().dx(), fmod(newLabel->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newLabel->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newLabel->setItemPosition( pos->x(), pos->y() );
}
}
addComposerLabel( newLabel );
if ( addUndoCommands )
Expand All @@ -482,7 +495,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen

if ( pos )
{
newMap->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newMap->setItemPosition( newMap->transform().dx(), fmod(newMap->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newMap->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newMap->setItemPosition( pos->x(), pos->y() );
}
}

if ( addUndoCommands )
Expand All @@ -499,7 +520,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newArrow->readXML( currentComposerArrowElem, doc );
if ( pos )
{
newArrow->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newArrow->setItemPosition( newArrow->transform().dx(), fmod(newArrow->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newArrow->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newArrow->setItemPosition( pos->x(), pos->y() );
}
}
addComposerArrow( newArrow );
if ( addUndoCommands )
Expand All @@ -516,7 +545,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newScaleBar->readXML( currentComposerScaleBarElem, doc );
if ( pos )
{
newScaleBar->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newScaleBar->setItemPosition( newScaleBar->transform().dx(), fmod(newScaleBar->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newScaleBar->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newScaleBar->setItemPosition( pos->x(), pos->y() );
}
}
addComposerScaleBar( newScaleBar );
if ( addUndoCommands )
Expand All @@ -533,7 +570,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newShape->readXML( currentComposerShapeElem, doc );
if ( pos )
{
newShape->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newShape->setItemPosition( newShape->transform().dx(), fmod(newShape->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newShape->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newShape->setItemPosition( pos->x(), pos->y() );
}
}
addComposerShape( newShape );
if ( addUndoCommands )
Expand All @@ -550,7 +595,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newPicture->readXML( currentComposerPictureElem, doc );
if ( pos )
{
newPicture->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newPicture->setItemPosition( newPicture->transform().dx(), fmod(newPicture->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newPicture->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newPicture->setItemPosition( pos->x(), pos->y() );
}
}
addComposerPicture( newPicture );
if ( addUndoCommands )
Expand All @@ -567,7 +620,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newLegend->readXML( currentComposerLegendElem, doc );
if ( pos )
{
newLegend->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newLegend->setItemPosition( newLegend->transform().dx(), fmod(newLegend->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newLegend->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newLegend->setItemPosition( pos->x(), pos->y() );
}
}
addComposerLegend( newLegend );
if ( addUndoCommands )
Expand All @@ -584,7 +645,15 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newTable->readXML( currentComposerTableElem, doc );
if ( pos )
{
newTable->setItemPosition( pos->x(), pos->y() );
if ( pasteInPlace )
{
newTable->setItemPosition( newTable->transform().dx(), fmod(newTable->transform().dy(), (paperHeight()+spaceBetweenPages()) ) );
newTable->move( pasteInPlacePt->x(),pasteInPlacePt->y() );
}
else
{
newTable->setItemPosition( pos->x(), pos->y() );
}
}
addComposerTable( newTable );
if ( addUndoCommands )
Expand Down
3 changes: 2 additions & 1 deletion src/core/composer/qgscomposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,11 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
@param mapsToRestore for reading from project file: set preview move 'rectangle' to all maps and save the preview states to show composer maps on demand
@param addUndoCommands insert AddItem commands if true (e.g. for copy/paste)
@param pos item position. Optional, take position from xml if 0
@param pasteInPlace wheter the position should be kept but mapped to the page origin. (the page is the page under to the mouse cursor)
@note not available in python bindings
*/
void addItemsFromXML( const QDomElement& elem, const QDomDocument& doc, QMap< QgsComposerMap*, int >* mapsToRestore = 0,
bool addUndoCommands = false, QPointF* pos = 0 );
bool addUndoCommands = false, QPointF* pos = 0, bool pasteInPlace = false );

/**Adds item to z list. Usually called from constructor of QgsComposerItem*/
void addItemToZList( QgsComposerItem* item );
Expand Down
22 changes: 6 additions & 16 deletions src/gui/qgscomposerview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@

QgsComposerView::QgsComposerView( QWidget* parent, const char* name, Qt::WFlags f )
: QGraphicsView( parent )
, mShiftKeyPressed( false )
, mRubberBandItem( 0 )
, mRubberBandLineItem( 0 )
, mMoveContentItem( 0 )
Expand Down Expand Up @@ -84,7 +83,7 @@ void QgsComposerView::mousePressEvent( QMouseEvent* e )
//select/deselect items and pass mouse event further
case Select:
{
if ( !mShiftKeyPressed ) //keep selection if shift key pressed
if ( !( e->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed
{
composition()->clearSelection();
}
Expand Down Expand Up @@ -448,10 +447,7 @@ void QgsComposerView::mouseDoubleClickEvent( QMouseEvent* e )

void QgsComposerView::keyPressEvent( QKeyEvent * e )
{
if ( e->key() == Qt::Key_Shift )
{
mShiftKeyPressed = true;
}
//TODO : those should be actions (so we could also display menu items and/or toolbar items)

if ( !composition() )
{
Expand Down Expand Up @@ -491,7 +487,8 @@ void QgsComposerView::keyPressEvent( QKeyEvent * e )
clipboard->setMimeData( mimeData );
}

if ( e->matches( QKeySequence::Paste ) )
//TODO : "Ctrl+Shift+V" is one way to paste, but on some platefoms you can use Shift+Ins and F18
if ( e->matches( QKeySequence::Paste ) || (e->key() == Qt::Key_V && e->modifiers() & Qt::ControlModifier && e->modifiers() & Qt::ShiftModifier) )
{
QDomDocument doc;
QClipboard *clipboard = QApplication::clipboard();
Expand All @@ -503,7 +500,8 @@ void QgsComposerView::keyPressEvent( QKeyEvent * e )
if ( composition() )
{
QPointF pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
composition()->addItemsFromXML( docElem, doc, 0, true, &pt );
bool pasteInPlace = (e->modifiers() & Qt::ShiftModifier);
composition()->addItemsFromXML( docElem, doc, 0, true, &pt, pasteInPlace );
}
}
}
Expand Down Expand Up @@ -559,14 +557,6 @@ void QgsComposerView::keyPressEvent( QKeyEvent * e )
}
}

void QgsComposerView::keyReleaseEvent( QKeyEvent * e )
{
if ( e->key() == Qt::Key_Shift )
{
mShiftKeyPressed = false;
}
}

void QgsComposerView::wheelEvent( QWheelEvent* event )
{
QPointF scenePoint = mapToScene( event->pos() );
Expand Down
3 changes: 0 additions & 3 deletions src/gui/qgscomposerview.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
void mouseDoubleClickEvent( QMouseEvent* e );

void keyPressEvent( QKeyEvent * e );
void keyReleaseEvent( QKeyEvent * e );

void wheelEvent( QWheelEvent* event );

Expand All @@ -106,8 +105,6 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
void showEvent( QShowEvent* e );

private:
/**Status of shift key (used for multiple selection)*/
bool mShiftKeyPressed;
/**Current composer tool*/
QgsComposerView::Tool mCurrentTool;
/**Rubber band item*/
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsscalecombobox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void QgsScaleComboBox::fixupScale()
if ( ok && ( newScale != oldScale ) )
{
// if a user types scale = 2345, we transform to 1:2345
if ( userSetScale )
if ( userSetScale && newScale >= 1.0 )
{
mScale = 1 / newScale;
}
Expand Down
6 changes: 3 additions & 3 deletions tests/src/gui/testqgsscalecombobox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ void TestQgsScaleComboBox::basic()
QCOMPARE( s->scaleString(), QString( "1:50" ) );
QCOMPARE( s->scale(), ( double ) 0.02 );

// Testing conversion from number to "x:1"
// Testing conversion from number to "1:x"
l->setText( "" );
QTest::keyClicks( l, QLocale::system().toString( 42 ) );
QTest::keyClick( l, Qt::Key_Return );
QCOMPARE( s->scaleString(), QString( "42:1" ) );
QCOMPARE( s->scale(), ( double ) 42 );
QCOMPARE( s->scaleString(), QString( "1:42" ) );
QCOMPARE( s->scale(), ( double ) 1.0 / ( double ) 42.0 );

// Testing rounding and conversion from illegal

Expand Down