Help With Dialog Buttons In Macro.

Post here for help on using FreeCAD's graphical user interface (GUI).
Forum rules
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help

Also, be nice to others! Read the FreeCAD code of conduct!
User avatar
quick61
Posts: 3793
Joined: Sat Aug 24, 2013 2:49 am
Location: u.S.A.

Help With Dialog Buttons In Macro.

Postby quick61 » Thu Sep 05, 2013 3:00 am

I have been working on a GUI front end for a script that was done by shoogen. Very nice little script for scaling an airfoil .dat file. After a couple of days now, I have found enough info to get the GUI to look the way i want and to open/display from the macro. This is the point where everything gets real confusing, as if getting the dialog to show it's self wasn't enough.

The main example I used to get to where I am was this - https://sourceforge.net/apps/mediawiki/ ... g_creation and the structure of the code was in line with the output I got from Qt4 Designer. i tried to glean enough from that to get even the main button to work but it seems that the input is not going anywhere and the script under it will not run. On top of that, I have no clue as to how to implement a "browse for file" function as all the examples i have seen have a compleatly different syntax / structure than what is in my script.

I used Qt4 Designer, pyuic4 for conversion as pyuic would not work, and the macro dialog in FreeCAD for editing. If someone that might know how I could get this to work would explane what I am doing wrong, or at least point me to where I might be able to find relevant examples, it would be most appreciated.

OS: Ubuntu 12.04.3 LTS
Platform: 32-bit
Version: 0.14.2431 (Git)
Branch: master
Hash: eae2ce3ac25b48052ab97f3778a78f50ec57c0e9
Python version: 2.7.3
Qt version: 4.8.1
Coin version: 3.1.3
SoQt version: 1.5.0
OCC version: 6.5.0

Here is the script:

Code: Select all

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'FreeCAD/Macro/AirFoilScaler.ui'
#
# Created: Wed Sep  4 13:15:09 2013
#      by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!

import FreeCAD, Draft, importAirfoilDAT, sys
from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(281, 250)
        self.header = QtGui.QLabel(Dialog)
        self.header.setGeometry(QtCore.QRect(0, 10, 281, 31))
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.header.setFont(font)
        self.header.setAlignment(QtCore.Qt.AlignCenter)
        self.header.setIndent(0)
        self.header.setObjectName(_fromUtf8("header"))
        self.fileLabel = QtGui.QLabel(Dialog)
        self.fileLabel.setGeometry(QtCore.QRect(0, 60, 281, 31))
        self.fileLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.fileLabel.setObjectName(_fromUtf8("fileLabel"))
        self.locationInput = QtGui.QLineEdit(Dialog)
        self.locationInput.setGeometry(QtCore.QRect(60, 81, 161, 21))
        self.locationInput.setObjectName(_fromUtf8("locationInput"))
        self.browseButton = QtGui.QToolButton(Dialog)
        self.browseButton.setGeometry(QtCore.QRect(240, 80, 25, 23))
        self.browseButton.setObjectName(_fromUtf8("browseButton"))
        self.scaleLabel = QtGui.QLabel(Dialog)
        self.scaleLabel.setGeometry(QtCore.QRect(0, 129, 281, 21))
        self.scaleLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.scaleLabel.setObjectName(_fromUtf8("scaleLabel"))
        self.chordLength = QtGui.QLineEdit(Dialog)
        self.chordLength.setGeometry(QtCore.QRect(100, 151, 81, 21))
        self.chordLength.setObjectName(_fromUtf8("chordLength"))
        self.scaleFoil = QtGui.QPushButton(Dialog)
        self.scaleFoil.setGeometry(QtCore.QRect(90, 210, 101, 23))
        self.scaleFoil.setObjectName(_fromUtf8("scaleFoil"))

        self.retranslateUi(Dialog)
        QtCore.QObject.connect(self.scaleFoil,QtCore.signal("clicked()"),self.createAirfoil)
        QtCore.QMetaObject.connectSlotsByName(Dialog)


    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
        self.header.setText(QtGui.QApplication.translate("Dialog", "Airfoil .dat Scaler", None, QtGui.QApplication.UnicodeUTF8))
        self.fileLabel.setText(QtGui.QApplication.translate("Dialog", "File location", None, QtGui.QApplication.UnicodeUTF8))
        self.browseButton.setText(QtGui.QApplication.translate("Dialog", "...", None, QtGui.QApplication.UnicodeUTF8))
        self.scaleLabel.setText(QtGui.QApplication.translate("Dialog", "Length of Chord", None, QtGui.QApplication.UnicodeUTF8))
        self.scaleFoil.setText(QtGui.QApplication.translate("Dialog", "Scale Airfoil", None, QtGui.QApplication.UnicodeUTF8))

	def createAirfoil(self):
		try:
			# check if valid number has been entered
			cL = float(self.chordLength.text())
		except ValueError:
			print "! Error ! Only Valid Numbers Accepted."
		else:
