FreeCAD

Форк
0
/
install_to_toolbar.py 
295 строк · 12.6 Кб
1
# SPDX-License-Identifier: LGPL-2.1-or-later
2
# ***************************************************************************
3
# *                                                                         *
4
# *   Copyright (c) 2022-2024 The FreeCAD Project Association AISBL         *
5
# *                                                                         *
6
# *   This file is part of FreeCAD.                                         *
7
# *                                                                         *
8
# *   FreeCAD is free software: you can redistribute it and/or modify it    *
9
# *   under the terms of the GNU Lesser General Public License as           *
10
# *   published by the Free Software Foundation, either version 2.1 of the  *
11
# *   License, or (at your option) any later version.                       *
12
# *                                                                         *
13
# *   FreeCAD is distributed in the hope that it will be useful, but        *
14
# *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
15
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
16
# *   Lesser General Public License for more details.                       *
17
# *                                                                         *
18
# *   You should have received a copy of the GNU Lesser General Public      *
19
# *   License along with FreeCAD. If not, see                               *
20
# *   <https://www.gnu.org/licenses/>.                                      *
21
# *                                                                         *
22
# ***************************************************************************
23

24
""" A collection of functions to handle installing a macro icon to the toolbar. """
25

26
import os
27

28
import FreeCAD
29
import FreeCADGui
30
from PySide import QtCore, QtWidgets
31
import Addon
32

33
translate = FreeCAD.Qt.translate
34

35

36
def ask_to_install_toolbar_button(repo: Addon) -> None:
37
    """Presents a dialog to the user asking if they want to install a toolbar button for
38
    a particular macro, and walks through that process if they agree to do so."""
39
    pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
40
    do_not_show_dialog = pref.GetBool("dontShowAddMacroButtonDialog", False)
41
    button_exists = check_for_button(repo)
42
    if not do_not_show_dialog and not button_exists:
43
        add_toolbar_button_dialog = FreeCADGui.PySideUic.loadUi(
44
            os.path.join(os.path.dirname(__file__), "add_toolbar_button_dialog.ui")
45
        )
46
        add_toolbar_button_dialog.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint, True)
47
        add_toolbar_button_dialog.buttonYes.clicked.connect(lambda: install_toolbar_button(repo))
48
        add_toolbar_button_dialog.buttonNever.clicked.connect(
49
            lambda: pref.SetBool("dontShowAddMacroButtonDialog", True)
50
        )
51
        add_toolbar_button_dialog.exec()
52

53

54
def check_for_button(repo: Addon) -> bool:
55
    """Returns True if a button already exists for this macro, or False if not."""
56
    command = FreeCADGui.Command.findCustomCommand(repo.macro.filename)
57
    if not command:
58
        return False
59
    custom_toolbars = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar")
60
    toolbar_groups = custom_toolbars.GetGroups()
61
    for group in toolbar_groups:
62
        toolbar = custom_toolbars.GetGroup(group)
63
        if toolbar.GetString(command, "*") != "*":
64
            return True
65
    return False
66

67

68
def ask_for_toolbar(repo: Addon, custom_toolbars) -> object:
69
    """Determine what toolbar to add the icon to. The first time it is called it prompts the
70
    user to select or create a toolbar. After that, the prompt is optional and can be configured
71
    via a preference. Returns the pref group for the new toolbar."""
72
    pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
73

74
    # In this one spot, default True: if this is the first time we got to
75
    # this chunk of code, we are always going to ask.
76
    ask = pref.GetBool("alwaysAskForToolbar", True)
77

78
    if ask:
79
        select_toolbar_dialog = FreeCADGui.PySideUic.loadUi(
80
            os.path.join(os.path.dirname(__file__), "select_toolbar_dialog.ui")
81
        )
82
        select_toolbar_dialog.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint, True)
83

84
        select_toolbar_dialog.comboBox.clear()
85

86
        for group in custom_toolbars:
87
            ref = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar/" + group)
88
            name = ref.GetString("Name", "")
89
            if name:
90
                select_toolbar_dialog.comboBox.addItem(name)
91
            else:
92
                FreeCAD.Console.PrintWarning(
93
                    f"Custom toolbar {group} does not have a Name element\n"
94
                )
95
        new_menubar_option_text = translate("AddonsInstaller", "Create new toolbar")
