File size: 8,435 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# SPDX-License-Identifier: LGPL-2.1-or-later

# ***************************************************************************
# *   Copyright (c) 2017 sliptonic <shopinthewoods@gmail.com>               *
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU Lesser General Public License (LGPL)    *
# *   as published by the Free Software Foundation; either version 2 of     *
# *   the License, or (at your option) any later version.                   *
# *   for detail see the LICENCE text file.                                 *
# *                                                                         *
# *   This program is distributed in the hope that it will be useful,       *
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
# *   GNU Library General Public License for more details.                  *
# *                                                                         *
# *   You should have received a copy of the GNU Library General Public     *
# *   License along with this program; if not, write to the Free Software   *
# *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
# *   USA                                                                   *
# *                                                                         *
# ***************************************************************************

import FreeCAD
import FreeCADGui
import Path
import Path.Op.Gui.Base as PathOpGui
import PathGui

from PySide import QtCore, QtGui

__title__ = "Base for Circular Hole based operations' UI"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecad.org"
__doc__ = "Implementation of circular hole specific base geometry page controller."

LOGLEVEL = False

if LOGLEVEL:
    Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
    Path.Log.trackModule(Path.Log.thisModule())
else:
    Path.Log.setLevel(Path.Log.Level.NOTICE, Path.Log.thisModule())


class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
    """Controller class to be used for the BaseGeomtery page.
    Circular holes don't just display the feature, they also add a column
    displaying the radius the feature describes. This page provides that
    UI and functionality for all circular hole based operations."""

    DataFeatureName = QtCore.Qt.ItemDataRole.UserRole
    DataObject = QtCore.Qt.ItemDataRole.UserRole + 1
    DataObjectSub = QtCore.Qt.ItemDataRole.UserRole + 2

    InitBase = False

    def getForm(self):
        """getForm() ... load and return page"""
        return FreeCADGui.PySideUic.loadUi(":/panels/PageBaseHoleGeometryEdit.ui")

    def initPage(self, obj):
        self.updating = False

    def setFields(self, obj):
        """setFields(obj) ... fill form with values from obj"""
        Path.Log.track()
        self.form.baseList.blockSignals(True)
        self.form.baseList.clearContents()
        self.form.baseList.setRowCount(0)
        for base, subs in obj.Base:
            for sub in subs:
                self.form.baseList.insertRow(self.form.baseList.rowCount())

                item = QtGui.QTableWidgetItem("%s.%s" % (base.Label, sub))
                item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
                if obj.Proxy.isHoleEnabled(obj, base, sub):
                    item.setCheckState(QtCore.Qt.Checked)
                else:
                    item.setCheckState(QtCore.Qt.Unchecked)
                name = "%s.%s" % (base.Name, sub)
                item.setData(self.DataFeatureName, name)
                item.setData(self.DataObject, base)
                item.setData(self.DataObjectSub, sub)
                self.form.baseList.setItem(self.form.baseList.rowCount() - 1, 0, item)

                dia = obj.Proxy.holeDiameter(obj, base, sub)
                item = QtGui.QTableWidgetItem()
                item.setData(QtCore.Qt.DisplayRole, float(dia))
                item.setTextAlignment(QtCore.Qt.AlignHCenter)
                self.form.baseList.setItem(self.form.baseList.rowCount() - 1, 1, item)

        self.form.baseList.resizeColumnToContents(0)
        self.form.baseList.blockSignals(False)
        self.form.baseList.setSortingEnabled(True)
        self.itemActivated()

    def itemActivated(self):
        """itemActivated() ... callback when item in table is selected"""
        Path.Log.track()
        if self.form.baseList.selectedItems():
            self.form.deleteBase.setEnabled(True)
            FreeCADGui.Selection.clearSelection()
            activatedRows = []
            for item in self.form.baseList.selectedItems():
                row = item.row()
                if not row in activatedRows:
                    activatedRows.append(row)
                    obj = item.data(self.DataObject)
                    sub = str(item.data(self.DataObjectSub))
                    Path.Log.debug("itemActivated() -> %s.%s" % (obj.Label, sub))
                    if sub:
                        FreeCADGui.Selection.addSelection(obj, sub)
                    else:
                        FreeCADGui.Selection.addSelection(obj)
        else:
            self.form.deleteBase.setEnabled(False)

    def deleteBase(self):
        """deleteBase() ... callback for push button"""
        Path.Log.track()
        selected = [self.form.baseList.row(item) for item in self.form.baseList.selectedItems()]
        self.form.baseList.blockSignals(True)
        for row in sorted(list(set(selected)), key=lambda row: -row):
            self.form.baseList.removeRow(row)
        self.updateBase()
        self.form.baseList.resizeColumnToContents(0)
        self.form.baseList.blockSignals(False)
        # self.obj.Proxy.execute(self.obj)
        FreeCAD.ActiveDocument.recompute()
        self.setFields(self.obj)

    def updateBase(self):
        """updateBase() ... helper function to transfer current table to obj"""
        Path.Log.track()
        newlist = []
        for i in range(self.form.baseList.rowCount()):
            item = self.form.baseList.item(i, 0)
            obj = item.data(self.DataObject)
            sub = str(item.data(self.DataObjectSub))
            base = (obj, sub)
            Path.Log.debug("keeping (%s.%s)" % (obj.Label, sub))
            newlist.append(base)
        Path.Log.debug("obj.Base=%s newlist=%s" % (self.obj.Base, newlist))
        self.updating = True
        self.obj.Base = newlist
        self.updating = False

    def checkedChanged(self):
        """checkeChanged() ... callback when checked status of a base feature changed"""
        Path.Log.track()
        disabled = []
        for i in range(0, self.form.baseList.rowCount()):
            item = self.form.baseList.item(i, 0)
            if item.checkState() != QtCore.Qt.Checked:
                disabled.append(item.data(self.DataFeatureName))
        self.obj.Disabled = disabled
        FreeCAD.ActiveDocument.recompute()

    def registerSignalHandlers(self, obj):
        """registerSignalHandlers(obj) ... setup signal handlers"""
        self.form.baseList.itemSelectionChanged.connect(self.itemActivated)
        self.form.addBase.clicked.connect(self.addBase)
        self.form.deleteBase.clicked.connect(self.deleteBase)
        self.form.resetBase.clicked.connect(self.resetBase)
        self.form.baseList.itemChanged.connect(self.checkedChanged)

    def resetBase(self):
        """resetBase() ... push button callback"""
        self.obj.Base = []
        self.obj.Disabled = []
        self.obj.Proxy.findAllHoles(self.obj)

        self.obj.Proxy.execute(self.obj)
        FreeCAD.ActiveDocument.recompute()

    def updateData(self, obj, prop):
        """updateData(obj, prop) ... callback whenever a property of the model changed"""
        if not self.updating and prop in ["Base", "Disabled"]:
            self.setFields(obj)


class TaskPanelOpPage(PathOpGui.TaskPanelPage):
    """Base class for circular hole based operation's page controller."""

    def taskPanelBaseGeometryPage(self, obj, features):
        """taskPanelBaseGeometryPage(obj, features) ... Return circular hole specific page controller for Base Geometry."""
        return TaskPanelHoleGeometryPage(obj, features)