PK "OLP ' quick_map_services/user_services_box.ui
UserServicesBox
0
0
400
246
UserServices
User Services
-
-
-
Create service from existing
...
-
Create service
...
-
false
Edit service
...
-
false
Delete service
...
-
Qt::Vertical
20
40
PK "OL\%) ) ( quick_map_services/data_sources_model.py# -*- coding: utf-8 -*-
"""
/***************************************************************************
QuickMapServices
A QGIS plugin
Collection of internet map services
-------------------
begin : 2014-11-21
git sha : $Format:%H$
copyright : (C) 2016 by NextGIS
email : info@nextgis.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from __future__ import absolute_import
# from data_source_info import DataSourceCategory
# from group_info import
from .data_sources_list import DataSourcesList
from .groups_list import GroupsList
from qgis.PyQt.QtCore import Qt, QAbstractItemModel, QModelIndex
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QTreeWidgetItem
from .plugin_settings import PluginSettings
from .singleton import QSingleton
class DSManagerModel(QAbstractItemModel):
__metaclass__ = QSingleton
COLUMN_GROUP_DS = 0
COLUMN_VISIBILITY = 1
COLUMN_SOURCE = 2
# instance = None
# @classmethod
# def getInstance(cls):
# if cls.instance
def __init__(self, parent=None):
super(DSManagerModel, self).__init__(parent)
self.columnNames = []
self.columnNames.insert(self.COLUMN_GROUP_DS, self.tr("Group/DS"))
self.columnNames.insert(self.COLUMN_VISIBILITY, self.tr("Visible"))
self.columnNames.insert(self.COLUMN_SOURCE, self.tr("Source"))
self.rootItem = QTreeWidgetItem(self.columnNames)
self.__setupModelData()
def resetModel(self):
self.beginResetModel()
self.__clear()
self.__setupModelData()
self.endResetModel()
self.modelReset.emit()
def __clear(self):
for groupIndex in range(self.rootItem.childCount() - 1, -1, -1):
groupItem = self.rootItem.child(groupIndex)
for dsIndex in range(groupItem.childCount() - 1, -1, -1):
dsItem = groupItem.child(dsIndex)
groupItem.removeChild(dsItem)
self.rootItem.removeChild(groupItem)
def __setupModelData(self):
dsList = DataSourcesList().data_sources.values()
groupInfoList = GroupsList().groups
groupsItems = []
groups = []
for ds in dsList:
if ds.group in groups:
group_item = groupsItems[groups.index(ds.group)]
else:
group_item = QTreeWidgetItem()
group_item.setData(self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.group)
group_item.setData(self.COLUMN_VISIBILITY, Qt.DisplayRole, "")
group_item.setData(self.COLUMN_SOURCE, Qt.DisplayRole, ds.category)
group_item.setCheckState(self.COLUMN_VISIBILITY, Qt.Unchecked)
groupInfo = groupInfoList.get(ds.group)
if groupInfo is not None:
group_item.setIcon(self.COLUMN_GROUP_DS, QIcon(groupInfo.icon))
else:
group_item.setData(self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.group + " (%s!)" % self.tr("group not found"))
group_item.setData(self.COLUMN_GROUP_DS, Qt.UserRole, groupInfo)
groups.append(ds.group)
groupsItems.append(group_item)
self.rootItem.addChild(group_item)
ds_item = QTreeWidgetItem()
ds_item.setData(self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.alias)
ds_item.setIcon(self.COLUMN_GROUP_DS, QIcon(ds.icon_path))
ds_item.setData(self.COLUMN_GROUP_DS, Qt.UserRole, ds)
ds_item.setData(self.COLUMN_VISIBILITY, Qt.DisplayRole, "")
ds_item.setData(self.COLUMN_SOURCE, Qt.DisplayRole, ds.category)
ds_check_state = Qt.Checked
if ds.id in PluginSettings.get_hide_ds_id_list():
ds_check_state = Qt.Unchecked
ds_item.setCheckState(self.COLUMN_VISIBILITY, ds_check_state)
if group_item.childCount() != 0 and group_item.checkState(1) != ds_check_state:
group_item.setCheckState(self.COLUMN_VISIBILITY, Qt.PartiallyChecked)
else:
group_item.setCheckState(self.COLUMN_VISIBILITY, ds_check_state)
group_item.addChild(
ds_item
)
def setData(self, index, value, role):
if not index.isValid():
return False
else:
item = index.internalPointer()
if role == Qt.CheckStateRole:
item.setData(self.COLUMN_VISIBILITY, role, value)
self.dataChanged.emit(
index,
index
)
self.updateChecks(index, value)
return True
def updateChecks(self, index, checkState):
if self.hasChildren(index):
for row in range(0, self.rowCount(index)):
childItem = index.internalPointer().child(row)
childItem.setCheckState(index.column(), checkState)
self.dataChanged.emit(
self.index(0, index.column(), index),
self.index(row, index.column(), index)
)
else:
parentIndex = self.parent(index)
parentItem = parentIndex.internalPointer()
diff = False
for row in range(0, self.rowCount(parentIndex)):
childItem = parentItem.child(row)
if childItem.checkState(index.column()) != checkState:
diff = True
break
if diff:
parentItem.setCheckState(index.column(), Qt.PartiallyChecked)
else:
parentItem.setCheckState(index.column(), checkState)
self.dataChanged.emit(
parentIndex,
parentIndex
)
def columnCount(self, parent):
if parent.isValid():
return parent.internalPointer().columnCount()
else:
return self.rootItem.columnCount()
def data(self, index, role):
if not index.isValid():
return None
if role not in [Qt.DisplayRole, Qt.CheckStateRole, Qt.DecorationRole, Qt.UserRole]:
return None
item = index.internalPointer()
return item.data(index.column(), role)
def flags(self, index):
if not index.isValid():
item = self.rootItem
else:
item = index.internalPointer()
return item.flags()
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.rootItem.data(section, Qt.DisplayRole)
return None
def index(self, row, column, parent):
if not self.hasIndex(row, column, parent):
return QModelIndex()
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QModelIndex()
def parent(self, index):
if not index.isValid():
return QModelIndex()
childItem = index.internalPointer()
parentItem = childItem.parent()
if parentItem == self.rootItem:
return QModelIndex()
return self.createIndex(parentItem.parent().indexOfChild(parentItem), index.column(), parentItem)
def rowCount(self, parent):
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
return parentItem.childCount()
def sort(self, column, order=Qt.AscendingOrder):
self.layoutAboutToBeChanged.emit()
if column == self.COLUMN_VISIBILITY:
role = Qt.CheckStateRole
else:
role = Qt.DisplayRole
if order == Qt.AscendingOrder:
# compareFunc = lambda a, b: True if cmp(a, b) < 0 else False
compareFunc = lambda a, b: a < b # need to check
else:
# compareFunc = lambda a, b: True if cmp(a, b) > 0 else False
compareFunc = lambda a, b: a >= b # need to check
for groupIndexI in range(0, self.rootItem.childCount()):
for groupIndexJ in range(0, groupIndexI):
groupItemI = self.rootItem.child(groupIndexI)
groupItemJ = self.rootItem.child(groupIndexJ)
if compareFunc(groupItemI.data(column, role), groupItemJ.data(column, role)):
self.rootItem.insertChild(groupIndexJ, self.rootItem.takeChild(groupIndexI))
break
self.layoutChanged.emit()
def checkAll(self):
for row in range(0, self.rootItem.childCount()):
groupItem = self.rootItem.child(row)
groupIndex = self.createIndex(row, self.COLUMN_VISIBILITY, groupItem)
self.setData(groupIndex, Qt.Checked, Qt.CheckStateRole)
def uncheckAll(self):
for row in range(0, self.rootItem.childCount()):
groupItem = self.rootItem.child(row)
groupIndex = self.createIndex(row, self.COLUMN_VISIBILITY, groupItem)
self.setData(groupIndex, Qt.Unchecked, Qt.CheckStateRole)
def saveSettings(self):
hideDSidList = []
for groupIndex in range(0, self.rootItem.childCount()):
groupItem = self.rootItem.child(groupIndex)
for dsIndex in range(0, groupItem.childCount()):
dsItem = groupItem.child(dsIndex)
if dsItem.checkState(self.COLUMN_VISIBILITY) == Qt.Unchecked:
hideDSidList.append(dsItem.data(self.COLUMN_GROUP_DS, Qt.UserRole).id)
PluginSettings.set_hide_ds_id_list(hideDSidList)
def isGroup(self, index):
childItem = index.internalPointer()
parentItem = childItem.parent()
if parentItem == self.rootItem:
return True
return False
PK "OLִZ ' quick_map_services/user_services_box.pyfrom __future__ import absolute_import
import os
import sys
import shutil
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QGroupBox, QListWidgetItem, QDialog, QMessageBox, QVBoxLayout, QTreeView, QHeaderView
from .data_sources_list import DataSourcesList, USER_DS_PATHS
from .ds_edit_dialog import DsEditDialog
from .data_sources_model import DSManagerModel
from .compat import get_file_dir
plugin_dir = get_file_dir(__file__)
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'user_services_box.ui'))
class UserServicesBox(QGroupBox, FORM_CLASS):
def __init__(self, parent=None):
"""Constructor."""
super(UserServicesBox, self).__init__(parent)
self.setupUi(self)
self.feel_list()
self.lstServices.currentItemChanged.connect(self.on_sel_changed)
self.lstServices.itemDoubleClicked.connect(self.on_edit)
self.btnEdit.clicked.connect(self.on_edit)
self.btnAdd.clicked.connect(self.on_add)
self.btnDelete.clicked.connect(self.on_delete)
self.btnCopy.clicked.connect(self.on_copy)
self.btnAdd.setIcon(QIcon(plugin_dir + '/icons/plus.svg'))
self.btnEdit.setIcon(QIcon(plugin_dir + '/icons/compose.svg'))
self.btnDelete.setIcon(QIcon(plugin_dir + '/icons/trash.svg'))
self.btnCopy.setIcon(QIcon(plugin_dir + '/icons/copy.svg'))
self.ds_model = DSManagerModel()
def feel_list(self):
self.lstServices.clear()
ds_list = DataSourcesList(USER_DS_PATHS)
for ds in ds_list.data_sources.values():
item = QListWidgetItem(ds.action.icon(), ds.action.text())
item.setData(Qt.UserRole, ds)
self.lstServices.addItem(item)
def on_sel_changed(self, curr, prev):
has_sel = curr is not None
self.btnEdit.setEnabled(has_sel)
self.btnDelete.setEnabled(has_sel)
def on_add(self):
edit_dialog = DsEditDialog()
edit_dialog.setWindowTitle(self.tr('Create service'))
if edit_dialog.exec_() == QDialog.Accepted:
self.feel_list()
self.ds_model.resetModel()
def on_edit(self):
item = self.lstServices.currentItem().data(Qt.UserRole)
edit_dialog = DsEditDialog()
edit_dialog.setWindowTitle(self.tr('Edit service'))
edit_dialog.set_ds_info(item)
if edit_dialog.exec_() == QDialog.Accepted:
self.feel_list()
self.ds_model.resetModel()
def on_delete(self):
res = QMessageBox.question(None,
self.tr('Delete service'),
self.tr('Delete selected service?'),
QMessageBox.Yes, QMessageBox.No)
if res == QMessageBox.Yes:
ds_info = self.lstServices.currentItem().data(Qt.UserRole)
dir_path = os.path.abspath(os.path.join(ds_info.file_path, os.path.pardir))
shutil.rmtree(dir_path, True)
self.feel_list()
self.ds_model.resetModel()
def on_copy(self):
self.ds_model.sort(DSManagerModel.COLUMN_GROUP_DS)
select_data_sources_dialog = QDialog(self)
select_data_sources_dialog.resize(400, 400)
select_data_sources_dialog.setWindowTitle(self.tr("Choose source service"))
layout = QVBoxLayout(select_data_sources_dialog)
select_data_sources_dialog.setLayout(layout)
list_view = QTreeView(self)
layout.addWidget(list_view)
list_view.setModel(self.ds_model)
#list_view.expandAll()
list_view.setColumnHidden(DSManagerModel.COLUMN_VISIBILITY, True)
list_view.setAlternatingRowColors(True)
if hasattr(list_view.header(), "setResizeMode"):
# Qt4
list_view.header().setResizeMode(DSManagerModel.COLUMN_GROUP_DS, QHeaderView.ResizeToContents)
else:
# Qt5
list_view.header().setSectionResizeMode(DSManagerModel.COLUMN_GROUP_DS, QHeaderView.ResizeToContents)
list_view.clicked.connect(
lambda index: select_data_sources_dialog.accept() \
if not self.ds_model.isGroup(index) and \
index.column() == DSManagerModel.COLUMN_GROUP_DS \
else None
)
if select_data_sources_dialog.exec_() == QDialog.Accepted:
data_source = self.ds_model.data(list_view.currentIndex(), Qt.UserRole)
data_source.id += "_copy"
edit_dialog = DsEditDialog()
edit_dialog.setWindowTitle(self.tr('Create service from existing'))
edit_dialog.fill_ds_info(data_source)
if edit_dialog.exec_() == QDialog.Accepted:
self.feel_list()
self.ds_model.resetModel()
PK "OLR R ' quick_map_services/custom_translator.py# -*- coding: utf-8 -*-
"""
/***************************************************************************
QuickMapServices
A QGIS plugin
Collection of internet map services
-------------------
begin : 2014-11-21
git sha : $Format:%H$
copyright : (C) 2014 by NextGIS
email : info@nextgis.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from __future__ import absolute_import
from qgis.PyQt.QtCore import QTranslator
from .singleton import singleton
@singleton
class CustomTranslator(QTranslator):
def __init__(self):
QTranslator.__init__(self)
self.__translates = {}
def append(self, text, translation):
if text and translation:
self.__translates[text] = translation
def clear_translations(self):
self.__translates.clear()
def translate(self, context, text, disambiguation, n=-1):
try:
if (isinstance(text, str) or isinstance(text, unicode)) and text in self.__translates:
return self.__translates[text]
return None
except:
return None
PK "OL<進c c quick_map_services/singleton.py# -*- coding: utf-8 -*-
"""
/***************************************************************************
QuickMapServices
A QGIS plugin
Collection of internet map services
-------------------
begin : 2014-11-21
git sha : $Format:%H$
copyright : (C) 2014 by NextGIS
email : info@nextgis.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from .compat2qgis import QGis
if QGis.QGIS_VERSION_INT >= 30000:
from qgis.PyQt.QtCore import QObject as QParentClass
else:
from qgis.PyQt.QtCore import pyqtWrapperType as QParentClass
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
class QSingleton(QParentClass):
def __init__(cls, name, bases, dict):
super(QSingleton, cls).__init__(cls, bases, dict)
cls._instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(QSingleton, cls).__call__(*args, **kwargs)
return cls._instance
PK "OLS< ' quick_map_services/about_dialog_base.ui
Dialog
0
0
432
326
About QuickMapServices
-
Qt::Horizontal
QDialogButtonBox::Close
-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;">
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Droid Sans'; font-size:16pt; font-weight:600;">QuickMapServices</span></p></body></html>
Qt::AlignCenter
-
0
0
TextLabel
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
0
false
Info
-
true
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;">
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"><br /></p></body></html>
Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
true
License
-
true
Third-party Components
-
true
-
TextLabel
Qt::AlignCenter
buttonBox
accepted()
Dialog
accept()
248
254
157
274
buttonBox
rejected()
Dialog
reject()
316
260
286
274
PK "OLv.4 # quick_map_services/plugin_locale.py# -*- coding: utf-8 -*-
"""
/***************************************************************************
QuickMapServices
A QGIS plugin
Collection of internet map services
-------------------
begin : 2014-11-21
git sha : $Format:%H$
copyright : (C) 2014 by NextGIS
email : info@nextgis.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from qgis.PyQt.QtCore import QSettings
class Locale(object):
@classmethod
def get_locale(cls):
return QSettings().value('locale/userLocale')[0:2]PK "OLl>5
5
quick_map_services/icon.pngPNG
IHDR szz sBIT|d pHYs t tfx tEXtSoftware www.inkscape.org< tEXtTitle GIS icon theme 0.2S tEXtAuthor Robert Szczepanek_V (tEXtDescription http://robert.szczepanek.pl/4 RtEXtCopyright CC Attribution-ShareAlike http://creativecommons.org/licenses/by-sa/3.0/^Z IDATXWkp~9eo/$lHHB.X&VkUNeTJ#SuNkN[]Tj[;EmmƪUD,D*@ &%M~]N@2P<ϙy{;K84~ n 7 X
@z>D0`g(
/+K <` BKsSQd#V"m69Xћ+N Ȁ? P
eMVۺs9mCz,Us-8!KV_9mC >NV |gm36ZܻD= GS{iSxO>?QR~י,֊F?DAxPg]Ѐ?~ݭ
É=hpDqIa<7y7G8K:71
>^<蝾zBҊ ^PgNmUNMaWVԖںLe*H͂i\rG\߲/'-{QrT '^lMvPGmٰn 7;c;kĮ䏿z'^|Cn6*s{T%ӲlR,t;y;%$
ࡩ+ =sՒUJ%[P
*UM;y}*DeIXNc4-PaM.'3U%6d%LHewD(O%w"2|ٲʯܱttP|l%2EUF
IURb[*t0Jr>Fʗ=V_ Ev kZl#{.ھs^z^^PkۛdY&Ncx N[?a>]25`l<海O{?<^a 7S MKӒ=͖qj)rMUuf:|01Th&3ЬNcÂl$Y)ˊ,&+nә|@3H.0j"]bTbMfHџ!>?hjbdY+ 6"vQt&)aΩdh&!0Q"1
S )Pb2Źibip-pDre' ID)JT,K@ f/?X-! ' Ep>aCm[qͻ'sB'Aə/,CVtx-b DGG瑵@ɋ^g3/![0c=fX vg\-aܭY5 pf||̜_wE h^.]EPgk Yr#Lj> %!mq}WwyfIH[xyEj1& Tg
ˌL \]i94
N>F l>Tx8=LR2JbGS WM'ɂ,88!8r[LVBJLM#^4D |0[uZ4
^QFJȴWIMpz&,!0!.IҰk6U~q;NNDK*D)vҲa\kx)d˟w͝]f lc$F(/~X]r_O۽KEZ&kr{=zpD 1㫚VvߞLBp'z/y횥-$jH7}i^y%($zhnr*wn|snݰ n
|1aJDc]չk] /HU~aBmw*{^W\oO5
Rdas>Ӧ^e n |ų5/Ԗ_9 9*.U:V(|݉D"fcѶ7Rshz[#~I" ۷{B߶t.8iW` uj#X"%fd_4geO4ot z lR(g,3X&