I am trying to restore SQL server backup using python. I have a UI built in Tkinter which accepts the filepath and other details like servername, databasename, etc. For testing I am just using localhost. There are two file that I have developed. One called tool.py that has the UI and the other file called Restorebackup.py which has the logic to restore the database. When you run the tool.py file and press the start button it asks you for the file path of the .dat_bak or .bak file that you want to restore. After choosing the .dat_bak file you wait for some time and you get the message as "Backup is restored". I go to SQL Server Management Studio and see the databases in localhost. It shows that backup is restoring with the blue arrow. Unfortunately it never completes and is stuck there forever. When I just run the Restorebackup.py by hardcoding filepath and other values it restores backup perfectly fine. Not sure what is the issue
Restorebackup.py file
import pyodbc
import os
#######################################################################################################################
def restore_backup(selectedChoiceServer, selectedChoiceDatabase, selectedChoiceSchema, filePath):
try:
driver= '{SQL Server}'
selectedChoiceServer="localhost"
db_environment= 'master'
username= 'sqlserverloginforlocalhost'
password='yourpassword'
connectionString = (('DRIVER='+driver+';PORT=1433;SERVER='+selectedChoiceServer+';PORT=1443;DATABASE='+ db_environment +';UID='+username+';PWD='+ password))
db_connection = pyodbc.connect(connectionString, autocommit=True)
cursor = db_connection.cursor()
cursor.execute("""RESTORE FILELISTONLY FROM DISK = '"""+filePath+"""'""")
dataset = cursor.fetchall()
YourMDFLogicalName = dataset[0][0]
YourLDFLogicalName = dataset[1][0]
if not os.path.exists('c:/mybackup/backuptest'):
os.mkdir('c:/mybackup/backuptest')
db_connection = pyodbc.connect(connectionString, autocommit=True)
sql = """
USE [master]
RESTORE DATABASE [testdatabase] FROM
DISK = N'"""+filePath+"""'
WITH FILE = 1
,RECOVERY
, MOVE N'Service' TO N'C:/mybackup/backuptest/""" + YourMDFLogicalName + """.mdf'
, MOVE N'Service_log' TO N'C:/mybackup/backuptest/""" + YourLDFLogicalName + """.ldf'
, NOUNLOAD, STATS = 5
"""
cursor.execute(sql)
db_connection.autocommit = False
return 1
except Exception as e:
print('Some Error Occured, so backup was not restored')
print('Error is :' + str(e))
return str(e)
#######################################################################################################################
tool.py file
from tkinter import messagebox
from tkinter import filedialog
import unknown_support
from Restorebackup import restore_backup
import tkinter as Tk
from tkinter import *
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = Tk()
top = Tool (root)
unknown_support.init(root, top)
root.mainloop()
def destroy_Tool():
root.destroy()
class Tool:
def StartButtonAction(self):
self.Button1.config(state=DISABLED)
selectedChoiceServer = self.Text3.get('1.0','end-1c')
selectedChoiceDatabase = self.Text1.get('1.0','end-1c')
selectedChoiceSchema = self.Text2.get('1.0','end-1c')
root.fileName = filedialog.askopenfilename( filetypes = ( ("bak files", "*.dat_bak"),("All files","*.*") ) )
#root.fileName = root.fileName.replace('/', '\\')
res = restore_backup(selectedChoiceServer, selectedChoiceDatabase, selectedChoiceSchema, root.fileName)
if res == 1:
messagebox.showinfo("Backup is restored", "Backup is restored")
else:
messagebox.showinfo("Error: ",res)
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
top.geometry("600x450+761+233")
top.title("Backup Restore Tool")
top.configure(background="#d9d9d9")
top.configure(highlightbackground="#d9d9d9")
top.configure(highlightcolor="black")
self.choice = IntVar()
self.databaseChoice = StringVar()
self.Label1 = Label(top)
self.Label1.place(relx=0.32, rely=0.38, height=26, width=58)
self.Label1.configure(background="#d9d9d9")
self.Label1.configure(disabledforeground="#a3a3a3")
self.Label1.configure(foreground="#000000")
self.Label1.configure(text='''Schema''')
self.Label2 = Label(top)
self.Label2.place(relx=0.3, rely=0.24, height=26, width=69)
self.Label2.configure(background="#d9d9d9")
self.Label2.configure(disabledforeground="#a3a3a3")
self.Label2.configure(foreground="#000000")
self.Label2.configure(text='''Database''')
self.Label3 = Label(top)
self.Label3.place(relx=0.3, rely=0.10, height=26, width=69)
self.Label3.configure(background="#d9d9d9")
self.Label3.configure(disabledforeground="#a3a3a3")
self.Label3.configure(foreground="#000000")
self.Label3.configure(text='''Server''')
self.Text1 = Text(top)
self.Text1.place(relx=0.45, rely=0.24, relheight=0.05, relwidth=0.39)
self.Text1.configure(background="#ffffffffffff")
self.Text1.configure(font="TkTextFont")
self.Text1.configure(foreground="black")
self.Text1.configure(highlightbackground="#d9d9d9")
self.Text1.configure(highlightcolor="black")
self.Text1.configure(insertbackground="black")
self.Text1.configure(selectbackground="#c4c4c4")
self.Text1.configure(selectforeground="black")
self.Text1.configure(width=234)
self.Text1.configure(wrap=WORD)
self.Text2 = Text(top)
self.Text2.place(relx=0.45, rely=0.38, relheight=0.05, relwidth=0.39)
self.Text2.configure(background="white")
self.Text2.configure(font="TkTextFont")
self.Text2.configure(foreground="black")
self.Text2.configure(highlightbackground="#d9d9d9")
self.Text2.configure(highlightcolor="black")
self.Text2.configure(insertbackground="black")
self.Text2.configure(selectbackground="#c4c4c4")
self.Text2.configure(selectforeground="black")
self.Text2.configure(width=234)
self.Text2.configure(wrap=WORD)
self.Text3 = Text(top)
self.Text3.place(relx=0.45, rely=0.10, relheight=0.05, relwidth=0.39)
self.Text3.configure(background="white")
self.Text3.configure(font="TkTextFont")
self.Text3.configure(foreground="black")
self.Text3.configure(highlightbackground="#d9d9d9")
self.Text3.configure(highlightcolor="black")
self.Text3.configure(insertbackground="black")
self.Text3.configure(selectbackground="#c4c4c4")
self.Text3.configure(selectforeground="black")
self.Text3.configure(width=234)
self.Text3.configure(wrap=WORD)
self.Button1 = Button(top)
self.Button1.place(relx=0.4, rely=0.58, height=33, width=186)
self.Button1.configure(activebackground="#d9d9d9")
self.Button1.configure(activeforeground="#000000")
self.Button1.configure(background="#d9d9d9")
self.Button1.configure(disabledforeground="#a3a3a3")
self.Button1.configure(foreground="#000000")
self.Button1.configure(highlightbackground="#d9d9d9")
self.Button1.configure(highlightcolor="black")
self.Button1.configure(pady="0")
self.Button1.configure(text='''Start''')
self.Button1.configure(width=186)
self.Button1.configure(command = self.StartButtonAction)
self.Button2 = Button(top)
self.Button2.place(relx=0.4, rely=0.68, height=33, width=186)
self.Button2.configure(activebackground="#d9d9d9")
self.Button2.configure(activeforeground="#000000")
self.Button2.configure(background="#d9d9d9")
self.Button2.configure(disabledforeground="#a3a3a3")
self.Button2.configure(foreground="#000000")
self.Button2.configure(highlightbackground="#d9d9d9")
self.Button2.configure(highlightcolor="black")
self.Button2.configure(pady="0")
self.Button2.configure(text='''Quit''')
self.Button2.configure(width=186)
self.Button2.configure(command = destroy_Tool)
if __name__ == '__main__':
vp_start_gui()
I just introduced some delay and made a few other changes and it worked for me. Please refer to the code as follows
restoreddatabase = selectedChoiceSchema + '-' + strftime("%Y%m%d%H%M%S", gmtime()) +'import'
connectionString = (('DRIVER='+driver+';PORT=1433;SERVER='+localserver+';PORT=1443;DATABASE='+ db_environment +';UID='+localusername+';PWD='+ password))
db_connection = pyodbc.connect(connectionString, autocommit = True)
cursor = db_connection.cursor()
cursor.execute("""RESTORE FILELISTONLY FROM DISK = '"""+filePath+"""'""")
dataset = cursor.fetchall()
filenames = []
for i in dataset:
filedetails = {}
#print(i[0])
#print(i[1][::-1][:(i[1][::-1]).find('\\')][::-1])
filedetails['name'] = i[0]
filedetails['withextension'] = i[1][::-1][:(i[1][::-1]).find('\\')][::-1]
filenames.append(filedetails)
if not os.path.exists(rootfolder + '/'+ restoreddatabase):
os.mkdir(rootfolder + '/'+ restoreddatabase)
print(filePath)
filePath = filePath.replace("/","\\")
rootfolder = rootfolder.replace("/","\\")
sql = """
USE [master]
RESTORE DATABASE ["""+restoreddatabase+"""] FROM
DISK = N'"""+filePath+"""'
WITH FILE = 1
,RECOVERY
"""
for i in filenames:
sql = sql + """, MOVE N'""" +i['name'] +"""' TO N'"""+ rootfolder +"""\\"""+ restoreddatabase+"""\\""" + i['withextension'] + """'"""
sql = sql + """, NOUNLOAD, STATS = 5
"""
cursor.execute(sql)
db_connection1 = pyodbc.connect(connectionString)
cursor1 = db_connection1.cursor()
database_restored_sql = """select top 1 * from msdb.dbo.restorehistory order by restore_date desc"""
cursor1.execute(database_restored_sql)
dataset = cursor1.fetchall()
tquery = """
SELECT session_id as SPID, command, a.text AS Query, start_time, percent_complete, dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) a WHERE r.command in ('BACKUP DATABASE','RESTORE DATABASE')
"""
print('Percentage Restored: ', end = '', flush = True)
#sys.stdout.write('Percentage Restored: ')
while restoreddatabase != dataset[0][2]:
#print('in while')
sleep(5)
cursor1.execute(database_restored_sql)
dataset = cursor1.fetchall()
cursor1.execute(tquery)
tdataset = cursor1.fetchall()
if len(tdataset) > 0:
if tdataset[0][4] > 99.99:
print(str(tdataset[0][4])[0:3] + '%',end = ' ', flush = True)
#sys.stdout.write(str(tdataset[0][4])[0:3] + '% ')
else:
print(str(tdataset[0][4])[0:2] + '% ',end = ' ', flush = True)
#sys.stdout.write(str(tdataset[0][4])[0:2] + '% ')
db_connection.autocommit = False
Related
I am trying to make a weather forecast "app" using python, following the instructions of this video: https://www.youtube.com/watch?v=7JoMTQgdxg0
Everything works fine, except from the functionality of displaying some icons to make it look better.
If i remove the code that its used for the icons, everything works perfect. I don´t know what I should do so this works.
from tkinter import *
from tkinter import messagebox
from configparser import ConfigParser
import requests
url = "https://api.openweathermap.org/data/2.5/weather?q={}&appid={}"
config_file = 'config.ini'
config = ConfigParser()
config.read(config_file)
api_key = config['api_key']['key']
def get_weather(city):
result = requests.get(url.format(city, api_key))
if result:
#print(result.content)
json = result.json()
#City, country, temp_celsius, temp:farenheit, icon weather
city = json['name']
country = json['sys']['country']
temp_kelvin = json['main']['temp']
temp_celsius = temp_kelvin - 273.15
temp_farenheit = (temp_kelvin - 273.15) * 9 / 5 + 32
icon = json['weather'][0]['icon']
weather = json['weather'][0]['main']
final = (city, country, temp_celsius, temp_farenheit, icon, weather)
return final
else:
return None
#print(get_weather('London'))
def search():
city = city_text.get()
weather = get_weather(city)
if weather:
location_lbl['text'] = '{}, {}'.format(weather[0], weather[1])
image['bitmap'] = 'weather_icons/{}.png'.format(weather[4])#HERE ITS THE PROBLEM
temp_lbl['text'] = '{:.2f}ºC, {:.2f}ºF'.format(weather[2], weather[3])
weather_lbl['text'] = weather[5]
else:
messagebox.showerror('Error', 'Cannot find city {}'.format(city))
app = Tk()
app.title("Weather App")
app.geometry('700x350')
city_text = StringVar()
city_entry = Entry(app, textvariable=city_text)
city_entry.pack()
search_btn = Button(app, text='Search Weather', width=12, command=search)
search_btn.pack()
location_lbl = Label(app, text="", font=('bold', 20))
location_lbl.pack()
image = Label(app, bitmap='')#HERE ITS THE PROBLEM
image.pack()
temp_lbl = Label(app, text="")
temp_lbl.pack()
weather_lbl = Label(app, text="")
weather_lbl.pack()
app.mainloop()
I also have another file that its called: config.ini for saving my API key, and a folder named weather_icons for storing the images
.
I'm unable to update my table in MySQL using Tkinter. It just won't get updated. I have tried checking where the table name is different but it's not. It shows no errors but not getting updated.
from tkinter import *
t = Tk()
t.geometry("500x500")
Label(text = 'Name:').place(x=10,y=10)
nm = Entry()
nm.place(x=55,y=12)
Label(text = 'age:').place(x=10,y=35)
ag = Entry()
ag.place(x=55,y=37)
def abcd():
import pymysql
x = pymysql.connect(host = 'localhost',user = 'root',password = 'admin',db ='db')
cur = x.cursor()
n= nm.get()
a = ag.get()
cur.execute('insert into sample2 values(%s, %s)',(n,a))
x.commit()
x.close()
Button(text ='Submit',command = abcd).place(x=40,y=65)
Label(text ='UPDATE',fg = 'white',bg = 'black',font = ('Times new roman',24,'bold')).place(x=10,y=100)
Label(text ='Enter the name to update').place(x = 5,y = 155)
b=Entry()
b.place(x = 150, y = 157)
Label(text = 'Enter new age:').place(x=5,y = 200)
nag = Entry()
nag.place(x=150,y = 202)
'''print(b)'''
def upd():
import pymysql
x = pymysql.connect(host = 'localhost',user = 'root',password = 'admin',db ='db')
cur = x.cursor()
gnd =b.get()
anag = nag.get()
cur.execute('update sample2 set age =%s where name = %s',(gnd,anag))
x.commit()
x.close()
t.mainloop()
Button(text = 'apply',command = upd).place(x = 200, y = 300)
t.mainloop()
It is because the order of the arguments used in UPDATE is wrong:
cur.execute('update sample2 set age =%s where name = %s',(gnd,anag)) # wrong order of arguments
So the WHERE clause is evaluated as False and no record will be updated.
It should be:
cur.execute('update sample2 set age =%s where name = %s',(anag, gnd))
I am making a small app with Tkinter, for educational purposes, which consists of pressing a button and displaying the contents of a textobox ... in another multiline textbox.
The problem is that you see this:
<bound method Text.get of <tkinter.Text object.! Text2 >>
and not the content that I manually write of the textobox. The textbox that I would like to print in the multiline textobox (called text) is called textbox_test. Textbox_test is called
A = f "{test_textbox.get} {'' .join (word2)} {abitanti} abitanti su un'area di {superficie}".
Questo è il textobox
test_textbox = Text(window,width=10,height=1)
test_textbox.pack()
test_textbox.place(x=5, y=100)
How can I remove the error above and correctly display the text of a textbox? I attach complete code. Thank you
from tkinter import *
from tkinter import ttk
import tkinter as tk
import sqlite3
import random
window=Tk()
window.title("xxxxxxxx")
window.geometry("750x750")
window.configure(bg='#78c030')
con = sqlite3.connect('/home/xxxxxxxxxxx/Database.db')
cursor = con.cursor()
# Search Data
def city(name_city):
name_city = city.get()
cursor.execute('SELECT * FROM Info WHERE City =?',(name_city,))
results = cursor.fetchone()
return results
# Print Data in textbox multiline
def write():
name_city = city.get
results = city(name_city)
inhabitants = results[2]
surface = results[3]
if categoria.get() == "Test 1" and sottocategoria.get() == "Test 1.1":
cursor.execute('SELECT xxxxxxxx FROM TableExample ORDER BY RANDOM() LIMIT 1')
word2 = cursor.fetchone()
text.delete(1.0,END)
A= f"{test_textbox.get} {''.join(word2)} {inhabitants} inhabitants on an area of {surface}"
B= f"Che sale a"
text.insert(tk.END, random.choice([A, B]))
button2 = Button(window, text="Button2", bg='white', command = write)
button2.pack()
button2.place(x=5, y=330)
### TEXTBOX MULTILINE ###
text = Text(window,width=63,height=38)
text.pack()
text.place(x=180, y=24)
### TEXTBOX ###
test_textbox = Text(window,width=10,height=1)
test_textbox.pack()
test_textbox.place(x=5, y=100)
### CATEGORIA E SOTTO CATEGORIA ###
cat=StringVar()
sub_cat=StringVar()
def change_val(*args):
if cat.get() == "Test 1":
sottocategorias = ["Test 1.1", "Test 1.2", "Test 1.3"]
sottocategoria.config(values=sottocategorias)
else:
sottocategorias = ["aaaa"]
sottocategoria.config(values=sottocategorias)
categorias=["Test 1", "Test 2", "Test 3"]
categoria=ttk.Combobox(window,value=categorias,textvariable=cat,width=16)
categoria.place(x=5, y=25)
cat.set("Scegliere categoria")
sottocategorias=["aaaa"]
sottocategoria=ttk.Combobox(window,textvariable=sub_cat,value=sottocategorias,
width=16)
sottocategoria.place(x=5, y=55)
cat.trace("w",change_val)
### COMBOBOX ###
def combo_nation():
cursor.execute('SELECT DISTINCT Nation FROM Info')
result=[row[0] for row in cursor]
return result
def combo_city(event=None):
val = city.get()
cursor.execute('SELECT City FROM Info WHERE Nation = ?', (val,))
result = [row[0] for row in cursor]
city['value'] = result
city.current(0)
return result
nation=ttk.Combobox(window,state="readonly")
nation['value'] = combo_nation()
nation.bind('<<ComboboxSelected>>', combo_city)
nation.place(x=5, y=150,height = 25, width = 180)
city=ttk.Combobox(window,state="readonly")
city.place(x=5, y=180, height = 25, width = 180)
window.mainloop()
IMPORTANT: If you try to change to A = f "{test_textbox.get (" 1.0 "," end-1c ")} {'' .join (word2)}, that's not good. The app won't open. Without this code instead opens
As #BryanOakley said in comment you need get with () to run it and widget Text needs it with arguments like
A = f"{test_textbox.get('1.0','end-1c')} ...
It didn't work because it was only part which you would have to replace in full text, but it seems you replaced all text. Because you didn't run code in console so you couldn't see error message which could explain problem
Full line should be
A = f"{test_textbox.get('1.0','end-1c')} {''.join(word2)} {inhabitants} inhabitants on an area of {surface}"
#imports
from tkinter import *
from tkinter import messagebox as ms
import sqlite3
# make database and users (if not exists already) table at programme start up
with sqlite3.connect('quit.db') as db:
c = db.cursor()
c.execute('CREATE TABLE IF NOT EXISTS user (username TEXT NOT NULL ,password TEX NOT NULL);')
db.commit()
db.close()
#main Class
class main:
def __init__(self,master):
# Window
self.master = master
# Some Usefull variables
self.username = StringVar()
self.password = StringVar()
self.n_username = StringVar()
self.n_password = StringVar()
#Create Widgets
self.widgets()
def NewPage():
global NewRoot
root.withdraw() # hide (close) the root/Tk window
NewRoot = tk.Toplevel(root)
# use the NewRoot as the root now
#Login Function
def login(self):
with sqlite3.connect('quit.db') as db:
c = db.cursor()
#Find user If there is any take proper action
find_user = ('SELECT * FROM user WHERE username = ? and password = ?')
c.execute(find_user,[(self.username.get()),(self.password.get())])
result = c.fetchall()
if result:
self.logf.pack_forget()
self.head['text'] = self.username.get() + '\n Logged In'
self.head['pady'] = 150
root.after(2000, NewPage)
else:
ms.showerror('Oops!','Username Not Found.')
def new_user(self):
#Establish Connection
with sqlite3.connect('quit.db') as db:
c = db.cursor()
#Find Existing username if any take proper action
find_user = ('SELECT * FROM user WHERE username = ?')
c.execute(find_user,[(self.username.get())])
if c.fetchall():
ms.showerror('Error!','Username Taken Try a Diffrent One.')
else:
ms.showinfo('Success!','Account Created!')
self.log()
#Create New Account
insert = 'INSERT INTO user(username,password) VALUES(?,?)'
c.execute(insert,[(self.n_username.get()),(self.n_password.get())])
db.commit()
#Frame Packing Methords
def log(self):
self.username.set('')
self.password.set('')
self.crf.pack_forget()
self.head['text'] = 'LOGIN'
self.logf.pack()
def cr(self):
self.n_username.set('')
self.n_password.set('')
self.logf.pack_forget()
self.head['text'] = 'Create Account'
self.crf.pack()
#Draw Widgets
def widgets(self):
self.head = Label(self.master,text = 'LOGIN',font = ('',35),pady = 10)
self.head.pack()
self.logf = Frame(self.master,padx =10,pady = 10)
Label(self.logf,text = 'Username: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.logf,textvariable = self.username,bd = 5,font = ('',15)).grid(row=0,column=1)
Label(self.logf,text = 'Password: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.logf,textvariable = self.password,bd = 5,font = ('',15),show = '*').grid(row=1,column=1)
Button(self.logf,text = ' Login ',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.login).grid()
Button(self.logf,text = ' Create Account ',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.cr).grid(row=2,column=1)
self.logf.pack()
self.crf = Frame(self.master,padx =10,pady = 10)
Label(self.crf,text = 'Username: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.crf,textvariable = self.n_username,bd = 5,font = ('',15)).grid(row=0,column=1)
Label(self.crf,text = 'Password: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.crf,textvariable = self.n_password,bd = 5,font = ('',15),show = '*').grid(row=1,column=1)
Button(self.crf,text = 'Create Account',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.new_user).grid()
Button(self.crf,text = 'Go to Login',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.log).grid(row=2,column=1)
if __name__ == '__main__':
#Create Object
#and setup window
root = Tk()
root.title('Login Form')
#root.geometry('400x350+300+300')
main(root)
root.mainloop()
On line 37 it says NewPage is not defined but I defined it on line 24, please help. this program is object oriented and im a student trying to complete this for my A-Level project. I dont understand alot of this code but any help would be much appreciated. Im a amateur when it comes to python/tkinter/sqlite but need this help otherwise I will fail my course because my teacher is not much help when it comes to programming
You are missing self in your function def NewPage(self): and go to the line which you have root.after(2000, NewPage) and replace it with root.after(2000, self.NewPage)
I need someone's expertise on this exporting problem of mine.
How it works: Select a camera (animated or not is optional) >> File >> Export Selection >> File Type : .chan (need to load this script as a plugin)
Here's where the problem starts. It is able to create a .text file, however, it is not 'exporting' or writing out the contents into the text file and the file size is of zero bytes.
I am making use of the current API that it has been coded, modifying the code to add in some maya cmds
Can someone kindly help me out?
import math, sys, string, os
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMayaAnim as OpenMayaAnim
import maya.cmds as cmds
import maya.mel as mel
kPluginTranslatorTypeName = "chan Export/Import"
kVersionNumber = "0.5a"
camSel = []
win_name = "chan_window"
class CustomNodeTranslator(OpenMayaMPx.MPxFileTranslator):
def __init__(self):
OpenMayaMPx.MPxFileTranslator.__init__(self)
def haveWriteMethod(self):
return True
def haveReadMethod(self):
return True
def filter(self):
return " .chan"
def defaultExtension(self):
return "chan"
def writer( self, fileObject, optionString, accessMode ):
try:
fullName = fileObject.fullName()
fileHandle = open(fullName,"w")
selectList = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList(selectList)
node = OpenMaya.MObject()
depFn = OpenMaya.MFnDependencyNode()
path = OpenMaya.MDagPath()
iterator = OpenMaya.MItSelectionList(selectList)
animationTime = OpenMayaAnim.MAnimControl()
maxTime = int(animationTime.maxTime().value())
minTime = int(animationTime.minTime().value())
while (iterator.isDone() == 0):
iterator.getDependNode(node)
depFn.setObject(node)
iterator.getDagPath(path, node)
cameraObject = OpenMaya.MFnCamera(path)
transform = OpenMaya.MFnTransform(path)
chanMe = fileExporter(transform, minTime, maxTime, cameraObject)
for all in chanMe():
fileHandle.write(all)
iterator.next()
fileHandle.close()
except:
sys.stderr.write( "Failed to write file information\n")
raise
def processLine( self, lineStr ):
self.importTheChan.writeFrameData(lineStr)
class fileExporter():
""" module for exporting chan files from application. arguments: object, startFrame, endFrame """
def __init__(self, transform, startAnimation, endAnimation, cameraObj):
self.fileExport = []
self.transform = transform
self.cameraObj = cameraObj
self.start = startAnimation
self.end = endAnimation
self.exportWin()
def exportWin(self):
self.expWindow = cmds.window(w=150, h=100, title = "Export Selection" )
cmds.columnLayout( adjustableColumn=True )
form = cmds.formLayout(numberOfDivisions=100)
cmds.radioCollection()
self.chk1 = cmds.radioButton( label='option1', onc = self.opt1On, ofc = self.opt1Off )
self.chk2 = cmds.radioButton( label='option2', onc = self.opt2On, ofc = self.opt2Off )
self.okayBtn = cmds.button(label='okay!', command=self.runSel, width=150, height=35)
cmds.formLayout(form, edit=True, attachForm=[\
(self.chk1, 'top', 15),\
(self.chk1, 'left', 15),\
(self.chk2, 'top', 30),\
(self.chk2, 'left', 15),\
(self.okayBtn, 'top', 50),\
(self.okayBtn, 'left', 15)])
cmds.showWindow( self.expWindow )
def opt1On(self, args):
print "User checked option1"
startAnimation = cmds.playbackOptions(query=True, minTime=True)
endAnimation = cmds.playbackOptions(query=True, maxTime=True)
self.start = startAnimation
self.end = endAnimation
def opt1Off(self, args):
print "User un-checked option1"
cmds.radioButton(self.chk2, edit = True, enable = True)
self.start = ""
self.end = ""
def opt2On(self, args):
print "User checked option2"
startAnimation = cmds.findKeyframe(which='first')
endAnimation = cmds.findKeyframe(which='last')
self.start = startAnimation
self.end = endAnimation
#self.start.append(int(startAnimation))
#self.end.append(int(endAnimation))
def opt2Off(self, args):
print "User un-checked option2"
self.start = ""
self.end = ""
def runSel(self, args):
chkVal1 = cmds.radioButton(self.chk1, query=True, sl=1)
chkVal2 = cmds.radioButton(self.chk2, query=True, sl=1)
if chkVal1 == 1:
print "opt1 Pressed!"
print self.start
print self.end
self.test()
self.closeWindow()
elif chkVal2 == 1:
print "opt2 Pressed!"
print self.start
print self.end
self.test()
self.closeWindow()
else:
cmds.warning("Check an option")
def closeWindow(self):
cmds.deleteUI(self.expWindow, window=True)
def test(self):
self.actualExp(self.transform, self.start, self.end, self.cameraObj)
def actualExp(self, transform, startAnimation, endAnimation, cameraObj):
mayaGlobal = OpenMaya.MGlobal()
mayaGlobal.viewFrame(OpenMaya.MTime(1))
# Converts the float arguement into integer
for i in range(int(startAnimation), int(endAnimation + 1)):
focalLength = cameraObj.focalLength()
vFilmApp = cameraObj.verticalFilmAperture()
focalOut = 2 math.degrees(math.atan(vFilmApp 25.4/ (2 focalLength)))
myEuler = OpenMaya.MEulerRotation()
spc = OpenMaya.MSpace.kWorld
trans = transform.getTranslation(spc)
rotation = transform.getRotation(myEuler)
rotVector = OpenMaya.MVector(myEuler.asVector())
self.fileExport.append((str(i) + '\t' + str(trans[0]) + "\t" + str(trans[1]) + "\t" + str(trans[2]) + "\t" + str(math.degrees(rotVector[0])) + "\t" + str(math.degrees(rotVector[1])) + "\t" + str(math.degrees(rotVector[2])) + "\t" + str(focalOut) + "\n"))
mayaGlobal.viewFrame(OpenMaya.MTime(i+1))
def __call__(self, args):
return self.fileExport
def radianToDegree(self, radians):
outDegrees = 0.0
outDegrees = (float(radians) / (math.pi)) 180
return outDegrees
# creator
def translatorCreator():
return OpenMayaMPx.asMPxPtr( CustomNodeTranslator() )
# initialize the script plug-in
def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.registerFileTranslator(kPluginTranslatorTypeName, None, translatorCreator)
except:
sys.stderr.write( "Failed to register translator: %s" % kPluginTranslatorTypeName )
raise
# uninitialize the script plug-in
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.deregisterFileTranslator( kPluginTranslatorTypeName )
except:
sys.stderr.write( "Failed to deregister translator: %s" % kPluginTranslatorTypeName )
raise
the __call__ method is what's supposed to provide the contents of the file. It returns self.fileExport, which is an empty list that is not getting populated.
The problem here is the writer method of the plugin will not wait for your exportWin UI to return the user inputs when you call
chanMe = fileExporter(transform, minTime, maxTime, cameraObject)
By the time the user has entered the inputs, the statements that follow have already been executed:
for all in chanMe():
fileHandle.write(all)
iterator.next()
fileHandle.close()
That is why plugin-based file exporters like these have their options UI tucked away in the option box. These options will be passed prior to call to the plugin's writer().
You will need to export your options UI code (in a certain specific format) using MEL in another script file and specify the name of that file in the optionsScriptName param of the registerFileTranslator call. There is a communication protocol that needs to be followed for communication between this options UI and the writer plugin itself. RobTheBloke's awesome post illustrates this process.
Ideally, the writer() method should have all the details it needs for computing and exporting without having to wait for user input.
Alternatively, if you prefer to have your own UI window and more control over the flow of things, you could write the exporter not as a plugin, but as a simple MEL/Python module. You could still use the power of the API.
Hope this helped!