#          ########################
#          scale script by  shoogen
#          ########################
			scalefactor = cL
			#import importAirfoilDAT      # ^^^ moved to top ^^^ #
			importAirfoilDAT.insert("/home/mark/Downloads/Airfoils/coord_seligFmt/ag35.dat","Unnamed") # imports one Draft Wire named and labeled 'DWire'
			oldobject = App.ActiveDocument.DWire # imported object
			matrix=FreeCAD.Matrix()
			matrix.scale(scalefactor,scalefactor,scalefactor) #scale uniformly
			newshape=oldobject.Shape.copy() # extract the shape from the imported airfoil 
			newshape.transformShape(matrix) # scale the Shape
			newobject=App.ActiveDocument.addObject('Part::Feature','Airfoil1') #create a new Object for the resized shape
			newobject.Shape=newshape # assign the resized shape
			oldobject.ViewObject.Visibility=False #hide the old object
			
			self.hide()
#Make the GUI appear??????????????
import AirFoilScaler
d = QtGui.QWidget()
d.ui = AirFoilScaler.Ui_Dialog()
d.ui.setupUi(d)
d.show()


Thanks - Mark
This post made with 0.0% Micro$oft products - GOT LINUX?
User avatar
shoogen
Posts: 2823
Joined: Thu Dec 01, 2011 5:24 pm

Re: Help With Dialog Buttons In Macro.

Postby shoogen » Thu Sep 05, 2013 10:21 am

I've only very little experience with Qt. But i think that introducing a new file section dialog might create more problems than it solves. However it might make sense if simplifies a work flow significantly.
I would start of with a simpler script, and make is more difficult for the user.
1. Let the user import the airfoil
2. Let the user select the airfoil (DWire)
3. Let the user activate the script (makro dialog, GUI command whatever)
4. Open a dialog or a Task in the task view to prompt for a single float (scale factor)
5. Create the scaled (non-parametric) copy. And close the dialog/task

This makes only sense if the user knows the scaling factor beforehand.

If it is likely to happen, that the user wants resize the airfoil it would be probably better to create a parametric feature for uniform resizing. this would enable the user to change the scaling factor in the properties view. i could do that in python. But i think that it makes more sense to implement this in c++ in the part module.
mario52
Posts: 2583
Joined: Wed May 16, 2012 2:13 pm

Re: Help With Dialog Buttons In Macro.

Postby mario52 » Thu Sep 05, 2013 5:11 pm

hi

new wiki Dialog_creation

to begin with the files:

Code: Select all

# -*- coding: utf-8 -*-

from PyQt4.QtGui import *
from PyQt4.QtCore import *
path = FreeCAD.ConfigGet("AppHomePath")

def errorDialog(msg):
    diag = QtGui.QMessageBox(QtGui.QMessageBox.Critical,u"Error Message",msg )
    diag.setWindowFlags(PyQt4.QtCore.Qt.WindowStaysOnTopHint) # cette fonction met la fenêtre en avant
#    diag.setWindowModality(QtCore.Qt.ApplicationModal)       # la fonction a été désactivée pour favoriser "WindowStaysOnTopHint"
    diag.exec_()

def saveFCInfo(fileFCInfo):
    SaveName = ""
    SaveName = QFileDialog.getSaveFileName(None,QString.fromLocal8Bit("Sauver un fichier txt"),path,"*.txt")
    try:
        if SaveName != "":
            f = open(SaveName, 'w') # write
            f.write(fileFCInfo)
            f.close()
            print fileFCInfo
    except:
        print "Erreur en écriture du fichier ",SaveName
        errorDialog(u"Erreur en écriture du fichier "+SaveName)

