GeneralAPPSetGroupUI.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. from PyQt5 import QtCore, QtWidgets, QtGui
  2. from PyQt5.QtCore import QSettings
  3. from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, RadioSet, OptionalInputSection, FCSpinner, \
  4. FCEntry
  5. from flatcamGUI.preferences import settings
  6. from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
  7. import gettext
  8. import FlatCAMTranslation as fcTranslate
  9. import builtins
  10. fcTranslate.apply_language('strings')
  11. if '_' not in builtins.__dict__:
  12. _ = gettext.gettext
  13. settings = QSettings("Open Source", "FlatCAM")
  14. if settings.contains("machinist"):
  15. machinist_setting = settings.value('machinist', type=int)
  16. else:
  17. machinist_setting = 0
  18. class GeneralAPPSetGroupUI(OptionsGroupUI):
  19. def __init__(self, decimals=4, parent=None):
  20. super(GeneralAPPSetGroupUI, self).__init__(self, parent=parent)
  21. self.setTitle(str(_("App Settings")))
  22. self.decimals = decimals
  23. theme_settings = QtCore.QSettings("Open Source", "FlatCAM")
  24. if theme_settings.contains("theme"):
  25. theme = theme_settings.value('theme', type=str)
  26. else:
  27. theme = 'white'
  28. if theme == 'white':
  29. self.resource_loc = 'assets/resources'
  30. else:
  31. self.resource_loc = 'assets/resources'
  32. # Create a grid layout for the Application general settings
  33. grid0 = QtWidgets.QGridLayout()
  34. self.layout.addLayout(grid0)
  35. grid0.setColumnStretch(0, 0)
  36. grid0.setColumnStretch(1, 1)
  37. # GRID Settings
  38. self.grid_label = QtWidgets.QLabel('<b>%s</b>' % _('Grid Settings'))
  39. grid0.addWidget(self.grid_label, 0, 0, 1, 2)
  40. # Grid X Entry
  41. self.gridx_label = QtWidgets.QLabel('%s:' % _('X value'))
  42. self.gridx_label.setToolTip(
  43. _("This is the Grid snap value on X axis.")
  44. )
  45. self.gridx_entry = FCDoubleSpinner()
  46. self.gridx_entry.set_precision(self.decimals)
  47. self.gridx_entry.setSingleStep(0.1)
  48. grid0.addWidget(self.gridx_label, 1, 0)
  49. grid0.addWidget(self.gridx_entry, 1, 1)
  50. # Grid Y Entry
  51. self.gridy_label = QtWidgets.QLabel('%s:' % _('Y value'))
  52. self.gridy_label.setToolTip(
  53. _("This is the Grid snap value on Y axis.")
  54. )
  55. self.gridy_entry = FCDoubleSpinner()
  56. self.gridy_entry.set_precision(self.decimals)
  57. self.gridy_entry.setSingleStep(0.1)
  58. grid0.addWidget(self.gridy_label, 2, 0)
  59. grid0.addWidget(self.gridy_entry, 2, 1)
  60. # Snap Max Entry
  61. self.snap_max_label = QtWidgets.QLabel('%s:' % _('Snap Max'))
  62. self.snap_max_label.setToolTip(_("Max. magnet distance"))
  63. self.snap_max_dist_entry = FCDoubleSpinner()
  64. self.snap_max_dist_entry.set_precision(self.decimals)
  65. self.snap_max_dist_entry.setSingleStep(0.1)
  66. grid0.addWidget(self.snap_max_label, 3, 0)
  67. grid0.addWidget(self.snap_max_dist_entry, 3, 1)
  68. separator_line = QtWidgets.QFrame()
  69. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  70. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  71. grid0.addWidget(separator_line, 4, 0, 1, 2)
  72. # Workspace
  73. self.workspace_label = QtWidgets.QLabel('<b>%s</b>' % _('Workspace Settings'))
  74. grid0.addWidget(self.workspace_label, 5, 0, 1, 2)
  75. self.workspace_cb = FCCheckBox('%s' % _('Active'))
  76. self.workspace_cb.setToolTip(
  77. _("Draw a delimiting rectangle on canvas.\n"
  78. "The purpose is to illustrate the limits for our work.")
  79. )
  80. grid0.addWidget(self.workspace_cb, 6, 0, 1, 2)
  81. self.workspace_type_lbl = QtWidgets.QLabel('%s:' % _('Size'))
  82. self.workspace_type_lbl.setToolTip(
  83. _("Select the type of rectangle to be used on canvas,\n"
  84. "as valid workspace.")
  85. )
  86. self.wk_cb = FCComboBox()
  87. grid0.addWidget(self.workspace_type_lbl, 7, 0)
  88. grid0.addWidget(self.wk_cb, 7, 1)
  89. self.pagesize = {}
  90. self.pagesize.update(
  91. {
  92. 'A0': (841, 1189),
  93. 'A1': (594, 841),
  94. 'A2': (420, 594),
  95. 'A3': (297, 420),
  96. 'A4': (210, 297),
  97. 'A5': (148, 210),
  98. 'A6': (105, 148),
  99. 'A7': (74, 105),
  100. 'A8': (52, 74),
  101. 'A9': (37, 52),
  102. 'A10': (26, 37),
  103. 'B0': (1000, 1414),
  104. 'B1': (707, 1000),
  105. 'B2': (500, 707),
  106. 'B3': (353, 500),
  107. 'B4': (250, 353),
  108. 'B5': (176, 250),
  109. 'B6': (125, 176),
  110. 'B7': (88, 125),
  111. 'B8': (62, 88),
  112. 'B9': (44, 62),
  113. 'B10': (31, 44),
  114. 'C0': (917, 1297),
  115. 'C1': (648, 917),
  116. 'C2': (458, 648),
  117. 'C3': (324, 458),
  118. 'C4': (229, 324),
  119. 'C5': (162, 229),
  120. 'C6': (114, 162),
  121. 'C7': (81, 114),
  122. 'C8': (57, 81),
  123. 'C9': (40, 57),
  124. 'C10': (28, 40),
  125. # American paper sizes
  126. 'LETTER': (8.5, 11),
  127. 'LEGAL': (8.5, 14),
  128. 'ELEVENSEVENTEEN': (11, 17),
  129. # From https://en.wikipedia.org/wiki/Paper_size
  130. 'JUNIOR_LEGAL': (5, 8),
  131. 'HALF_LETTER': (5.5, 8),
  132. 'GOV_LETTER': (8, 10.5),
  133. 'GOV_LEGAL': (8.5, 13),
  134. 'LEDGER': (17, 11),
  135. }
  136. )
  137. page_size_list = list(self.pagesize.keys())
  138. self.wk_cb.addItems(page_size_list)
  139. # Page orientation
  140. self.wk_orientation_label = QtWidgets.QLabel('%s:' % _("Orientation"))
  141. self.wk_orientation_label.setToolTip(_("Can be:\n"
  142. "- Portrait\n"
  143. "- Landscape"))
  144. self.wk_orientation_radio = RadioSet([{'label': _('Portrait'), 'value': 'p'},
  145. {'label': _('Landscape'), 'value': 'l'},
  146. ], stretch=False)
  147. self.wks = OptionalInputSection(self.workspace_cb,
  148. [
  149. self.workspace_type_lbl,
  150. self.wk_cb,
  151. self.wk_orientation_label,
  152. self.wk_orientation_radio
  153. ])
  154. grid0.addWidget(self.wk_orientation_label, 8, 0)
  155. grid0.addWidget(self.wk_orientation_radio, 8, 1)
  156. separator_line = QtWidgets.QFrame()
  157. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  158. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  159. grid0.addWidget(separator_line, 9, 0, 1, 2)
  160. # Font Size
  161. self.font_size_label = QtWidgets.QLabel('<b>%s</b>' % _('Font Size'))
  162. grid0.addWidget(self.font_size_label, 10, 0, 1, 2)
  163. # Notebook Font Size
  164. self.notebook_font_size_label = QtWidgets.QLabel('%s:' % _('Notebook'))
  165. self.notebook_font_size_label.setToolTip(
  166. _("This sets the font size for the elements found in the Notebook.\n"
  167. "The notebook is the collapsible area in the left side of the GUI,\n"
  168. "and include the Project, Selected and Tool tabs.")
  169. )
  170. self.notebook_font_size_spinner = FCSpinner()
  171. self.notebook_font_size_spinner.set_range(8, 40)
  172. self.notebook_font_size_spinner.setWrapping(True)
  173. qsettings = QSettings("Open Source", "FlatCAM")
  174. if qsettings.contains("notebook_font_size"):
  175. self.notebook_font_size_spinner.set_value(qsettings.value('notebook_font_size', type=int))
  176. else:
  177. self.notebook_font_size_spinner.set_value(12)
  178. grid0.addWidget(self.notebook_font_size_label, 11, 0)
  179. grid0.addWidget(self.notebook_font_size_spinner, 11, 1)
  180. # Axis Font Size
  181. self.axis_font_size_label = QtWidgets.QLabel('%s:' % _('Axis'))
  182. self.axis_font_size_label.setToolTip(
  183. _("This sets the font size for canvas axis.")
  184. )
  185. self.axis_font_size_spinner = FCSpinner()
  186. self.axis_font_size_spinner.set_range(0, 40)
  187. self.axis_font_size_spinner.setWrapping(True)
  188. qsettings = QSettings("Open Source", "FlatCAM")
  189. if qsettings.contains("axis_font_size"):
  190. self.axis_font_size_spinner.set_value(qsettings.value('axis_font_size', type=int))
  191. else:
  192. self.axis_font_size_spinner.set_value(8)
  193. grid0.addWidget(self.axis_font_size_label, 12, 0)
  194. grid0.addWidget(self.axis_font_size_spinner, 12, 1)
  195. # TextBox Font Size
  196. self.textbox_font_size_label = QtWidgets.QLabel('%s:' % _('Textbox'))
  197. self.textbox_font_size_label.setToolTip(
  198. _("This sets the font size for the Textbox GUI\n"
  199. "elements that are used in FlatCAM.")
  200. )
  201. self.textbox_font_size_spinner = FCSpinner()
  202. self.textbox_font_size_spinner.set_range(8, 40)
  203. self.textbox_font_size_spinner.setWrapping(True)
  204. qsettings = QSettings("Open Source", "FlatCAM")
  205. if qsettings.contains("textbox_font_size"):
  206. self.textbox_font_size_spinner.set_value(settings.value('textbox_font_size', type=int))
  207. else:
  208. self.textbox_font_size_spinner.set_value(10)
  209. grid0.addWidget(self.textbox_font_size_label, 13, 0)
  210. grid0.addWidget(self.textbox_font_size_spinner, 13, 1)
  211. separator_line = QtWidgets.QFrame()
  212. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  213. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  214. grid0.addWidget(separator_line, 14, 0, 1, 2)
  215. # -----------------------------------------------------------
  216. # -------------- MOUSE SETTINGS -----------------------------
  217. # -----------------------------------------------------------
  218. self.mouse_lbl = QtWidgets.QLabel('<b>%s</b>' % _('Mouse Settings'))
  219. grid0.addWidget(self.mouse_lbl, 21, 0, 1, 2)
  220. # Mouse Cursor Shape
  221. self.cursor_lbl = QtWidgets.QLabel('%s:' % _('Cursor Shape'))
  222. self.cursor_lbl.setToolTip(
  223. _("Choose a mouse cursor shape.\n"
  224. "- Small -> with a customizable size.\n"
  225. "- Big -> Infinite lines")
  226. )
  227. self.cursor_radio = RadioSet([
  228. {"label": _("Small"), "value": "small"},
  229. {"label": _("Big"), "value": "big"}
  230. ], orientation='horizontal', stretch=False)
  231. grid0.addWidget(self.cursor_lbl, 22, 0)
  232. grid0.addWidget(self.cursor_radio, 22, 1)
  233. # Mouse Cursor Size
  234. self.cursor_size_lbl = QtWidgets.QLabel('%s:' % _('Cursor Size'))
  235. self.cursor_size_lbl.setToolTip(
  236. _("Set the size of the mouse cursor, in pixels.")
  237. )
  238. self.cursor_size_entry = FCSpinner()
  239. self.cursor_size_entry.set_range(10, 70)
  240. self.cursor_size_entry.setWrapping(True)
  241. grid0.addWidget(self.cursor_size_lbl, 23, 0)
  242. grid0.addWidget(self.cursor_size_entry, 23, 1)
  243. # Cursor Width
  244. self.cursor_width_lbl = QtWidgets.QLabel('%s:' % _('Cursor Width'))
  245. self.cursor_width_lbl.setToolTip(
  246. _("Set the line width of the mouse cursor, in pixels.")
  247. )
  248. self.cursor_width_entry = FCSpinner()
  249. self.cursor_width_entry.set_range(1, 10)
  250. self.cursor_width_entry.setWrapping(True)
  251. grid0.addWidget(self.cursor_width_lbl, 24, 0)
  252. grid0.addWidget(self.cursor_width_entry, 24, 1)
  253. # Cursor Color Enable
  254. self.mouse_cursor_color_cb = FCCheckBox(label='%s' % _('Cursor Color'))
  255. self.mouse_cursor_color_cb.setToolTip(
  256. _("Check this box to color mouse cursor.")
  257. )
  258. grid0.addWidget(self.mouse_cursor_color_cb, 25, 0, 1, 2)
  259. # Cursor Color
  260. self.mouse_color_label = QtWidgets.QLabel('%s:' % _('Cursor Color'))
  261. self.mouse_color_label.setToolTip(
  262. _("Set the color of the mouse cursor.")
  263. )
  264. self.mouse_cursor_entry = FCEntry()
  265. self.mouse_cursor_button = QtWidgets.QPushButton()
  266. self.mouse_cursor_button.setFixedSize(15, 15)
  267. self.form_box_child_1 = QtWidgets.QHBoxLayout()
  268. self.form_box_child_1.addWidget(self.mouse_cursor_entry)
  269. self.form_box_child_1.addWidget(self.mouse_cursor_button)
  270. self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
  271. grid0.addWidget(self.mouse_color_label, 26, 0)
  272. grid0.addLayout(self.form_box_child_1, 26, 1)
  273. self.mois = OptionalInputSection(
  274. self.mouse_cursor_color_cb,
  275. [
  276. self.mouse_color_label,
  277. self.mouse_cursor_entry,
  278. self.mouse_cursor_button
  279. ]
  280. )
  281. # Select mouse pan button
  282. self.panbuttonlabel = QtWidgets.QLabel('%s:' % _('Pan Button'))
  283. self.panbuttonlabel.setToolTip(
  284. _("Select the mouse button to use for panning:\n"
  285. "- MMB --> Middle Mouse Button\n"
  286. "- RMB --> Right Mouse Button")
  287. )
  288. self.pan_button_radio = RadioSet([{'label': _('MMB'), 'value': '3'},
  289. {'label': _('RMB'), 'value': '2'}])
  290. grid0.addWidget(self.panbuttonlabel, 27, 0)
  291. grid0.addWidget(self.pan_button_radio, 27, 1)
  292. # Multiple Selection Modifier Key
  293. self.mselectlabel = QtWidgets.QLabel('%s:' % _('Multiple Selection'))
  294. self.mselectlabel.setToolTip(
  295. _("Select the key used for multiple selection.")
  296. )
  297. self.mselect_radio = RadioSet([{'label': _('CTRL'), 'value': 'Control'},
  298. {'label': _('SHIFT'), 'value': 'Shift'}])
  299. grid0.addWidget(self.mselectlabel, 28, 0)
  300. grid0.addWidget(self.mselect_radio, 28, 1)
  301. separator_line = QtWidgets.QFrame()
  302. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  303. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  304. grid0.addWidget(separator_line, 29, 0, 1, 2)
  305. # Delete confirmation
  306. self.delete_conf_cb = FCCheckBox(_('Delete object confirmation'))
  307. self.delete_conf_cb.setToolTip(
  308. _("When checked the application will ask for user confirmation\n"
  309. "whenever the Delete object(s) event is triggered, either by\n"
  310. "menu shortcut or key shortcut.")
  311. )
  312. grid0.addWidget(self.delete_conf_cb, 30, 0, 1, 2)
  313. # Open behavior
  314. self.open_style_cb = FCCheckBox('%s' % _('"Open" behavior'))
  315. self.open_style_cb.setToolTip(
  316. _("When checked the path for the last saved file is used when saving files,\n"
  317. "and the path for the last opened file is used when opening files.\n\n"
  318. "When unchecked the path for opening files is the one used last: either the\n"
  319. "path for saving files or the path for opening files.")
  320. )
  321. grid0.addWidget(self.open_style_cb, 31, 0, 1, 2)
  322. # Enable/Disable ToolTips globally
  323. self.toggle_tooltips_cb = FCCheckBox(label=_('Enable ToolTips'))
  324. self.toggle_tooltips_cb.setToolTip(
  325. _("Check this box if you want to have toolTips displayed\n"
  326. "when hovering with mouse over items throughout the App.")
  327. )
  328. grid0.addWidget(self.toggle_tooltips_cb, 32, 0, 1, 2)
  329. # Machinist settings that allow unsafe settings
  330. self.machinist_cb = FCCheckBox(_("Allow Machinist Unsafe Settings"))
  331. self.machinist_cb.setToolTip(
  332. _("If checked, some of the application settings will be allowed\n"
  333. "to have values that are usually unsafe to use.\n"
  334. "Like Z travel negative values or Z Cut positive values.\n"
  335. "It will applied at the next application start.\n"
  336. "<<WARNING>>: Don't change this unless you know what you are doing !!!")
  337. )
  338. grid0.addWidget(self.machinist_cb, 33, 0, 1, 2)
  339. # Bookmarks Limit in the Help Menu
  340. self.bm_limit_spinner = FCSpinner()
  341. self.bm_limit_spinner.set_range(0, 9999)
  342. self.bm_limit_label = QtWidgets.QLabel('%s:' % _('Bookmarks limit'))
  343. self.bm_limit_label.setToolTip(
  344. _("The maximum number of bookmarks that may be installed in the menu.\n"
  345. "The number of bookmarks in the bookmark manager may be greater\n"
  346. "but the menu will hold only so much.")
  347. )
  348. grid0.addWidget(self.bm_limit_label, 34, 0)
  349. grid0.addWidget(self.bm_limit_spinner, 34, 1)
  350. # Activity monitor icon
  351. self.activity_label = QtWidgets.QLabel('%s:' % _("Activity Icon"))
  352. self.activity_label.setToolTip(
  353. _("Select the GIF that show activity when FlatCAM is active.")
  354. )
  355. self.activity_combo = FCComboBox()
  356. self.activity_combo.addItems(['Ball black', 'Ball green', 'Arrow green', 'Eclipse green'])
  357. grid0.addWidget(self.activity_label, 35, 0)
  358. grid0.addWidget(self.activity_combo, 35, 1)
  359. self.layout.addStretch()
  360. self.mouse_cursor_color_cb.stateChanged.connect(self.on_mouse_cursor_color_enable)
  361. self.mouse_cursor_entry.editingFinished.connect(self.on_mouse_cursor_entry)
  362. self.mouse_cursor_button.clicked.connect(self.on_mouse_cursor_button)
  363. def on_mouse_cursor_color_enable(self, val):
  364. if val:
  365. self.app.cursor_color_3D = self.app.defaults["global_cursor_color"]
  366. else:
  367. theme_settings = QtCore.QSettings("Open Source", "FlatCAM")
  368. if theme_settings.contains("theme"):
  369. theme = theme_settings.value('theme', type=str)
  370. else:
  371. theme = 'white'
  372. if theme == 'white':
  373. self.app.cursor_color_3D = 'black'
  374. else:
  375. self.app.cursor_color_3D = 'gray'
  376. def on_mouse_cursor_entry(self):
  377. self.app.defaults['global_cursor_color'] = self.mouse_cursor_entry.get_value()
  378. self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_cursor_color']))
  379. self.app.cursor_color_3D = self.app.defaults["global_cursor_color"]
  380. def on_mouse_cursor_button(self):
  381. current_color = QtGui.QColor(self.app.defaults['global_cursor_color'])
  382. c_dialog = QtWidgets.QColorDialog()
  383. proj_color = c_dialog.getColor(initial=current_color)
  384. if proj_color.isValid() is False:
  385. return
  386. self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(proj_color.name()))
  387. new_val_sel = str(proj_color.name())
  388. self.mouse_cursor_entry.set_value(new_val_sel)
  389. self.app.defaults['global_cursor_color'] = new_val_sel
  390. self.app.cursor_color_3D = self.app.defaults["global_cursor_color"]