easyScripter.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import os
  2. import string
  3. import json
  4. from PyQt5 import QtCore
  5. from PyQt5.QtGui import *
  6. from PyQt5.QtCore import *
  7. from PyQt5.QtWidgets import QWidget
  8. from PyQt5.QtWidgets import (
  9. QWidget,
  10. QDockWidget,
  11. QTreeView,
  12. QStyle,
  13. QFileDialog,
  14. QLineEdit,
  15. QPushButton,
  16. QMessageBox,
  17. QHBoxLayout,
  18. QVBoxLayout,
  19. QAbstractItemView,
  20. QTextEdit,
  21. )
  22. script_folder = os.path.dirname(os.path.realpath(__file__))
  23. cfg_file = os.path.join(script_folder, "cfg.json")
  24. # default connection config
  25. default_config = {"path": r""}
  26. def read_cfg(data_file):
  27. if not os.path.isfile(data_file):
  28. with open(data_file, "w", encoding="utf-8") as d:
  29. json.dump(default_config, d, indent=4, ensure_ascii=False)
  30. data = default_config
  31. else:
  32. with open(data_file, "r") as fp:
  33. data = json.load(fp)
  34. path = data["path"]
  35. descriptions_path = os.path.join(path, "descriptions.json")
  36. if os.path.isfile(descriptions_path):
  37. with open(descriptions_path, "r") as fp:
  38. data_desc = json.load(fp)
  39. else:
  40. data_desc = {}
  41. return path, data_desc
  42. class Scripter(QDockWidget):
  43. closingPlugin = pyqtSignal()
  44. def __init__(self, wrapper):
  45. QDockWidget.__init__(self)
  46. self.wrapper = wrapper
  47. self.setWindowTitle("Scripter")
  48. self.ispnippets = Scripter_widget(self)
  49. self.setWidget(self.ispnippets)
  50. def closeEvent(self, event):
  51. self.closingPlugin.emit()
  52. event.accept()
  53. class Scripter_widget(QWidget):
  54. # Main widget tab tool
  55. def __init__(self, parent):
  56. super().__init__()
  57. self.initUI()
  58. def initUI(self):
  59. self.wpath, self.descriptions = read_cfg(cfg_file)
  60. self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
  61. self.upd_table = QPushButton()
  62. self.upd_table.setIcon(self.style().standardIcon(QStyle.SP_BrowserReload))
  63. self.upd_table.setToolTip("Update script list")
  64. self.upd_table.setMaximumWidth(35)
  65. self.path_line = QLineEdit()
  66. self.path_line.setPlaceholderText("Path to scripts...")
  67. self.path_line.setText(self.wpath)
  68. self.settings = QPushButton()
  69. self.settings.setIcon(self.style().standardIcon(QStyle.SP_DirIcon))
  70. self.settings.setToolTip("Path to scripts")
  71. self.settings.setMaximumWidth(35)
  72. self.dataView = QTreeView()
  73. self.dataView.setEditTriggers(QAbstractItemView.NoEditTriggers)
  74. self.dataView.setRootIsDecorated(False)
  75. self.dataView.doubleClicked.connect(self.on_double_click)
  76. self.model = QStandardItemModel(0, 1, self.dataView)
  77. self.model.setColumnCount(1)
  78. self.model.setHeaderData(0, Qt.Horizontal, "Script")
  79. self.description_area = QTextEdit()
  80. self.description_area.setReadOnly(True)
  81. self.dataView.setModel(self.model)
  82. self.btn_run = QPushButton()
  83. self.btn_run.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
  84. h_layout = QVBoxLayout(self)
  85. buttons_layout = QHBoxLayout(self)
  86. content_layout = QHBoxLayout(self)
  87. h_layout.addLayout(buttons_layout)
  88. h_layout.addLayout(content_layout)
  89. buttons_layout.addWidget(self.upd_table, 1)
  90. buttons_layout.addWidget(self.path_line, 1)
  91. buttons_layout.addWidget(self.settings, 1)
  92. buttons_layout.addStretch()
  93. content_layout.addWidget(self.dataView, 1)
  94. content_layout.addWidget(self.description_area, 1)
  95. self.description_area.setAlignment(Qt.AlignLeft | Qt.AlignTop)
  96. h_layout.addWidget(self.btn_run)
  97. self.upd_table.clicked.connect(lambda: self.get_actions(self.model))
  98. self.btn_run.clicked.connect(self.run_action)
  99. self.settings.clicked.connect(self.load_folder)
  100. self.dataView.clicked.connect(self.get_description)
  101. self.get_actions(self.model)
  102. def on_double_click(self, index):
  103. self.run_action()
  104. def get_description(self):
  105. selected_data = self.dataView.selectedIndexes()
  106. script_name = selected_data[0].data()
  107. self.description_area.setHtml(
  108. "<b>{}</b>".format(self.descriptions.get(script_name, ""))
  109. )
  110. def load_folder(self):
  111. result = QFileDialog.getExistingDirectoryUrl(self, "Select scripts folder")
  112. if result:
  113. selected_path = result.path().strip(string.punctuation)
  114. if selected_path:
  115. self.wpath = selected_path
  116. else:
  117. return
  118. with open(cfg_file, "w", encoding="utf-8") as d:
  119. json.dump({"path": self.wpath}, d, indent=4, ensure_ascii=False)
  120. self.path_line.setText(self.wpath)
  121. self.get_actions(self.model)
  122. self.description_area.setHtml("<b></b>")
  123. def get_actions(self, model):
  124. current_path = self.path_line.text()
  125. if not current_path:
  126. return
  127. if not os.path.isdir(current_path):
  128. self.warning_message("Wrong path")
  129. return
  130. self.wpath = current_path
  131. model.setRowCount(0)
  132. for afile in os.listdir(self.wpath):
  133. if os.path.isfile(os.path.join(self.wpath, afile)):
  134. if "." not in afile:
  135. continue
  136. action_name, action_type = os.path.splitext(afile)
  137. if action_type == ".py":
  138. model.insertRow(0)
  139. model.setData(model.index(0, 0), action_name)
  140. self.description_area.setHtml("<b></b>")
  141. print("-->", current_path)
  142. file_descriptions = os.path.join(current_path, "descriptions.json")
  143. if os.path.isfile(file_descriptions):
  144. with open(file_descriptions, "r") as fp:
  145. self.descriptions = json.load(fp)
  146. else:
  147. self.descriptions = {}
  148. with open(cfg_file, "w", encoding="utf-8") as d:
  149. json.dump({"path": self.wpath}, d, indent=4, ensure_ascii=False)
  150. def run_action(self):
  151. selected_data = self.dataView.selectedIndexes()
  152. if selected_data:
  153. script_name = selected_data[0].data()
  154. self.run_script(script_name)
  155. else:
  156. self.warning_message("Select script then press ▶︎ button")
  157. def run_script(self, script):
  158. script_path = os.path.join(self.wpath, "{}.py".format(script))
  159. try:
  160. self.result = exec(
  161. open("{}".format(script_path).encode("utf-8")).read(),
  162. {"wrapper": self, "project_folder": self.wpath, "script_name": script},
  163. )
  164. except Exception as e:
  165. print(e)
  166. self.warning_message("Error in script\nSee Python console for details")
  167. def warning_message(self, err_text):
  168. msg = QMessageBox()
  169. msg.warning(self, "Warning", err_text)