def readFCInfo():
    fileFCInfoW = ""
    OpenName = QFileDialog.getOpenFileName(None,QString.fromLocal8Bit("Lire un fichier txt"),path,"*.txt *.txt")
    try:
        if OpenName != "":
            f = open(OpenName, 'r') # read
            fileFCInfoW = f.read()
            f.close()
            print fileFCInfoW
    except:
        print "Erreur en lecture du fichier ",OpenName
        errorDialog(u"Erreur en lecture du fichier "+OpenName)

saveFCInfo("FreeCAd the best")

readFCInfo():

Maybe you need a special feature, go into Macros_recipes and Code_snippets, Dialog creation. My macros on Gist.github.
User avatar
quick61
Posts: 3793
Joined: Sat Aug 24, 2013 2:49 am
Location: u.S.A.

Re: Help With Dialog Buttons In Macro.

Postby quick61 » Sun Sep 22, 2013 10:23 pm

Thank's for the input guys. I'v been going at this with the "headless chicken" approach over the last several weeks, i.e., coming round to it by chance every now and again, and have made some progress. But now I am stuck once again. :oops:

I have the script opening up a file browser and I can select the file I want. It then asks for the scale, (input as chord length) and then it proceeds to only output the original sized airfoil. It does not seem to be running through the rest of the script to make the scale. I know it is getting the scale number from the dialog as I can have that printed out on the Report View in FreeCAD. So, maybe someone can now point out just where I am going wrong and or why this macro is not working like it is suppose to?

Mark

EDIT: I should add, it seems to stop at the "oldobject = App.Act..." line is the Original Script section.

Code: Select all

#=================================================
#			Import & Scale .dat Formated Airfoil
#   Original scaling script by shoogen, modified for GUI input			
#=================================================

from PyQt4 import QtCore, QtGui
import FreeCAD, FreeCADGui, Draft, math
import importAirfoilDAT

# Selcet .dat airfoil data file to be imported
filename = QtGui.QFileDialog.getOpenFileName(QtGui.qApp.activeWindow(),'Open An Airfoil File','*.dat')


def proceed():
	#FreeCAD.Console.PrintError("Importing Scaled Airfoil") # this was a bit noisy :}
	try:
		#	start Original Script 
		scalefactor=str(int(s1.text()))
		f1=str(filename)
		importAirfoilDAT.insert(f1,"Unnamed") # imports one Draft Wire named and labeled 'DWire'
		oldobject = App.ActiveDocument.DWire # imported object
		matrix=FreeCAD.Matrix()
		matrix.scale(scalefactor,scalefactor,scalefactor) #scale uniformly
		newshape=oldobject.Shape.copy() # extract the shape from the imported airfoil 
		newshape.transformShape(matrix) # scale the Shape
		newobject=App.ActiveDocument.addObject('Part::Feature','Airfoil1') #create a new Object for the resized shape
		newobject.Shape=newshape # assign the resized shape
		oldobject.ViewObject.Visibility=False #hide the old object
		#	end Original Script
	except:
            FreeCAD.Console.PrintError("Error, not a valid .dat file")
	close()	
	diag.show()

def close():
    dialog.hide()

# Do dialog box and get the scale size
dialog = QtGui.QDialog()
dialog.resize(260,100)
dialog.setWindowTitle("Airfoil Import Scale")
la = QtGui.QVBoxLayout(dialog)
t1 = QtGui.QLabel("Chord Length")
la.addWidget(t1)
s1 = QtGui.QLineEdit()
la.addWidget(s1)
okbox = QtGui.QDialogButtonBox(dialog)
okbox.setOrientation(QtCore.Qt.Horizontal)
okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
la.addWidget(okbox)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), proceed)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), close)
QtCore.QMetaObject.connectSlotsByName(dialog)
dialog.show()

diag = QtGui.QMessageBox(QtGui.QMessageBox.Information, 'Import Scaled Airfoil', 'Import Finish')
diag.setWindowModality(QtCore.Qt.ApplicationModal)
OS: Ubuntu 13.04
Platform: 64-bit
Version: 0.14.2538 (Git)
Branch: master
Hash: 4eddde5c4691511096236b1bc811741d1c5d2575
Python version: 2.7.4
Qt version: 4.8.4
Coin version: 3.1.3
SoQt version: 1.5.0
OCC version: 6.5.0
This post made with 0.0% Micro$oft products - GOT LINUX?