96
        select_toolbar_dialog.comboBox.addItem(new_menubar_option_text)
97

98
        result = select_toolbar_dialog.exec()
99
        if result == QtWidgets.QDialog.Accepted:
100
            selection = select_toolbar_dialog.comboBox.currentText()
101
            if select_toolbar_dialog.checkBox.checkState() == QtCore.Qt.Unchecked:
102
                pref.SetBool("alwaysAskForToolbar", False)
103
            else:
104
                pref.SetBool("alwaysAskForToolbar", True)
105
            if selection == new_menubar_option_text:
106
                return create_new_custom_toolbar()
107
            return get_toolbar_with_name(selection)
108
        return None
109

110
    # If none of the above code returned...
111
    custom_toolbar_name = pref.GetString("CustomToolbarName", "Auto-Created Macro Toolbar")
112
    toolbar = get_toolbar_with_name(custom_toolbar_name)
113
    if not toolbar:
114
        # They told us not to ask, but then the toolbar got deleted... ask anyway!
115
        ask = pref.RemBool("alwaysAskForToolbar")
116
        return ask_for_toolbar(repo, custom_toolbars)
117
    return toolbar
118

119

120
def get_toolbar_with_name(name: str) -> object:
121
    """Try to find a toolbar with a given name. Returns the preference group for the toolbar
122
    if found, or None if it does not exist."""
123
    top_group = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar")
124
    custom_toolbars = top_group.GetGroups()
125
    for toolbar in custom_toolbars:
126
        group = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar/" + toolbar)
127
        group_name = group.GetString("Name", "")
128
        if group_name == name:
129
            return group
130
    return None
131

132

133
def create_new_custom_toolbar() -> object:
134
    """Create a new custom toolbar and returns its preference group."""
135

136
    # We need two names: the name of the auto-created toolbar, as it will be displayed to the
137
    # user in various menus, and the underlying name of the toolbar group. Both must be
138
    # unique.
139

140
    # First, the displayed name
141
    custom_toolbar_name = "Auto-Created Macro Toolbar"
142
    top_group = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar")
143
    custom_toolbars = top_group.GetGroups()
144
    name_taken = check_for_toolbar(custom_toolbar_name)
145
    if name_taken:
146
        i = 2  # Don't use (1), start at (2)
147
        while True:
148
            test_name = custom_toolbar_name + f" ({i})"
149
            if not check_for_toolbar(test_name):
150
                custom_toolbar_name = test_name
151
            i = i + 1
152

153
    # Second, the toolbar preference group name
154
    i = 1
155
    while True:
156
        new_group_name = "Custom_" + str(i)
157
        if new_group_name not in custom_toolbars:
158
            break
159
        i = i + 1
160

161
    custom_toolbar = FreeCAD.ParamGet(
162
        "User parameter:BaseApp/Workbench/Global/Toolbar/" + new_group_name
163
    )
164
    custom_toolbar.SetString("Name", custom_toolbar_name)
165
    custom_toolbar.SetBool("Active", True)
166
    return custom_toolbar
167

168

169
def check_for_toolbar(toolbar_name: str) -> bool:
170
    """Returns True if the toolbar exists, otherwise False"""
171
    return get_toolbar_with_name(toolbar_name) is not None
172

173

174
def install_toolbar_button(repo: Addon) -> None:
175
    """If the user has requested a toolbar button be installed, this function is called
176
    to continue the process and request any additional required information."""
177
    pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
178
    custom_toolbar_name = pref.GetString("CustomToolbarName", "Auto-Created Macro Toolbar")
179

180
    # Default to false here: if the variable hasn't been set, we don't assume
181
    # that we have to ask, because the simplest is to just create a new toolbar
182
    # and never ask at all.
183
    ask = pref.GetBool("alwaysAskForToolbar", False)
184

185
    # See if there is already a custom toolbar for macros:
186
    top_group = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar")
187
    custom_toolbars = top_group.GetGroups()
188
    if custom_toolbars:
189
        # If there are already custom toolbars, see if one of them is the one we used last time
190
        found_toolbar = False
191
        for toolbar_name in custom_toolbars:
192
            test_toolbar = FreeCAD.ParamGet(
193
                "User parameter:BaseApp/Workbench/Global/Toolbar/" + toolbar_name
194
            )
