db_tree.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. """
  2. /***************************************************************************
  3. Name : DB Manager
  4. Description : Database manager plugin for QGIS
  5. Date : May 23, 2011
  6. copyright : (C) 2011 by Giuseppe Sucameli
  7. email : brush.tyler@gmail.com
  8. ***************************************************************************/
  9. /***************************************************************************
  10. * *
  11. * This program is free software; you can redistribute it and/or modify *
  12. * it under the terms of the GNU General Public License as published by *
  13. * the Free Software Foundation; either version 2 of the License, or *
  14. * (at your option) any later version. *
  15. * *
  16. ***************************************************************************/
  17. """
  18. from qgis.PyQt.QtCore import pyqtSignal, QCoreApplication
  19. from qgis.PyQt.QtWidgets import QWidget, QTreeView, QMenu, QLabel
  20. from qgis.core import Qgis, QgsProject, QgsMessageLog
  21. from qgis.gui import QgsMessageBar, QgsMessageBarItem
  22. from .db_model import DBModel, PluginItem
  23. from .db_plugins.plugin import DBPlugin, Schema, Table
  24. from .db_plugins.vlayers.plugin import LTable
  25. class DBTree(QTreeView):
  26. selectedItemChanged = pyqtSignal(object)
  27. def __init__(self, mainWindow):
  28. QTreeView.__init__(self, mainWindow)
  29. self.mainWindow = mainWindow
  30. self.setModel(DBModel(self))
  31. self.setHeaderHidden(True)
  32. self.setEditTriggers(QTreeView.EditKeyPressed | QTreeView.SelectedClicked)
  33. self.setDragEnabled(True)
  34. self.setAcceptDrops(True)
  35. self.setDropIndicatorShown(True)
  36. self.doubleClicked.connect(self.addLayer)
  37. self.selectionModel().currentChanged.connect(self.currentItemChanged)
  38. self.expanded.connect(self.itemChanged)
  39. self.collapsed.connect(self.itemChanged)
  40. self.model().dataChanged.connect(self.modelDataChanged)
  41. self.model().notPopulated.connect(self.collapse)
  42. def refreshItem(self, item=None):
  43. if item is None:
  44. item = self.currentItem()
  45. if item is None:
  46. return
  47. self.model().refreshItem(item)
  48. def showSystemTables(self, show):
  49. pass
  50. def currentItem(self):
  51. indexes = self.selectedIndexes()
  52. if len(indexes) <= 0:
  53. return
  54. return self.model().getItem(indexes[0])
  55. def currentDatabase(self):
  56. item = self.currentItem()
  57. if item is None:
  58. return
  59. if isinstance(item, (DBPlugin, Schema, Table)):
  60. return item.database()
  61. return None
  62. def currentSchema(self):
  63. item = self.currentItem()
  64. if item is None:
  65. return
  66. if isinstance(item, (Schema, Table)):
  67. return item.schema()
  68. return None
  69. def currentTable(self):
  70. item = self.currentItem()
  71. if isinstance(item, Table):
  72. return item
  73. return None
  74. def newConnection(self):
  75. index = self.currentIndex()
  76. if not index.isValid() or not isinstance(index.internalPointer(), PluginItem):
  77. return
  78. item = self.currentItem()
  79. self.mainWindow.invokeCallback(item.addConnectionActionSlot, index)
  80. def itemChanged(self, index):
  81. self.setCurrentIndex(index)
  82. self.selectedItemChanged.emit(self.currentItem())
  83. def modelDataChanged(self, indexFrom, indexTo):
  84. self.itemChanged(indexTo)
  85. def currentItemChanged(self, current, previous):
  86. self.itemChanged(current)
  87. def contextMenuEvent(self, ev):
  88. index = self.indexAt(ev.pos())
  89. if not index.isValid():
  90. return
  91. if index != self.currentIndex():
  92. self.itemChanged(index)
  93. item = self.currentItem()
  94. menu = QMenu(self)
  95. if isinstance(item, (Table, Schema)) and not isinstance(item, LTable):
  96. menu.addAction(QCoreApplication.translate("DBTree", "Rename…"), self.rename)
  97. menu.addAction(QCoreApplication.translate("DBTree", "Delete…"), self.delete)
  98. if isinstance(item, Table) and item.canBeAddedToCanvas():
  99. menu.addSeparator()
  100. menu.addAction(self.tr("Add to Canvas"), self.addLayer)
  101. item.addExtraContextMenuEntries(menu)
  102. elif isinstance(item, DBPlugin):
  103. if item.database() is not None:
  104. menu.addAction(self.tr("Re-connect"), self.reconnect)
  105. menu.addAction(self.tr("Remove"), self.delete)
  106. elif not index.parent().isValid() and item.typeName() in ("spatialite", "gpkg"):
  107. menu.addAction(QCoreApplication.translate("DBTree", "New Connection…"), self.newConnection)
  108. if not menu.isEmpty():
  109. menu.exec_(ev.globalPos())
  110. menu.deleteLater()
  111. def rename(self):
  112. item = self.currentItem()
  113. if isinstance(item, (Table, Schema)):
  114. self.edit(self.currentIndex())
  115. def delete(self):
  116. item = self.currentItem()
  117. if isinstance(item, (Table, Schema)):
  118. self.mainWindow.invokeCallback(item.database().deleteActionSlot)
  119. elif isinstance(item, DBPlugin):
  120. self.mainWindow.invokeCallback(item.removeActionSlot)
  121. def addLayer(self):
  122. table = self.currentTable()
  123. if table is not None:
  124. layer = table.toMapLayer(table.geometryType())
  125. layers = QgsProject.instance().addMapLayers([layer])
  126. if len(layers) != 1:
  127. QgsMessageLog.logMessage(
  128. self.tr("%1 is an invalid layer - not loaded").replace("%1", layer.publicSource()))
  129. msgLabel = QLabel(self.tr(
  130. "%1 is an invalid layer and cannot be loaded. Please check the <a href=\"#messageLog\">message log</a> for further info.").replace(
  131. "%1", layer.publicSource()), self.mainWindow.infoBar)
  132. msgLabel.setWordWrap(True)
  133. msgLabel.linkActivated.connect(self.mainWindow.iface.mainWindow().findChild(QWidget, "MessageLog").show)
  134. msgLabel.linkActivated.connect(self.mainWindow.iface.mainWindow().raise_)
  135. self.mainWindow.infoBar.pushItem(QgsMessageBarItem(msgLabel, Qgis.Warning))
  136. def reconnect(self):
  137. db = self.currentDatabase()
  138. if db is not None:
  139. self.mainWindow.invokeCallback(db.reconnectActionSlot)