├── .gitignore ├── InstantPrintPlugin.py ├── InstantPrintTool.py ├── LICENSE ├── Makefile ├── README.md ├── __init__.py ├── help ├── documentation.pdf ├── documentation.tex └── img │ ├── logo_full.pdf │ ├── logo_text.pdf │ └── screenshot.png ├── i18n ├── instantprint_de.qm ├── instantprint_de.ts ├── instantprint_it.qm ├── instantprint_it.ts ├── instantprint_ja.qm └── instantprint_ja.ts ├── icons └── icon.png ├── instantprint_ts.pro ├── instantprint_ts.pro.qtds ├── metadata.txt ├── pyqgis.cmd ├── pyrcc5.txt ├── resources.qrc ├── resources_rc.py └── ui ├── __init__.py ├── printdialog.ui └── ui_printdialog.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | 3 | -------------------------------------------------------------------------------- /InstantPrintPlugin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # copyright : (C) 2014-2015 by Sandro Mani / Sourcepole AG 9 | # email : smani@sourcepole.ch 10 | 11 | from qgis.core import Qgis 12 | from PyQt5.QtCore import QObject, QSettings, QTranslator, QCoreApplication 13 | from PyQt5.QtGui import QIcon 14 | from PyQt5.QtWidgets import QToolButton 15 | from qgis.gui import QgisInterface 16 | import os 17 | from .InstantPrintTool import InstantPrintTool 18 | from . import resources_rc 19 | 20 | 21 | class InstantPrintPlugin(QObject): 22 | def __init__(self, iface): 23 | QObject.__init__(self) 24 | 25 | self.iface = iface 26 | self.pluginDir = os.path.dirname(__file__) 27 | 28 | # Localize 29 | locale = QSettings().value("locale/userLocale")[0:2] 30 | localePath = os.path.join(self.pluginDir, 'i18n', 'instantprint_{}.qm'.format(locale)) 31 | 32 | if os.path.exists(localePath): 33 | self.translator = QTranslator() 34 | self.translator.load(localePath) 35 | QCoreApplication.installTranslator(self.translator) 36 | 37 | self.tool = InstantPrintTool(self.iface) 38 | 39 | 40 | 41 | def initGui(self): 42 | self.toolButton = QToolButton(self.iface.mapNavToolToolBar()) 43 | self.toolButton.setIcon(QIcon(":/plugins/instantprint/icons/icon.png")) 44 | self.toolButton.setText(self.tr("Instant Print")) 45 | self.toolButton.setToolTip(self.tr("Instant Print")) 46 | self.toolButton.setCheckable(True) 47 | self.toolAction = self.iface.pluginToolBar().addWidget(self.toolButton) 48 | 49 | self.toolButton.toggled.connect(self.__enableTool) 50 | self.iface.mapCanvas().mapToolSet.connect(self.__onToolSet) 51 | 52 | def unload(self): 53 | self.tool.setEnabled(False) 54 | self.tool = None 55 | self.iface.pluginToolBar().removeAction(self.toolAction) 56 | 57 | def __enableTool(self, active): 58 | self.tool.setEnabled(active) 59 | 60 | def __onToolSet(self, tool): 61 | if tool != self.tool: 62 | self.toolButton.setChecked(False) 63 | -------------------------------------------------------------------------------- /InstantPrintTool.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # copyright : (C) 2014-2015 by Sandro Mani / Sourcepole AG 9 | # email : smani@sourcepole.ch 10 | 11 | from PyQt5.QtCore import Qt, QSettings, QPointF, QRectF, QRect, QUrl, pyqtSignal, QLocale 12 | from PyQt5.QtGui import QColor, QDesktopServices, QIcon 13 | from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox, QFileDialog 14 | from PyQt5.QtPrintSupport import QPrintDialog, QPrinter 15 | from qgis.core import QgsRectangle, QgsLayoutManager, QgsPointXY as QgsPoint, Qgis, QgsProject, QgsWkbTypes, QgsLayoutExporter, PROJECT_SCALES, QgsLayoutItemMap 16 | from qgis.gui import QgisInterface, QgsMapTool, QgsRubberBand 17 | import os 18 | from .ui.ui_printdialog import Ui_InstantPrintDialog 19 | 20 | 21 | class InstantPrintDialog(QDialog): 22 | 23 | hidden = pyqtSignal() 24 | 25 | def __init__(self, parent): 26 | QDialog.__init__(self, parent) 27 | 28 | def hideEvent(self, ev): 29 | self.hidden.emit() 30 | 31 | def keyPressEvent(self, e): 32 | if e.key() == Qt.Key_Escape: 33 | self.hidden.emit() 34 | 35 | 36 | class InstantPrintTool(QgsMapTool, InstantPrintDialog): 37 | 38 | def __init__(self, iface, populateCompositionFz=None): 39 | QgsMapTool.__init__(self, iface.mapCanvas()) 40 | 41 | self.iface = iface 42 | projectInstance = QgsProject.instance() 43 | self.projectLayoutManager = projectInstance.layoutManager() 44 | self.rubberband = None 45 | self.oldrubberband = None 46 | self.pressPos = None 47 | self.printer = QPrinter() 48 | self.mapitem = None 49 | self.populateCompositionFz = populateCompositionFz 50 | 51 | self.dialog = InstantPrintDialog(self.iface.mainWindow()) 52 | self.dialogui = Ui_InstantPrintDialog() 53 | self.dialogui.setupUi(self.dialog) 54 | self.dialogui.addScale.setIcon(QIcon(":/images/themes/default/mActionAdd.svg")) 55 | self.dialogui.deleteScale.setIcon(QIcon(":/images/themes/default/symbologyRemove.svg")) 56 | self.dialog.hidden.connect(self.__onDialogHidden) 57 | self.exportButton = self.dialogui.buttonBox.addButton(self.tr("Export"), QDialogButtonBox.ActionRole) 58 | self.printButton = self.dialogui.buttonBox.addButton(self.tr("Print"), QDialogButtonBox.ActionRole) 59 | self.helpButton = self.dialogui.buttonBox.addButton(self.tr("Help"), QDialogButtonBox.HelpRole) 60 | self.dialogui.comboBox_fileformat.addItem("PDF", self.tr("PDF Document (*.pdf);;")) 61 | self.dialogui.comboBox_fileformat.addItem("JPG", self.tr("JPG Image (*.jpg);;")) 62 | self.dialogui.comboBox_fileformat.addItem("BMP", self.tr("BMP Image (*.bmp);;")) 63 | self.dialogui.comboBox_fileformat.addItem("PNG", self.tr("PNG Image (*.png);;")) 64 | self.iface.layoutDesignerOpened.connect(lambda view: self.__reloadLayouts()) 65 | self.iface.layoutDesignerWillBeClosed.connect(self.__reloadLayouts) 66 | self.dialogui.comboBox_layouts.currentIndexChanged.connect(self.__selectLayout) 67 | self.dialogui.comboBox_scale.lineEdit().textChanged.connect(self.__changeScale) 68 | self.dialogui.comboBox_scale.scaleChanged.connect(self.__changeScale) 69 | self.exportButton.clicked.connect(self.__export) 70 | self.printButton.clicked.connect(self.__print) 71 | self.helpButton.clicked.connect(self.__help) 72 | self.dialogui.buttonBox.button(QDialogButtonBox.Close).clicked.connect(lambda: self.dialog.hide()) 73 | self.dialogui.addScale.clicked.connect(self.add_new_scale) 74 | self.dialogui.deleteScale.clicked.connect(self.remove_scale) 75 | self.deactivated.connect(self.__cleanup) 76 | self.setCursor(Qt.OpenHandCursor) 77 | 78 | settings = QSettings() 79 | if settings.value("instantprint/geometry") is not None: 80 | self.dialog.restoreGeometry(settings.value("instantprint/geometry")) 81 | if settings.value("instantprint/scales") is not None: 82 | for scale in settings.value("instantprint/scales").split(";"): 83 | if scale: 84 | self.retrieve_scales(scale) 85 | self.check_scales() 86 | 87 | def __onDialogHidden(self): 88 | self.setEnabled(False) 89 | self.iface.mapCanvas().unsetMapTool(self) 90 | QSettings().setValue("instantprint/geometry", self.dialog.saveGeometry()) 91 | list = [] 92 | for i in range(self.dialogui.comboBox_scale.count()): 93 | list.append(self.dialogui.comboBox_scale.itemText(i)) 94 | QSettings().setValue("instantprint/scales", ";".join(list)) 95 | 96 | def retrieve_scales(self, checkScale): 97 | if self.dialogui.comboBox_scale.findText(checkScale) == -1: 98 | self.dialogui.comboBox_scale.addItem(checkScale) 99 | 100 | def add_new_scale(self): 101 | new_layout = self.dialogui.comboBox_scale.currentText() 102 | if self.dialogui.comboBox_scale.findText(new_layout) == -1: 103 | self.dialogui.comboBox_scale.addItem(new_layout) 104 | self.check_scales() 105 | 106 | def remove_scale(self): 107 | layout_to_delete = self.dialogui.comboBox_scale.currentIndex() 108 | self.dialogui.comboBox_scale.removeItem(layout_to_delete) 109 | self.check_scales() 110 | 111 | def setEnabled(self, enabled): 112 | if enabled: 113 | self.dialog.setVisible(True) 114 | self.__reloadLayouts() 115 | self.iface.mapCanvas().setMapTool(self) 116 | else: 117 | self.dialog.setVisible(False) 118 | self.iface.mapCanvas().unsetMapTool(self) 119 | 120 | def __changeScale(self): 121 | if not self.mapitem: 122 | return 123 | newscale = self.dialogui.comboBox_scale.scale() 124 | if abs(newscale) < 1E-6: 125 | return 126 | extent = self.mapitem.extent() 127 | center = extent.center() 128 | newwidth = extent.width() / self.mapitem.scale() * newscale 129 | newheight = extent.height() / self.mapitem.scale() * newscale 130 | x1 = center.x() - 0.5 * newwidth 131 | y1 = center.y() - 0.5 * newheight 132 | x2 = center.x() + 0.5 * newwidth 133 | y2 = center.y() + 0.5 * newheight 134 | self.mapitem.setExtent(QgsRectangle(x1, y1, x2, y2)) 135 | self.__createRubberBand() 136 | self.check_scales() 137 | 138 | def __selectLayout(self): 139 | if not self.dialog.isVisible(): 140 | return 141 | activeIndex = self.dialogui.comboBox_layouts.currentIndex() 142 | if activeIndex < 0: 143 | return 144 | 145 | layoutView = self.dialogui.comboBox_layouts.itemData(activeIndex) 146 | maps = [] 147 | layout_name = self.dialogui.comboBox_layouts.currentText() 148 | layout = self.projectLayoutManager.layoutByName(layout_name) 149 | for item in layoutView.items(): 150 | if isinstance(item, QgsLayoutItemMap): 151 | maps.append(item) 152 | if len(maps) != 1: 153 | QMessageBox.warning(self.iface.mainWindow(), self.tr("Invalid layout"), self.tr("The layout must have exactly one map item.")) 154 | self.exportButton.setEnabled(False) 155 | self.iface.mapCanvas().scene().removeItem(self.rubberband) 156 | self.rubberband = None 157 | self.dialogui.comboBox_scale.setEnabled(False) 158 | return 159 | 160 | self.dialogui.comboBox_scale.setEnabled(True) 161 | self.exportButton.setEnabled(True) 162 | 163 | self.layoutView = layoutView 164 | self.mapitem = layout.referenceMap() 165 | self.dialogui.comboBox_scale.setScale(self.mapitem.scale()) 166 | self.__createRubberBand() 167 | 168 | def __createRubberBand(self): 169 | self.__cleanup() 170 | extent = self.mapitem.extent() 171 | center = self.iface.mapCanvas().extent().center() 172 | self.corner = QPointF(center.x() - 0.5 * extent.width(), center.y() - 0.5 * extent.height()) 173 | self.rect = QRectF(self.corner.x(), self.corner.y(), extent.width(), extent.height()) 174 | self.mapitem.setExtent(QgsRectangle(self.rect)) 175 | self.rubberband = QgsRubberBand(self.iface.mapCanvas(), QgsWkbTypes.PolygonGeometry) 176 | self.rubberband.setToCanvasRectangle(self.__canvasRect(self.rect)) 177 | self.rubberband.setColor(QColor(127, 127, 255, 127)) 178 | 179 | self.pressPos = None 180 | 181 | def __cleanup(self): 182 | if self.rubberband: 183 | self.iface.mapCanvas().scene().removeItem(self.rubberband) 184 | if self.oldrubberband: 185 | self.iface.mapCanvas().scene().removeItem(self.oldrubberband) 186 | self.rubberband = None 187 | self.oldrubberband = None 188 | self.pressPos = None 189 | 190 | def canvasPressEvent(self, e): 191 | if not self.rubberband: 192 | return 193 | r = self.__canvasRect(self.rect) 194 | if e.button() == Qt.LeftButton and self.__canvasRect(self.rect).contains(e.pos()): 195 | self.oldrect = QRectF(self.rect) 196 | self.oldrubberband = QgsRubberBand(self.iface.mapCanvas(), QgsWkbTypes.PolygonGeometry) 197 | self.oldrubberband.setToCanvasRectangle(self.__canvasRect(self.oldrect)) 198 | self.oldrubberband.setColor(QColor(127, 127, 255, 31)) 199 | self.pressPos = (e.x(), e.y()) 200 | self.iface.mapCanvas().setCursor(Qt.ClosedHandCursor) 201 | 202 | def canvasMoveEvent(self, e): 203 | if not self.pressPos: 204 | return 205 | mup = self.iface.mapCanvas().mapSettings().mapUnitsPerPixel() 206 | x = self.corner.x() + (e.x() - self.pressPos[0]) * mup 207 | y = self.corner.y() + (self.pressPos[1] - e.y()) * mup 208 | 209 | snaptol = 10 * mup 210 | # Left edge matches with old right 211 | if abs(x - (self.oldrect.x() + self.oldrect.width())) < snaptol: 212 | x = self.oldrect.x() + self.oldrect.width() 213 | # Right edge matches with old left 214 | elif abs(x + self.rect.width() - self.oldrect.x()) < snaptol: 215 | x = self.oldrect.x() - self.rect.width() 216 | # Left edge matches with old left 217 | elif abs(x - self.oldrect.x()) < snaptol: 218 | x = self.oldrect.x() 219 | # Bottom edge matches with old top 220 | if abs(y - (self.oldrect.y() + self.oldrect.height())) < snaptol: 221 | y = self.oldrect.y() + self.oldrect.height() 222 | # Top edge matches with old bottom 223 | elif abs(y + self.rect.height() - self.oldrect.y()) < snaptol: 224 | y = self.oldrect.y() - self.rect.height() 225 | # Bottom edge matches with old bottom 226 | elif abs(y - self.oldrect.y()) < snaptol: 227 | y = self.oldrect.y() 228 | 229 | self.rect = QRectF( 230 | x, 231 | y, 232 | self.rect.width(), 233 | self.rect.height() 234 | ) 235 | self.rubberband.setToCanvasRectangle(self.__canvasRect(self.rect)) 236 | 237 | def canvasReleaseEvent(self, e): 238 | if e.button() == Qt.LeftButton and self.pressPos: 239 | self.corner = QPointF(self.rect.x(), self.rect.y()) 240 | self.pressPos = None 241 | self.iface.mapCanvas().setCursor(Qt.OpenHandCursor) 242 | self.iface.mapCanvas().scene().removeItem(self.oldrubberband) 243 | self.oldrect = None 244 | self.oldrubberband = None 245 | self.mapitem.setExtent(QgsRectangle(self.rect)) 246 | 247 | def __canvasRect(self, rect): 248 | mtp = self.iface.mapCanvas().mapSettings().mapToPixel() 249 | p1 = mtp.transform(QgsPoint(rect.left(), rect.top())) 250 | p2 = mtp.transform(QgsPoint(rect.right(), rect.bottom())) 251 | return QRect(int(p1.x()), int(p1.y()), int(p2.x() - p1.x()), int(p2.y() - p1.y())) 252 | 253 | def __export(self): 254 | settings = QSettings() 255 | format = self.dialogui.comboBox_fileformat.itemData(self.dialogui.comboBox_fileformat.currentIndex()) 256 | filepath = QFileDialog.getSaveFileName( 257 | self.iface.mainWindow(), 258 | self.tr("Export Layout"), 259 | settings.value("/instantprint/lastfile", ""), 260 | format 261 | ) 262 | if not all(filepath): 263 | return 264 | 265 | # Ensure output filename has correct extension 266 | filename = os.path.splitext(filepath[0])[0] + "." + self.dialogui.comboBox_fileformat.currentText().lower() 267 | settings.setValue("/instantprint/lastfile", filepath[0]) 268 | 269 | if self.populateCompositionFz: 270 | self.populateCompositionFz(self.layoutView.composition()) 271 | 272 | success = False 273 | layout_name = self.dialogui.comboBox_layouts.currentText() 274 | layout_item = self.projectLayoutManager.layoutByName(layout_name) 275 | layout_item.refresh() 276 | exporter = QgsLayoutExporter(layout_item) 277 | if filename[-3:].lower() == u"pdf": 278 | success = exporter.exportToPdf(filepath[0], QgsLayoutExporter.PdfExportSettings()) 279 | else: 280 | success = exporter.exportToImage(filepath[0], QgsLayoutExporter.ImageExportSettings()) 281 | if success != 0: 282 | QMessageBox.warning(self.iface.mainWindow(), self.tr("Export Failed"), self.tr("Failed to export the layout.")) 283 | 284 | def __print(self): 285 | layout_name = self.dialogui.comboBox_layouts.currentText() 286 | layout_item = self.projectLayoutManager.layoutByName(layout_name) 287 | layout_item.refresh() 288 | actual_printer = QgsLayoutExporter(layout_item) 289 | 290 | printdialog = QPrintDialog(self.printer) 291 | if printdialog.exec_() != QDialog.Accepted: 292 | return 293 | 294 | success = actual_printer.print(self.printer, QgsLayoutExporter.PrintExportSettings()) 295 | 296 | if success != 0: 297 | QMessageBox.warning(self.iface.mainWindow(), self.tr("Print Failed"), self.tr("Failed to print the layout.")) 298 | 299 | def __reloadLayouts(self, removed=None): 300 | if not self.dialog.isVisible(): 301 | # Make it less likely to hit the issue outlined in https://github.com/qgis/QGIS/pull/1938 302 | return 303 | 304 | self.dialogui.comboBox_layouts.blockSignals(True) 305 | prev = None 306 | if self.dialogui.comboBox_layouts.currentIndex() >= 0: 307 | prev = self.dialogui.comboBox_layouts.currentText() 308 | self.dialogui.comboBox_layouts.clear() 309 | active = 0 310 | for layout in self.projectLayoutManager.layouts(): 311 | if layout != removed and layout.name(): 312 | cur = layout.name() 313 | self.dialogui.comboBox_layouts.addItem(cur, layout) 314 | if prev == cur: 315 | active = self.dialogui.comboBox_layouts.count() - 1 316 | self.dialogui.comboBox_layouts.setCurrentIndex(-1) # Ensure setCurrentIndex below actually changes an index 317 | self.dialogui.comboBox_layouts.blockSignals(False) 318 | if self.dialogui.comboBox_layouts.count() > 0: 319 | self.dialogui.comboBox_layouts.setCurrentIndex(active) 320 | self.dialogui.comboBox_scale.setEnabled(True) 321 | self.exportButton.setEnabled(True) 322 | else: 323 | self.exportButton.setEnabled(False) 324 | self.dialogui.comboBox_scale.setEnabled(False) 325 | 326 | def __help(self): 327 | manualPath = os.path.join(os.path.dirname(__file__), "help", "documentation.pdf") 328 | QDesktopServices.openUrl(QUrl.fromLocalFile(manualPath)) 329 | 330 | def scaleFromString(self, scaleText): 331 | locale = QLocale() 332 | parts = [locale.toInt(part) for part in scaleText.split(":")] 333 | try: 334 | if len(parts) == 2 and parts[0][1] and parts[1][1] and parts[0][0] != 0 and parts[1][0] != 0: 335 | return float(parts[0][0]) / float(parts[1][0]) 336 | else: 337 | return None 338 | except ZeroDivisionError: 339 | return 340 | 341 | def check_scales(self): 342 | predefScalesStr = QSettings().value("Map/scales", PROJECT_SCALES).split(",") 343 | predefScales = [self.scaleFromString(scaleString) for scaleString in predefScalesStr] 344 | 345 | comboScalesStr = [self.dialogui.comboBox_scale.itemText(i) for i in range(self.dialogui.comboBox_scale.count())] 346 | comboScales = [self.scaleFromString(scaleString) for scaleString in comboScalesStr] 347 | 348 | currentScale = self.scaleFromString(self.dialogui.comboBox_scale.currentText()) 349 | 350 | if not currentScale: 351 | self.dialogui.comboBox_scale.lineEdit().setStyleSheet("background: #FF7777; color: #FFFFFF;") 352 | self.dialogui.addScale.setVisible(True) 353 | self.dialogui.addScale.setEnabled(False) 354 | self.dialogui.deleteScale.setVisible(False) 355 | else: 356 | self.dialogui.comboBox_scale.lineEdit().setStyleSheet("") 357 | if currentScale in comboScales: 358 | # If entry scale is already in the list, allow removing it unless it is a predefined scale 359 | self.dialogui.addScale.setVisible(False) 360 | self.dialogui.deleteScale.setVisible(True) 361 | self.dialogui.deleteScale.setEnabled(currentScale not in predefScales) 362 | else: 363 | # Otherwise, show button to add it 364 | self.dialogui.addScale.setVisible(True) 365 | self.dialogui.addScale.setEnabled(True) 366 | self.dialogui.deleteScale.setVisible(False) 367 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | git archive --prefix=instantprint/ -o instantprint.zip master 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Instant Print plugin for QGIS 2 | ============================= 3 | 4 | The instant print plugin allows to quickly print map excerpts to a file, utilizing an existing composer as page layout. 5 | 6 | ![screenshot](help/img/screenshot.png) 7 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # copyright : (C) 2014-2015 by Sandro Mani / Sourcepole AG 9 | # email : smani@sourcepole.ch 10 | 11 | 12 | def classFactory(iface): 13 | from .InstantPrintPlugin import InstantPrintPlugin 14 | return InstantPrintPlugin(iface) 15 | -------------------------------------------------------------------------------- /help/documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/help/documentation.pdf -------------------------------------------------------------------------------- /help/documentation.tex: -------------------------------------------------------------------------------- 1 | \pdfobjcompresslevel=1 2 | \newcommand{\doctitle}{QGIS Instant Print Plugin} 3 | \newcommand{\docauthor}{Sandro Mani} 4 | 5 | \documentclass[11pt,twoside,a4paper]{report} 6 | %Language, input 7 | \usepackage[english]{babel} 8 | \usepackage[utf8]{inputenc} 9 | \usepackage[T1]{fontenc} 10 | \selectlanguage{english} 11 | %\mathcode`\.="613A % Uncomment if using coma as decimal separator 12 | %\mathcode`\,="013B % Uncomment if using dot as decimal separator 13 | 14 | %Geometry, Documentstyle 15 | \usepackage{geometry,rotating,tabls} 16 | \geometry{a4paper,twoside=true,inner=3cm,outer=2cm} 17 | \setlength{\headheight}{14pt} 18 | \addtolength{\voffset}{-1cm} 19 | \addtolength{\textheight}{4cm} 20 | \linespread{1.3} \sloppy 21 | \parindent=0cm 22 | \setlength{\parskip}{1.5ex} 23 | 24 | 25 | %Headers, Footers 26 | \usepackage{fancyhdr} 27 | \pagestyle{fancy} \fancyhf{} 28 | \fancyhead[L]{\doctitle} 29 | \fancyhead[R]{\includegraphics[width=.25\textwidth]{logo_text.pdf}} 30 | \renewcommand{\footrulewidth}{0.4pt} 31 | \fancyfoot[R]{\nouppercase{\thepage}} 32 | 33 | \fancypagestyle{plain}{ 34 | \pagestyle{fancy} \fancyhf{} 35 | \fancyhead[L]{\doctitle} 36 | \fancyhead[R]{\includegraphics[width=.25\textwidth]{logo_text.pdf}} 37 | \renewcommand{\footrulewidth}{0.4pt} 38 | \fancyfoot[R]{\nouppercase{\thepage}} 39 | } 40 | 41 | 42 | %Graphics, Pictures 43 | \usepackage{color,graphicx} 44 | \usepackage[footnotesize,hang,it]{caption} 45 | \setlength{\captionmargin}{20pt} 46 | \graphicspath{{img/}} 47 | 48 | %Footnotes, Lists 49 | \usepackage{footnote,paralist,enumerate} 50 | \usepackage[stable]{footmisc} 51 | \makesavenoteenv{tabular} 52 | \makesavenoteenv{figure} 53 | \makesavenoteenv{itemize} 54 | 55 | %Index, Bibliography 56 | \usepackage{makeidx,tocbibind} % Use \tableofcontents resp \makeindex 57 | \makeindex 58 | 59 | %Hyperref 60 | \usepackage[pdftitle={\doctitle},pdfauthor={\docauthor, Sourcepole AG},pdfdisplaydoctitle={false}]{hyperref} 61 | \hypersetup{colorlinks=false,linkcolor=blue,anchorcolor=red,citecolor=blue,filecolor=red,urlcolor=blue} 62 | 63 | %Font 64 | \renewcommand{\familydefault}{\sfdefault} 65 | 66 | %Chapter style 67 | \usepackage{titlesec,color} 68 | \titleformat{\chapter}[hang]{\Huge\bfseries}{\thechapter\quad\textcolor[rgb]{0.75,0.75,0.75}{|}\quad}{0pt}{\Huge\bfseries} 69 | 70 | %Misc 71 | \usepackage{tabularx} 72 | 73 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 | \begin{document} 75 | \thispagestyle{empty} 76 | \begin{flushright} 77 | \includegraphics[width=.5\textwidth]{logo_full.pdf}\\[5mm] 78 | \begin{minipage}{.5\textwidth} 79 | \begin{center} 80 | \small{ 81 | Sourcepole AG | Weberstrasse 5 | 8004 Zürich\\ 82 | Tel. +41 44 440 77 11 | Fax +41 44 440 77 12\\ 83 | info@sourcepole.ch | www.sourcepole.ch 84 | } 85 | \end{center} 86 | \end{minipage} 87 | \end{flushright} 88 | \vfill 89 | {\huge{\textbf{\doctitle}}} 90 | \vfill 91 | \begin{tabular}{ll} 92 | Version: & 1.0\\ 93 | Author: & \docauthor\\ 94 | Date: & \today\\ 95 | \end{tabular} 96 | 97 | \newpage 98 | 99 | \chapter*{Usage} 100 | 101 | The instant print plugin allows to quickly print map excerpts to a file, utilizing an existing composer as page layout. 102 | 103 | To use the instant print tool, a composer needs to be created first. The only requirement is that it contains exactly one map item. 104 | 105 | The instant print tool can then be activated from the plugin toolbar by clicking on the plugin icon \includegraphics[height=11pt]{../icons/icon.png}. 106 | 107 | In the dialog window which appears, one can pick the composer to use as page layout. A selection rectangle is displayed in the map canvas, sized according to the size of the map item in the composer and the scale chosen in the instant print dialog. The selection rectangle can be freely dragged around to choose the region one wishes to print. When dragging the selection rectangle, the previous rectangle is shown shaded and can be used as a snap reference when setting the new region. While the instant print tool is active, the canvas can be panned with the middle mouse button. 108 | 109 | \begin{center} 110 | \includegraphics[width=.5\textwidth]{img/screenshot.jpg} 111 | \end{center} 112 | 113 | 114 | Clicking on the Export button in the instant print dialog opens a file save dialog which allows one to save the composer with the selected map excerpt. 115 | 116 | \newpage 117 | {\Large{\textbf{Version history}}} 118 | {\small{ 119 | \begin{center} 120 | \begin{tabularx}{\textwidth}{|c|c|l|X|} 121 | \hline 122 | \textbf{Version} & \textbf{Date} & \textbf{Author} & \textbf{Description} \\\hline 123 | 1.0 & 26.02.2015 & Sandro Mani & First release \\\hline 124 | 1.0.1 & 18.03.2015 & Sandro Mani & Ensure export filename has correct extension. \\ 125 | & & & Partial workaround for QGIS bug causing crashes when closing a project with more than one composer. (To prevent crashes, make sure the Instant Print dialog is closed before closing a project.)\\\hline 126 | 1.0.2 & 15.06.2015 & Sandro Mani & Fix cursor not unsetting after tool deactivated \\ 127 | & & & Add support for PyQt4 < 4.8.4 \\\hline 128 | \end{tabularx} 129 | \end{center} 130 | }} 131 | 132 | 133 | \end{document} 134 | -------------------------------------------------------------------------------- /help/img/logo_full.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/help/img/logo_full.pdf -------------------------------------------------------------------------------- /help/img/logo_text.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/help/img/logo_text.pdf -------------------------------------------------------------------------------- /help/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/help/img/screenshot.png -------------------------------------------------------------------------------- /i18n/instantprint_de.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/i18n/instantprint_de.qm -------------------------------------------------------------------------------- /i18n/instantprint_de.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | InstantPrintDialog 6 | 7 | 8 | Instant Print 9 | Sofortdruck 10 | 11 | 12 | 13 | Layout: 14 | Drucklayout: 15 | 16 | 17 | 18 | Scale: 19 | Skala: 20 | 21 | 22 | 23 | File format: 24 | Dateiformat: 25 | 26 | 27 | 28 | InstantPrintPlugin 29 | 30 | 31 | Instant Print 32 | Sofortdruck 33 | 34 | 35 | 36 | InstantPrintTool 37 | 38 | 39 | Export 40 | Export 41 | 42 | 43 | 44 | Print 45 | Drucken 46 | 47 | 48 | 49 | Help 50 | Hilfe 51 | 52 | 53 | 54 | PDF Document (*.pdf);; 55 | PDF-Dokument (*.pdf);; 56 | 57 | 58 | 59 | JPG Image (*.jpg);; 60 | JPG-Bild (*.jpg);; 61 | 62 | 63 | 64 | BMP Image (*.bmp);; 65 | BMP-Bild (*.bmp);; 66 | 67 | 68 | 69 | PNG Image (*.png);; 70 | PNG-Bild (*.png);; 71 | 72 | 73 | 74 | Invalid layout 75 | Ungültiges Drucklayout 76 | 77 | 78 | 79 | The layout must have exactly one map item. 80 | Das Drucklayout muss genau ein Kartenelement enthalten. 81 | 82 | 83 | 84 | Export Layout 85 | Drucklayout exportieren 86 | 87 | 88 | 89 | Export Failed 90 | Export fehlgeschlagen 91 | 92 | 93 | 94 | Failed to export the layout. 95 | Das Drucklayout konnte nicht exportiert werden. 96 | 97 | 98 | 99 | Print Failed 100 | Drucken fehlgeschlagen 101 | 102 | 103 | 104 | Failed to print the layout. 105 | Das Drucklayout konnte nicht gedruckt werden. 106 | 107 | 108 | 109 | Ui_InstantPrintDialog 110 | 111 | 112 | Instant Print 113 | Sofortdruck 114 | 115 | 116 | 117 | Layout: 118 | Drucklayout: 119 | 120 | 121 | 122 | Scale: 123 | Skala: 124 | 125 | 126 | 127 | File format: 128 | Dateiformat: 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /i18n/instantprint_it.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/i18n/instantprint_it.qm -------------------------------------------------------------------------------- /i18n/instantprint_it.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | InstantPrintDialog 6 | 7 | 8 | Instant Print 9 | Stampa instantanea 10 | 11 | 12 | 13 | Layout: 14 | 15 | 16 | 17 | Composer: 18 | Composizione: 19 | 20 | 21 | 22 | File format: 23 | Formato: 24 | 25 | 26 | 27 | Scale: 28 | Scala: 29 | 30 | 31 | 32 | InstantPrintPlugin 33 | 34 | 35 | 36 | Instant Print 37 | Stampa instantanea 38 | 39 | 40 | 41 | InstantPrintTool 42 | 43 | 44 | Export 45 | Esporta 46 | 47 | 48 | 49 | Print 50 | 51 | 52 | 53 | 54 | Help 55 | Aiuto 56 | 57 | 58 | 59 | PDF Document (*.pdf);; 60 | Documento PDF (*.pdf);; 61 | 62 | 63 | 64 | JPG Image (*.jpg);; 65 | Immagine JPG (*.jpg);; 66 | 67 | 68 | 69 | BMP Image (*.bmp);; 70 | Immagine BMP (*.bmp);; 71 | 72 | 73 | 74 | PNG Image (*.png);; 75 | Immagine PNG (*.png);; 76 | 77 | 78 | 79 | Invalid layout 80 | 81 | 82 | 83 | 84 | The layout must have exactly one map item. 85 | 86 | 87 | 88 | 89 | Export Layout 90 | 91 | 92 | 93 | 94 | Export Failed 95 | 96 | 97 | 98 | 99 | Failed to export the layout. 100 | 101 | 102 | 103 | 104 | Failed to print the layout. 105 | 106 | 107 | 108 | Invalid composer 109 | Composizione invalida 110 | 111 | 112 | The composer must have exactly one map item. 113 | La composizione deve contenere esattamente una mappa. 114 | 115 | 116 | Print Composition 117 | Stampa composizione 118 | 119 | 120 | 121 | Print Failed 122 | Stampa non riuscita 123 | 124 | 125 | Failed to print the composition. 126 | La stampa della composizione non è riuscita. 127 | 128 | 129 | 130 | Ui_InstantPrintDialog 131 | 132 | 133 | Instant Print 134 | Stampa instantanea 135 | 136 | 137 | 138 | Layout: 139 | 140 | 141 | 142 | 143 | Scale: 144 | Scala: 145 | 146 | 147 | 148 | File format: 149 | Formato: 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /i18n/instantprint_ja.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/i18n/instantprint_ja.qm -------------------------------------------------------------------------------- /i18n/instantprint_ja.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | InstantPrintDialog 6 | 7 | 8 | Instant Print 9 | 簡単印刷 10 | 11 | 12 | 13 | Layout: 14 | レイアウト: 15 | 16 | 17 | 18 | Scale: 19 | 縮尺: 20 | 21 | 22 | 23 | File format: 24 | ファイル形式: 25 | 26 | 27 | 28 | InstantPrintPlugin 29 | 30 | 31 | 32 | Instant Print 33 | 簡単印刷 34 | 35 | 36 | 37 | InstantPrintTool 38 | 39 | 40 | Export 41 | 出力 42 | 43 | 44 | 45 | Print 46 | 印刷 47 | 48 | 49 | 50 | Help 51 | ヘルプ 52 | 53 | 54 | 55 | PDF Document (*.pdf);; 56 | 57 | 58 | 59 | 60 | JPG Image (*.jpg);; 61 | 62 | 63 | 64 | 65 | BMP Image (*.bmp);; 66 | 67 | 68 | 69 | 70 | PNG Image (*.png);; 71 | 72 | 73 | 74 | 75 | Invalid layout 76 | レイアウトが無効です 77 | 78 | 79 | 80 | The layout must have exactly one map item. 81 | レイアウトには最低1つのマップアイテムがなければならない。 82 | 83 | 84 | 85 | Export Layout 86 | 出力するレイアウト 87 | 88 | 89 | 90 | Export Failed 91 | エクスポートに失敗しました 92 | 93 | 94 | 95 | Failed to export the layout. 96 | レイアウトの出力に失敗しました。 97 | 98 | 99 | 100 | Print Failed 101 | 印刷に失敗しました 102 | 103 | 104 | 105 | Failed to print the layout. 106 | レイアウトの印刷に失敗しました。 107 | 108 | 109 | 110 | Ui_InstantPrintDialog 111 | 112 | 113 | Instant Print 114 | 簡単印刷 115 | 116 | 117 | 118 | Layout: 119 | レイアウト: 120 | 121 | 122 | 123 | Scale: 124 | 縮尺: 125 | 126 | 127 | 128 | File format: 129 | ファイル形式: 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/icons/icon.png -------------------------------------------------------------------------------- /instantprint_ts.pro: -------------------------------------------------------------------------------- 1 | SOURCES += \ 2 | InstantPrintPlugin.py \ 3 | InstantPrintTool.py \ 4 | ui/ui_printdialog.py 5 | 6 | FORMS = ui/printdialog.ui 7 | 8 | TRANSLATIONS += i18n/instantprint_de.ts \ 9 | i18n/instantprint_it.ts \ 10 | i18n/instantprint_ja.ts 11 | -------------------------------------------------------------------------------- /instantprint_ts.pro.qtds: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {f8846bc4-233b-4f0d-99a5-65c8e21a01d0} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | false 41 | true 42 | false 43 | 0 44 | true 45 | true 46 | 0 47 | 8 48 | true 49 | false 50 | 1 51 | true 52 | true 53 | true 54 | *.md, *.MD, Makefile 55 | false 56 | true 57 | 58 | 59 | 60 | ProjectExplorer.Project.Target.0 61 | 62 | Desktop 63 | Desktop Qt 6.3.1 64 | Desktop Qt 6.3.1 65 | {63f87550-2541-4163-9631-08b7fea781da} 66 | 0 67 | 0 68 | 0 69 | 70 | 0 71 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Desktop_Qt_6_3_1-Debug 72 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Desktop_Qt_6_3_1-Debug 73 | 74 | 75 | true 76 | QtProjectManager.QMakeBuildStep 77 | false 78 | 79 | 80 | 81 | true 82 | Qt4ProjectManager.MakeStep 83 | 84 | 2 85 | Build 86 | Build 87 | ProjectExplorer.BuildSteps.Build 88 | 89 | 90 | 91 | true 92 | Qt4ProjectManager.MakeStep 93 | clean 94 | 95 | 1 96 | Clean 97 | Clean 98 | ProjectExplorer.BuildSteps.Clean 99 | 100 | 2 101 | false 102 | 103 | false 104 | 105 | Debug 106 | Qt4ProjectManager.Qt4BuildConfiguration 107 | 2 108 | 109 | 110 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Desktop_Qt_6_3_1-Release 111 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Desktop_Qt_6_3_1-Release 112 | 113 | 114 | true 115 | QtProjectManager.QMakeBuildStep 116 | false 117 | 118 | 119 | 120 | true 121 | Qt4ProjectManager.MakeStep 122 | 123 | 2 124 | Build 125 | Build 126 | ProjectExplorer.BuildSteps.Build 127 | 128 | 129 | 130 | true 131 | Qt4ProjectManager.MakeStep 132 | clean 133 | 134 | 1 135 | Clean 136 | Clean 137 | ProjectExplorer.BuildSteps.Clean 138 | 139 | 2 140 | false 141 | 142 | false 143 | 144 | Release 145 | Qt4ProjectManager.Qt4BuildConfiguration 146 | 0 147 | 0 148 | 149 | 150 | 0 151 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Desktop_Qt_6_3_1-Profile 152 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Desktop_Qt_6_3_1-Profile 153 | 154 | 155 | true 156 | QtProjectManager.QMakeBuildStep 157 | false 158 | 159 | 160 | 161 | true 162 | Qt4ProjectManager.MakeStep 163 | 164 | 2 165 | Build 166 | Build 167 | ProjectExplorer.BuildSteps.Build 168 | 169 | 170 | 171 | true 172 | Qt4ProjectManager.MakeStep 173 | clean 174 | 175 | 1 176 | Clean 177 | Clean 178 | ProjectExplorer.BuildSteps.Clean 179 | 180 | 2 181 | false 182 | 183 | false 184 | 185 | Profile 186 | Qt4ProjectManager.Qt4BuildConfiguration 187 | 0 188 | 0 189 | 0 190 | 191 | 3 192 | 193 | 194 | 0 195 | Deploy 196 | Deploy 197 | ProjectExplorer.BuildSteps.Deploy 198 | 199 | 1 200 | 201 | false 202 | ProjectExplorer.DefaultDeployConfiguration 203 | 204 | 1 205 | 206 | true 207 | 208 | 2 209 | 210 | ProjectExplorer.CustomExecutableRunConfiguration 211 | 212 | false 213 | true 214 | false 215 | true 216 | 217 | 1 218 | 219 | 220 | 221 | ProjectExplorer.Project.Target.1 222 | 223 | Android.Device.Type 224 | Android device 225 | Android device 226 | {fcfcb7a6-2c80-4785-b1a9-02d08953be61} 227 | 0 228 | 0 229 | 0 230 | 231 | 0 232 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Android_device-Debug 233 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Android_device-Debug 234 | 235 | 236 | true 237 | QtProjectManager.QMakeBuildStep 238 | false 239 | 240 | 241 | 242 | true 243 | Qt4ProjectManager.MakeStep 244 | 245 | 246 | true 247 | Copy application data 248 | Qt4ProjectManager.AndroidPackageInstallationStep 249 | 250 | 251 | 252 | 253 | true 254 | Build Android APK 255 | QmakeProjectManager.AndroidBuildApkStep 256 | false 257 | 258 | 4 259 | Build 260 | Build 261 | ProjectExplorer.BuildSteps.Build 262 | 263 | 264 | 265 | true 266 | Qt4ProjectManager.MakeStep 267 | clean 268 | 269 | 1 270 | Clean 271 | Clean 272 | ProjectExplorer.BuildSteps.Clean 273 | 274 | 2 275 | false 276 | 277 | false 278 | 279 | Debug 280 | Qt4ProjectManager.Qt4BuildConfiguration 281 | 2 282 | 283 | 284 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Android_device-Release 285 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Android_device-Release 286 | 287 | 288 | true 289 | QtProjectManager.QMakeBuildStep 290 | false 291 | 292 | 293 | 294 | true 295 | Qt4ProjectManager.MakeStep 296 | 297 | 298 | true 299 | Copy application data 300 | Qt4ProjectManager.AndroidPackageInstallationStep 301 | 302 | 303 | 304 | 305 | true 306 | Build Android APK 307 | QmakeProjectManager.AndroidBuildApkStep 308 | false 309 | 310 | 4 311 | Build 312 | Build 313 | ProjectExplorer.BuildSteps.Build 314 | 315 | 316 | 317 | true 318 | Qt4ProjectManager.MakeStep 319 | clean 320 | 321 | 1 322 | Clean 323 | Clean 324 | ProjectExplorer.BuildSteps.Clean 325 | 326 | 2 327 | false 328 | 329 | false 330 | 331 | Release 332 | Qt4ProjectManager.Qt4BuildConfiguration 333 | 0 334 | 0 335 | 336 | 337 | 0 338 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Android_device-Profile 339 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Android_device-Profile 340 | 341 | 342 | true 343 | QtProjectManager.QMakeBuildStep 344 | false 345 | 346 | 347 | 348 | true 349 | Qt4ProjectManager.MakeStep 350 | 351 | 352 | true 353 | Copy application data 354 | Qt4ProjectManager.AndroidPackageInstallationStep 355 | 356 | 357 | 358 | 359 | true 360 | Build Android APK 361 | QmakeProjectManager.AndroidBuildApkStep 362 | false 363 | 364 | 4 365 | Build 366 | Build 367 | ProjectExplorer.BuildSteps.Build 368 | 369 | 370 | 371 | true 372 | Qt4ProjectManager.MakeStep 373 | clean 374 | 375 | 1 376 | Clean 377 | Clean 378 | ProjectExplorer.BuildSteps.Clean 379 | 380 | 2 381 | false 382 | 383 | false 384 | 385 | Profile 386 | Qt4ProjectManager.Qt4BuildConfiguration 387 | 0 388 | 0 389 | 0 390 | 391 | 3 392 | 393 | 394 | 395 | true 396 | Qt4ProjectManager.AndroidDeployQtStep 397 | 398 | 1 399 | Deploy 400 | Deploy 401 | ProjectExplorer.BuildSteps.Deploy 402 | 403 | 1 404 | 405 | false 406 | Qt4ProjectManager.AndroidDeployConfiguration2 407 | 408 | 1 409 | 410 | true 411 | 412 | 2 413 | 414 | ProjectExplorer.CustomExecutableRunConfiguration 415 | 416 | false 417 | true 418 | false 419 | true 420 | 421 | 1 422 | 423 | 424 | 425 | ProjectExplorer.Project.Target.2 426 | 427 | Desktop 428 | Desktop Qt 5.15.5 429 | Desktop Qt 5.15.5 430 | {8994bd34-5ed9-4c45-8c0a-94c8f33eca4a} 431 | 0 432 | 0 433 | 0 434 | 435 | 0 436 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Desktop_Qt_5_15_5-Debug 437 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Desktop_Qt_5_15_5-Debug 438 | 439 | 440 | true 441 | QtProjectManager.QMakeBuildStep 442 | false 443 | 444 | 445 | 446 | true 447 | Qt4ProjectManager.MakeStep 448 | 449 | 2 450 | Build 451 | Build 452 | ProjectExplorer.BuildSteps.Build 453 | 454 | 455 | 456 | true 457 | Qt4ProjectManager.MakeStep 458 | clean 459 | 460 | 1 461 | Clean 462 | Clean 463 | ProjectExplorer.BuildSteps.Clean 464 | 465 | 2 466 | false 467 | 468 | false 469 | 470 | Debug 471 | Qt4ProjectManager.Qt4BuildConfiguration 472 | 2 473 | 474 | 475 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Desktop_Qt_5_15_5-Release 476 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Desktop_Qt_5_15_5-Release 477 | 478 | 479 | true 480 | QtProjectManager.QMakeBuildStep 481 | false 482 | 483 | 484 | 485 | true 486 | Qt4ProjectManager.MakeStep 487 | 488 | 2 489 | Build 490 | Build 491 | ProjectExplorer.BuildSteps.Build 492 | 493 | 494 | 495 | true 496 | Qt4ProjectManager.MakeStep 497 | clean 498 | 499 | 1 500 | Clean 501 | Clean 502 | ProjectExplorer.BuildSteps.Clean 503 | 504 | 2 505 | false 506 | 507 | false 508 | 509 | Release 510 | Qt4ProjectManager.Qt4BuildConfiguration 511 | 0 512 | 0 513 | 514 | 515 | 0 516 | C:\Users\ryu\Documents\GitHub\build-instantprint_ts-Desktop_Qt_5_15_5-Profile 517 | C:/Users/ryu/Documents/GitHub/build-instantprint_ts-Desktop_Qt_5_15_5-Profile 518 | 519 | 520 | true 521 | QtProjectManager.QMakeBuildStep 522 | false 523 | 524 | 525 | 526 | true 527 | Qt4ProjectManager.MakeStep 528 | 529 | 2 530 | Build 531 | Build 532 | ProjectExplorer.BuildSteps.Build 533 | 534 | 535 | 536 | true 537 | Qt4ProjectManager.MakeStep 538 | clean 539 | 540 | 1 541 | Clean 542 | Clean 543 | ProjectExplorer.BuildSteps.Clean 544 | 545 | 2 546 | false 547 | 548 | false 549 | 550 | Profile 551 | Qt4ProjectManager.Qt4BuildConfiguration 552 | 0 553 | 0 554 | 0 555 | 556 | 3 557 | 558 | 559 | 0 560 | Deploy 561 | Deploy 562 | ProjectExplorer.BuildSteps.Deploy 563 | 564 | 1 565 | 566 | false 567 | ProjectExplorer.DefaultDeployConfiguration 568 | 569 | 1 570 | 571 | true 572 | 573 | 2 574 | 575 | ProjectExplorer.CustomExecutableRunConfiguration 576 | 577 | false 578 | true 579 | false 580 | true 581 | 582 | 1 583 | 584 | 585 | 586 | ProjectExplorer.Project.TargetCount 587 | 3 588 | 589 | 590 | ProjectExplorer.Project.Updater.FileVersion 591 | 22 592 | 593 | 594 | Version 595 | 22 596 | 597 | 598 | -------------------------------------------------------------------------------- /metadata.txt: -------------------------------------------------------------------------------- 1 | # This file contains metadata for your plugin. Beginning 2 | # with version 1.8 this is the preferred way to supply information about a 3 | # plugin. The current method of embedding metadata in __init__.py will 4 | # be supported until version 2.0 5 | 6 | # This file should be included when you package your plugin. 7 | 8 | # Mandatory items: 9 | 10 | 11 | [general] 12 | name=Instant Print 13 | qgisMinimumVersion=3.0 14 | qgisMaximumVersion=3.99 15 | description=Instantly print map excerpts 16 | about=The instant print plugin allows to quickly print map excerpts to a file, utilizing an existing composer as page layout. 17 | version=3.0.1 18 | author=Sandro Mani, Sourcepole AG 19 | email=smani@sourcepole.ch 20 | 21 | # end of mandatory metadata 22 | 23 | # Optional items: 24 | 25 | # Uncomment the following line and add your changelog entries: 26 | changelog= 27 | Rev 3.0.1 (24.01.2025) 28 | - Resolve "unexpected type 'float'" (@gducerf) 29 | - Refresh LayoutItem prior to printing or exporting to update Item (@ictoain) 30 | 31 | Rev 3.0.0 (08.03.2018) 32 | - QGIS 3.0 support 33 | - Allow managing predefined scales 34 | - Allow printing to physical printer 35 | - Various bug fixes 36 | 37 | Rev 1.0.2 (15.06.2015) 38 | - Fix cursor not unsetting after tool deactivated 39 | - Add support for PyQt4 < 4.8.4 40 | 41 | Rev 1.0.1 (18.03.2015) 42 | - Ensure export filename has correct extension. 43 | - Partial workaround for QGIS bug causing crashes when closing a project with more than one composer. 44 | (To prevent crashes, make sure the Instant Print dialog is closed before closing a project.) 45 | 46 | Rev 1.0.0 (26.02.2015) 47 | - Initial release 48 | 49 | # tags are comma separated with spaces allowed 50 | tags=print,composer 51 | 52 | homepage=https://github.com/sourcepole/qgis-instantprint-plugin 53 | tracker=https://github.com/sourcepole/qgis-instantprint-plugin/issues 54 | repository=https://github.com/sourcepole/qgis-instantprint-plugin 55 | icon=icons/icon.png 56 | # experimental flag 57 | experimental=False 58 | 59 | # deprecated flag (applies to the whole plugin, not just a single version 60 | deprecated=False 61 | -------------------------------------------------------------------------------- /pyqgis.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | SET QGIS_ROOT=C:\Program Files\QGIS 3.22.7 3 | call "%QGIS_ROOT%"\bin\o4w_env.bat 4 | call "%QGIS_ROOT%"\apps\grass\grass78\etc\env.bat 5 | @echo off 6 | path %PATH%;%QGIS_ROOT%\apps\qgis\bin 7 | path %PATH%;%QGIS_ROOT%\apps\grass\grass78\lib 8 | path %PATH%;%QGIS_ROOT%\apps\Qt5\bin 9 | path %PATH%;%QGIS_ROOT%\apps\Python39\Scripts 10 | set PYTHONPATH=%PYTHONPATH%;%QGIS_ROOT%\apps\qgis-ltr\python 11 | set PYTHONHOME=%QGIS_ROOT%\apps\Python39 12 | cmd.exe 13 | pyrcc5 -o resources.py resources.qrc -------------------------------------------------------------------------------- /pyrcc5.txt: -------------------------------------------------------------------------------- 1 | pyrcc5 -o resources_rc.py resources.qrc -------------------------------------------------------------------------------- /resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/icon.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources_rc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Resource object code 4 | # 5 | # Created by: The Resource Compiler for PyQt5 (Qt v5.15.2) 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore 10 | 11 | qt_resource_data = b"\ 12 | \x00\x00\x02\xa1\ 13 | \x89\ 14 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ 15 | \x00\x00\x18\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0\x77\x3d\xf8\ 16 | \x00\x00\x00\x06\x62\x4b\x47\x44\x00\x5e\x00\x5e\x00\x5e\x94\x91\ 17 | \xb5\x9c\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\ 18 | \x0d\xd7\x01\x42\x28\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\ 19 | \xdf\x02\x1a\x0c\x38\x1d\x17\x5b\xc9\x87\x00\x00\x02\x2e\x49\x44\ 20 | \x41\x54\x48\xc7\xad\x95\x4f\x68\x13\x41\x14\x87\xbf\xcd\xae\x26\ 21 | \x34\xb4\x12\x68\x93\xb4\xc6\x7a\xc8\x21\x39\x94\xb4\x8a\x01\x0f\ 22 | \xe2\xc1\x8b\xc6\x8b\xf4\x56\xf0\x16\x21\x50\xf1\xe6\x41\x2f\x22\ 23 | \x4a\xc1\x53\x11\x2f\x1b\x48\x41\x28\x52\x10\x0f\x82\xa0\x20\x8b\ 24 | \x8a\x77\x21\x4a\xa0\xda\x48\x40\x91\x4a\x36\xd2\x10\x89\x22\x6a\ 25 | \x36\x1d\x0f\xf9\x43\x36\x35\xb3\xdb\x36\x0f\x06\x66\xdf\xcc\xfc\ 26 | \xbe\x99\x37\x6f\xdf\x28\x42\x08\xf6\x6d\x45\x45\x21\xf6\x1f\xa1\ 27 | \xa2\xa2\x28\x43\x01\xb4\xc4\xfa\x85\x9e\x13\x13\x29\x4d\xb6\x26\ 28 | \xb7\xb2\x62\x36\x2d\x2b\x24\x9b\xa3\x6a\x5a\x25\x73\x3a\x73\xa3\ 29 | \xcf\x5d\x27\x26\x52\x00\x52\x40\xd3\xb2\x42\x99\xc5\x45\xe9\xc6\ 30 | \x73\xd9\x6c\x08\xb8\xd2\xe7\x3e\xd9\xe9\x78\xf6\x1b\x99\x51\x5f\ 31 | \x15\x20\xd1\xe3\xba\x46\x4c\x7c\x18\x1a\x60\x26\xf2\xba\xdf\xe5\ 32 | \xa1\xa8\xdc\xa4\xa8\x5c\x70\x0c\x91\x1b\x4b\x1c\x79\xd5\xef\xba\ 33 | \x03\x54\x81\x88\x0d\x90\xca\x5c\x3f\x3b\x15\x9c\x58\x3d\xa0\xa9\ 34 | \x21\x94\x96\x6f\x36\xe8\x95\x8a\x2b\xf5\x87\x78\xda\xc9\x23\x04\ 35 | \x28\xed\x75\x57\xd7\xe6\x2f\x2f\xdf\x7e\xfc\xdb\x06\x98\x0a\x4e\ 36 | \xac\x9e\x38\x96\x08\x05\x02\x81\xae\x40\xad\xf8\x46\x0a\x10\x63\ 37 | \x0b\x64\xd7\x6a\x04\x62\x49\x16\x0e\x27\x01\x58\x7a\x79\x8b\xfc\ 38 | \xe7\xef\xcb\xc0\x23\x1b\xc0\xa3\x60\x13\x07\xd0\xbc\x3e\x72\xd9\ 39 | \xac\x14\xa2\x79\x7d\xcc\x8d\xdd\x05\xe0\x45\x79\x09\xe1\x9f\xc3\ 40 | \x6a\x1a\x91\xee\x78\xa7\xf3\xf5\xdb\x16\x7f\x1b\x16\x9a\xaa\xd2\ 41 | \x09\x91\xff\xe8\x8c\xab\x7b\x88\x8f\xa6\x79\x57\xbb\xc4\x5b\x33\ 42 | \x09\x34\xec\x1b\xe8\x74\x7e\xfc\xfc\xc5\x97\x4a\x95\x83\xda\xee\ 43 | \xee\x7d\x76\xfc\x19\xc5\xda\x29\x9e\x7e\x9c\x47\x88\xc6\xce\x13\ 44 | \xda\x62\x2a\xe0\x4f\xc3\x02\xa0\xbc\x91\x77\x05\x38\x77\xc6\xe0\ 45 | \xde\x93\x8b\x4c\xc6\x07\x84\x70\xd0\xc2\xf2\x46\x9e\x68\x34\x2a\ 46 | \x15\x3f\xe4\xaf\xf3\xc0\x38\x4f\xb9\x94\x67\x32\x7e\x7c\x77\x00\ 47 | \xc0\x11\x00\x30\x0e\x94\x4a\x9f\x06\x8e\x7b\x1c\x0a\x99\x23\xc0\ 48 | \x69\x4e\x77\x54\x53\xd5\x4d\xd3\x34\x23\xe1\x70\xb8\xb7\xd8\xe1\ 49 | \xa2\xd8\xd9\xbe\x4d\xd3\x44\x53\xd5\xcd\x1d\x00\x21\xb6\xd3\xef\ 50 | \xd7\xd7\xef\x17\x0a\x85\x56\x0e\x8f\x4c\x0f\x14\xe9\x58\x07\xbe\ 51 | \x35\x32\x8d\x61\x18\xdd\x8d\x0a\xb1\x9d\xee\xc9\x1c\x31\xb0\xe9\ 52 | \xba\x2e\x2c\x21\xa4\x4d\xd7\x75\x21\xd3\x70\x95\xf4\x4e\x27\x70\ 53 | \x75\x07\x32\x73\x23\xb4\x27\x80\xaa\x69\x95\xf6\x8b\x25\x9d\x23\ 54 | \xad\xb8\x43\x7b\xf4\xf7\xf2\x1f\x0c\xc3\xfe\x01\x58\x1f\xf8\x21\ 55 | \xab\x0f\x26\x08\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ 56 | \ 57 | " 58 | 59 | qt_resource_name = b"\ 60 | \x00\x07\ 61 | \x07\x3b\xe0\xb3\ 62 | \x00\x70\ 63 | \x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\ 64 | \x00\x0c\ 65 | \x0b\xbc\xdd\x54\ 66 | \x00\x69\ 67 | \x00\x6e\x00\x73\x00\x74\x00\x61\x00\x6e\x00\x74\x00\x70\x00\x72\x00\x69\x00\x6e\x00\x74\ 68 | \x00\x05\ 69 | \x00\x6f\xa6\x53\ 70 | \x00\x69\ 71 | \x00\x63\x00\x6f\x00\x6e\x00\x73\ 72 | \x00\x08\ 73 | \x0a\x61\x5a\xa7\ 74 | \x00\x69\ 75 | \x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ 76 | " 77 | 78 | qt_resource_struct_v1 = b"\ 79 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 80 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ 81 | \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ 82 | \x00\x00\x00\x32\x00\x02\x00\x00\x00\x01\x00\x00\x00\x04\ 83 | \x00\x00\x00\x42\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 84 | " 85 | 86 | qt_resource_struct_v2 = b"\ 87 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 88 | \x00\x00\x00\x00\x00\x00\x00\x00\ 89 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ 90 | \x00\x00\x00\x00\x00\x00\x00\x00\ 91 | \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ 92 | \x00\x00\x00\x00\x00\x00\x00\x00\ 93 | \x00\x00\x00\x32\x00\x02\x00\x00\x00\x01\x00\x00\x00\x04\ 94 | \x00\x00\x00\x00\x00\x00\x00\x00\ 95 | \x00\x00\x00\x42\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 96 | \x00\x00\x01\x81\xce\x7c\xbe\x00\ 97 | " 98 | 99 | qt_version = [int(v) for v in QtCore.qVersion().split('.')] 100 | if qt_version < [5, 8, 0]: 101 | rcc_version = 1 102 | qt_resource_struct = qt_resource_struct_v1 103 | else: 104 | rcc_version = 2 105 | qt_resource_struct = qt_resource_struct_v2 106 | 107 | def qInitResources(): 108 | QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) 109 | 110 | def qCleanupResources(): 111 | QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) 112 | 113 | qInitResources() 114 | -------------------------------------------------------------------------------- /ui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcepole/qgis-instantprint-plugin/33058ad63eada1c95ed3dc743990cfd1337c95fc/ui/__init__.py -------------------------------------------------------------------------------- /ui/printdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | InstantPrintDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 357 10 | 157 11 | 12 | 13 | 14 | Instant Print 15 | 16 | 17 | 18 | qgis-instantprint-plugin/uiqgis-instantprint-plugin/ui 19 | 20 | 21 | 22 | 23 | 24 | Layout: 25 | 26 | 27 | 28 | 29 | 30 | 31 | false 32 | 33 | 34 | 35 | 36 | 37 | 38 | Scale: 39 | 40 | 41 | 42 | 43 | 44 | 45 | File format: 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Qt::Horizontal 56 | 57 | 58 | QDialogButtonBox::Close 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 0 67 | 68 | 69 | 0 70 | 71 | 72 | 0 73 | 74 | 75 | 0 76 | 77 | 78 | 0 79 | 80 | 81 | 82 | 83 | true 84 | 85 | 86 | 87 | 0 88 | 0 89 | 90 | 91 | 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | false 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | false 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | QgsScaleComboBox 124 | QComboBox 125 |
qgis/gui.h
126 |
127 |
128 | 129 | 130 | 131 | buttonBox 132 | accepted() 133 | InstantPrintDialog 134 | accept() 135 | 136 | 137 | 254 138 | 198 139 | 140 | 141 | 157 142 | 205 143 | 144 | 145 | 146 | 147 | buttonBox 148 | rejected() 149 | InstantPrintDialog 150 | reject() 151 | 152 | 153 | 257 154 | 198 155 | 156 | 157 | 263 158 | 205 159 | 160 | 161 | 162 | 163 |
164 | -------------------------------------------------------------------------------- /ui/ui_printdialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/printdialog.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.9.1 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | from qgis.PyQt.QtCore import QUrl, QCoreApplication, QTranslator, QSettings 11 | 12 | class Ui_InstantPrintDialog(object): 13 | 14 | def tr(self,string): 15 | return QCoreApplication.translate('Ui_InstantPrintDialog', string) 16 | 17 | def setupUi(self, InstantPrintDialog): 18 | InstantPrintDialog.setObjectName("InstantPrintDialog") 19 | InstantPrintDialog.resize(357, 157) 20 | icon = QtGui.QIcon.fromTheme("printer") 21 | InstantPrintDialog.setWindowIcon(icon) 22 | self.gridLayout = QtWidgets.QGridLayout(InstantPrintDialog) 23 | self.gridLayout.setObjectName("gridLayout") 24 | self.label_layout = QtWidgets.QLabel(InstantPrintDialog) 25 | self.label_layout.setObjectName("label_layout") 26 | self.gridLayout.addWidget(self.label_layout, 0, 0, 1, 1) 27 | self.comboBox_layouts = QtWidgets.QComboBox(InstantPrintDialog) 28 | self.comboBox_layouts.setEditable(False) 29 | self.comboBox_layouts.setObjectName("comboBox_layouts") 30 | self.gridLayout.addWidget(self.comboBox_layouts, 0, 1, 1, 1) 31 | self.label = QtWidgets.QLabel(InstantPrintDialog) 32 | self.label.setObjectName("label") 33 | self.gridLayout.addWidget(self.label, 1, 0, 1, 1) 34 | self.label_fileformat = QtWidgets.QLabel(InstantPrintDialog) 35 | self.label_fileformat.setObjectName("label_fileformat") 36 | self.gridLayout.addWidget(self.label_fileformat, 2, 0, 1, 1) 37 | self.comboBox_fileformat = QtWidgets.QComboBox(InstantPrintDialog) 38 | self.comboBox_fileformat.setObjectName("comboBox_fileformat") 39 | self.gridLayout.addWidget(self.comboBox_fileformat, 2, 1, 1, 1) 40 | self.buttonBox = QtWidgets.QDialogButtonBox(InstantPrintDialog) 41 | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 42 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close) 43 | self.buttonBox.setObjectName("buttonBox") 44 | self.gridLayout.addWidget(self.buttonBox, 3, 0, 1, 2) 45 | self.widget = QtWidgets.QWidget(InstantPrintDialog) 46 | self.widget.setObjectName("widget") 47 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget) 48 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0) 49 | self.horizontalLayout.setSpacing(0) 50 | self.horizontalLayout.setObjectName("horizontalLayout") 51 | self.comboBox_scale = QgsScaleComboBox(self.widget) 52 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) 53 | sizePolicy.setHorizontalStretch(0) 54 | sizePolicy.setVerticalStretch(0) 55 | sizePolicy.setHeightForWidth(self.comboBox_scale.sizePolicy().hasHeightForWidth()) 56 | self.comboBox_scale.setSizePolicy(sizePolicy) 57 | self.comboBox_scale.setEditable(True) 58 | self.comboBox_scale.setObjectName("comboBox_scale") 59 | self.horizontalLayout.addWidget(self.comboBox_scale) 60 | self.deleteScale = QtWidgets.QToolButton(self.widget) 61 | self.deleteScale.setEnabled(False) 62 | self.deleteScale.setText("") 63 | self.deleteScale.setObjectName("deleteScale") 64 | self.horizontalLayout.addWidget(self.deleteScale) 65 | self.addScale = QtWidgets.QToolButton(self.widget) 66 | self.addScale.setEnabled(False) 67 | self.addScale.setText("") 68 | self.addScale.setObjectName("addScale") 69 | self.horizontalLayout.addWidget(self.addScale) 70 | self.gridLayout.addWidget(self.widget, 1, 1, 1, 1) 71 | 72 | self.retranslateUi(InstantPrintDialog) 73 | self.buttonBox.accepted.connect(InstantPrintDialog.accept) 74 | self.buttonBox.rejected.connect(InstantPrintDialog.reject) 75 | QtCore.QMetaObject.connectSlotsByName(InstantPrintDialog) 76 | 77 | def retranslateUi(self, InstantPrintDialog): 78 | _translate = QtCore.QCoreApplication.translate 79 | InstantPrintDialog.setWindowTitle(self.tr("Instant Print")) 80 | self.label_layout.setText(self.tr("Layout:")) 81 | self.label.setText(self.tr("Scale:")) 82 | self.label_fileformat.setText(self.tr("File format:")) 83 | 84 | from qgis.gui import QgsScaleComboBox 85 | --------------------------------------------------------------------------------