195
            name = test_toolbar.GetString("Name", "")
196
            if name == custom_toolbar_name:
197
                custom_toolbar = test_toolbar
198
                found_toolbar = True
199
                break
200
        if ask or not found_toolbar:
201
            # We have to ask the user what to do...
202
            custom_toolbar = ask_for_toolbar(repo, custom_toolbars)
203
            if custom_toolbar:
204
                custom_toolbar_name = custom_toolbar.GetString("Name")
205
                pref.SetString("CustomToolbarName", custom_toolbar_name)
206
    else:
207
        # Create a custom toolbar
208
        custom_toolbar = FreeCAD.ParamGet(
209
            "User parameter:BaseApp/Workbench/Global/Toolbar/Custom_1"
210
        )
211
        custom_toolbar.SetString("Name", custom_toolbar_name)
212
        custom_toolbar.SetBool("Active", True)
213

214
    if custom_toolbar:
215
        install_macro_to_toolbar(repo, custom_toolbar)
216
    else:
217
        FreeCAD.Console.PrintMessage("In the end, no custom toolbar was set, bailing out\n")
218

219

220
def find_installed_icon(repo: Addon) -> str:
221
    """The icon the macro specifies is usually not the actual installed icon, but rather a cached
222
    copy. This function looks for a file with the same name located in the macro installation
223
    path."""
224
    macro_repo_dir = FreeCAD.getUserMacroDir(True)
225
    if repo.macro.icon:
226
        basename = os.path.basename(repo.macro.icon)
227
        # Simple case first: the file is just in the macro directory...
228
        if os.path.isfile(os.path.join(macro_repo_dir, basename)):
229
            return os.path.join(macro_repo_dir, basename)
230
        # More complex: search for it
231
        for root, dirs, files in os.walk(macro_repo_dir):
232
            for name in files:
233
                if name == basename:
234
                    return os.path.join(root, name)
235
        return ""
236
    elif repo.macro.xpm:
237
        return os.path.normpath(os.path.join(macro_repo_dir, repo.macro.name + "_icon.xpm"))
238
    else:
239
        return ""
240

241

242
def install_macro_to_toolbar(repo: Addon, toolbar: object) -> None:
243
    """Adds an icon for the given macro to the given toolbar."""
244
    menuText = repo.display_name
245
    tooltipText = f"<b>{repo.display_name}</b>"
246
    if repo.macro.comment:
247
        tooltipText += f"<br/><p>{repo.macro.comment}</p>"
248
        whatsThisText = repo.macro.comment
249
    else:
250
        whatsThisText = translate(
251
            "AddonsInstaller", "A macro installed with the FreeCAD Addon Manager"
252
        )
253
    statustipText = (
254
        translate("AddonsInstaller", "Run", "Indicates a macro that can be 'run'")
255
        + " "
256
        + repo.display_name
257
    )
258
    pixmapText = find_installed_icon(repo)
259

260
    # Add this command to that toolbar
261
    command_name = FreeCADGui.Command.createCustomCommand(
262
        repo.macro.filename,
263
        menuText,
264
        tooltipText,
265
        whatsThisText,
266
        statustipText,
267
        pixmapText,
268
    )
269
    toolbar.SetString(command_name, "FreeCAD")
270

271
    # Force the toolbars to be recreated
272
    wb = FreeCADGui.activeWorkbench()
273
    wb.reloadActive()
274

275

276
def remove_custom_toolbar_button(repo: Addon) -> None:
277
    """If this repo contains a macro, look through the custom commands and
278
    see if one is set up for this macro. If so, remove it, including any
279
    toolbar entries."""
280

281
    command = FreeCADGui.Command.findCustomCommand(repo.macro.filename)
282
    if not command:
283
        return
284
    custom_toolbars = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar")
285
    toolbar_groups = custom_toolbars.GetGroups()
286
    for group in toolbar_groups:
287
        toolbar = custom_toolbars.GetGroup(group)
288
        if toolbar.GetString(command, "*") != "*":
289
            toolbar.RemString(command)
290

291
    FreeCADGui.Command.removeCustomCommand(command)
292

293
    # Force the toolbars to be recreated
294
    wb = FreeCADGui.activeWorkbench()
295
    wb.reloadActive()
296

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.