Esempio n. 1
0
class MainWindow(QtGui.QMainWindow):
	def __init__(self):#inicjalizacja klasy
		QtGui.QMainWindow.__init__(self)

	#inicjalizacji glownego ui
		ui = self.ui = Ui_MainWindow() 
		self.ui.setupUi(self)
		self.show()
		
		self.addWidgets() #dodanie pozostalych widgetow
		self.connectSignals() #polaczenie sygnalow ze slotami
		self.flags() #stworzenie/ustawinie flag
		self.variables() #inicjalizacja zmiennych
		self.setToolTipsForAll() #ustawia wskazowki do wsyzstkich narzezi
		self.setWindowTitle("PyCAD")
	
	def addWidgets(self):#dodanie widgetow do glownego okna
		#opengl
		self.qgl = GLWidget(self) 
		self.ui.horizontalLayout.addWidget(self.qgl) #dodanie widgeta zajmujacego sie obsluga opengl do glownego okna
		
		#lista obiektow
		self.widgetlist = WidgetList()
		self.ui.horizontalLayout.addWidget(self.widgetlist)
		self.widgetlist.hide()
		
		#przyciski do recznego wprowadzania danych
		self.widgetxy = WidgetXY()
		self.ui.verticalLayoutDown.addWidget(self.widgetxy)
		#self.widgetxy.hide()
	
	def flags(self): #flagi
		self.setMouseTracking(False) #wylaczenie sledzenia myszki w glownym oknie
		self.f_saved = True #czy plik zostal zapisany
		self.setAcceptDrops(True)
	
	def variables(self): #wykorzystywane zmienne
		self.markedobjects = [] #zaznaczone obiekty
		self.nrofconstobjt = 2
		self.fname = "" #nazwa pliku
		self.zoom = 0.5 #o ile bedzie zmienial sie widok
		self.dxdy = 0.5 #o ile przesuwam scene przy uzyciu strzalek
	
	def connectSignals(self):#polaczenie sygnalow i slotow
	#sygnaly wyemitowane przez qgl przypisanego do jednego slota (nie ma potrzeby rozroznienia tych zdarzen w tym miejscu)
		self.qgl.s_mousepos.connect(self.qglMouse) #zmiana pozycji
		self.qgl.s_mousepress.connect(self.qglMouse) #klikniecie 
		self.qgl.s_newobj.connect(self.addedObjWidgetList)#dodano nowy obiekt do listy
		self.qgl.s_filechanged.connect(self.FileNotSaved)
		self.qgl.s_zoomend.connect(self.zoomSignal) 
		self.qgl.s_knowpoint.connect(self.knowpoint)
		
	#lista
		self.widgetlist.ui.pushButtonDown.clicked.connect(self.pushButtonDown)
		self.widgetlist.ui.pushButtonUp.clicked.connect(self.pushButtonUp)
		self.widgetlist.ui.pushButtonUsun.clicked.connect(self.pushButtonRemove)
		self.widgetlist.ui.listWidget.itemClicked.connect(self.clickWidgetList)
		self.widgetlist.ui.listWidget.itemSelectionChanged.connect(self.clickWidgetList)
	
	#Przyciski - niestety klasa QSignalMapper nie dziala wec zostaje to
		self.ui.pushButtonNarz0.clicked.connect(self.pushButtonNarz0)
		self.ui.pushButtonNarz1.clicked.connect(self.pushButtonNarz1)
		self.ui.pushButtonNarz2.clicked.connect(self.pushButtonNarz2)
		self.ui.pushButtonNarz3.clicked.connect(self.pushButtonNarz3)
		self.ui.pushButtonNarz4.clicked.connect(self.pushButtonNarz4)
		self.ui.pushButtonNarz5.clicked.connect(self.pushButtonNarz5)
		self.ui.pushButtonNarz6.clicked.connect(self.pushButtonNarz6)
		self.ui.pushButtonNarz7.clicked.connect(self.pushButtonNarz7)
		self.ui.pushButtonNarz8.clicked.connect(self.pushButtonNarz8)
		
	#menubar - plik
		self.ui.actionNowy.triggered.connect(self.newAction) #wcisniecie przycisku nowy
		self.ui.actionZakoncz.triggered.connect(self.closeEvent) #uwaga dwa razy wola zamkniecie
		self.ui.actionZapisz.triggered.connect(self.saveFile) #zapisanie
		self.ui.actionZapisz_jako.triggered.connect(self.saveFileAs) #zapisz jako
		self.ui.actionOtworz.triggered.connect(self.loadAction) #otwarcie pliku
		self.ui.actionZakoncz.triggered.connect(self.closeEvent) #wcisniecie przycisku nowy
		
	#menubar - edycja
		self.ui.actionCofnij.triggered.connect(self.menubarBack)
		self.qgl.s_previous.connect(self.signalMenubarBack)
		
		self.ui.actionPonow.triggered.connect(self.menubarForward) 
		self.qgl.s_next.connect(self.signalMenubarNext)
		
	#menubar - widok
		self.ui.actionPowieksz.triggered.connect(self.ZoomInView)
		self.ui.actionPomniejsz.triggered.connect(self.ZoomOutView)
		self.ui.actionStandardowy.triggered.connect(self.defaultView)
		
	def setToolTipsForAll(self): #ustawia wskazowki do wszystkich narzedzi
		#--- Ui_MainWindow (glowne ui) ---#
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz0,"Zaznaczenie jednego obiektu")
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz1,"Linia")
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz2,"Linie laczace sie")
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz3,"Tworzenie luku")
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz4,"Lista obiektow")
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz5,"Linia + kat - do wycofania") 
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz6,"Zaznaczenie wielu obiektow")
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz7,"Strzalki (nie zaimplementowane)")
		self.defaultToolTipStyleForButton(self.ui.pushButtonNarz8,"Przesuwanie punktu")
	
#------------ WIDGETLIST ------------#
	def markObjectsWidgetList(self): #zanaczenie listy obiektow
		for nr in self.markedobjects:
			self.qgl.setMarkedObj(nr)
	
	def unmarObjectsWidgetList(self):#odznaczenie listy obiektow
		for nr in self.markedobjects:
			self.qgl.setUnmarkedObj(nr)
		self.markedobjects = []
	
	def addedObjWidgetList(self): #osbluga sygnalu o dodaniu nowego obiektu do sceny
		self.widgetlist.ui.listWidget.addItem(self.qgl.obj[-1].WhatAmILongTxt())
	
	def clickWidgetList(self):#obsluga klikniecia na listWidget
	#odznaecznie obiekotw
		self.unmarObjectsWidgetList()
	#odczytanie ktory obiekt ma byc zaznaczony
		nr = self.widgetlist.ui.listWidget.currentIndex().row()
		nr = nr + self.nrofconstobjt
		self.markedobjects.append(nr)
	#zaznaczenie obiektow
		self.markObjectsWidgetList()
		
	def createWidgetList(self):#stworzenie calej listy od zera
		lengthobj = len(self.qgl.obj)
		if(lengthobj > self.nrofconstobjt): #cos wiecej niz osie X,Y
			self.widgetlist.ui.listWidget.clear()
			for i in range(self.nrofconstobjt,lengthobj):
				self.widgetlist.ui.listWidget.addItem(self.qgl.obj[i].WhatAmILongTxt()) #objekty sie przedstawia w odpowiednim formacie wystarczy je dodac do listy
				
	def pushButtonUp(self): #zmiana kolejnosci obiektow 
		if(len(self.widgetlist.ui.listWidget.selectedItems()) != 0):
		#numer wybranej linii liczony od 0
			nr = self.widgetlist.ui.listWidget.currentIndex().row() 
			if(nr != 0):
				
			#zamiana w liscie
				item = self.widgetlist.ui.listWidget.item(nr-1).text()
				self.widgetlist.ui.listWidget.item(nr-1).setText(self.widgetlist.ui.listWidget.item(nr).text())
				self.widgetlist.ui.listWidget.item(nr).setText(item)
				self.widgetlist.ui.listWidget.setCurrentItem(self.widgetlist.ui.listWidget.item(nr-1))
				
			#zmiany na obiektach
				self.unmarObjectsWidgetList()
				nr = nr + self.nrofconstobjt
				self.qgl.swapObj(nr,nr-1)
				self.markedobjects.append(nr-1)
				self.markObjectsWidgetList()
		
	def pushButtonDown(self): #zmiana kolejnosci obiektow
		if(len(self.widgetlist.ui.listWidget.selectedItems()) != 0):
			nr = self.widgetlist.ui.listWidget.currentIndex().row() #numer wybranej linii liczony od 0
			if(nr != (len(self.widgetlist.ui.listWidget)-1)):
			#zamiana w liscie
				item = self.widgetlist.ui.listWidget.item(nr+1).text()
				self.widgetlist.ui.listWidget.item(nr+1).setText(self.widgetlist.ui.listWidget.item(nr).text())
				self.widgetlist.ui.listWidget.item(nr).setText(item)
				
			#zmiany na obiektach
				self.unmarObjectsWidgetList()
				nr = nr + self.nrofconstobjt
				self.qgl.swapObj(nr,nr+1)
				self.widgetlist.ui.listWidget.setCurrentItem(self.widgetlist.ui.listWidget.item(nr+1-self.nrofconstobjt))
		
	def pushButtonRemove(self): #usuwa obiekty ze sceny
		if(len(self.widgetlist.ui.listWidget.selectedItems()) != 0):
		#odczytanie indeksu zaznaczonego obiektu na liscie
			nr = self.widgetlist.ui.listWidget.currentIndex().row() #numer wybranej linii liczony od 0
		#usuniecie numeru z listy
			item = self.widgetlist.ui.listWidget.takeItem(nr)
			del item 
		#usuniecie obiektu ze sceny
			self.qgl.removeObj(nr+self.nrofconstobjt) #usuniecie obiektu ze sceny
		#zaznaczenie kolejnego obiektu na liscie
			self.clickWidgetList() 
		#odswezenie lsity
			self.createWidgetList()
		
#------------ PRZYCISKI (TOOLS) ------------#
#tool5 - linia + kat (moze bedzie do wycofania)
#tool7 - strzalki informujace o poczatku i koncu wszystkich obiektow
#tool8 - przesuwanie pkt
	def defaultToolTipStyleForButton(self,obj,txt): #domyslny styl wskazowek dla przyciskow
		html = "<font color ='purple'><b><i>" #styl htmlowy wskaozwki - otwarcie
		html = html + txt #wlozenie stylu txt do html 
		html = html + "</i></b></font>" #styl htmlowy wskaozwki - zamkniecie
		obj.setToolTip(html) #ustawienie wskazowki wraz ze stworzonym stylem
	
	def pushButtonNarz0(self): #klikniecie na obiekt
		self.qgl.setTool(0)
	
	def pushButtonNarz1(self): #linia
		self.qgl.setTool(1)
		
	def pushButtonNarz2(self): #linia-linia
		self.qgl.setTool(2)
		
	def pushButtonNarz3(self):
		self.qgl.setTool(3)
		
	def pushButtonNarz4(self): #lista
		if(self.widgetlist.isVisible() == True):
			self.widgetlist.hide()
		else:
			self.widgetlist.show()
		self.qgl.setTool(4)
		
	def pushButtonNarz5(self):
		self.qgl.setTool(5)
	
	def pushButtonNarz6(self): #zaznaczanie wielu obiektow na scenie
		self.qgl.setTool(6)
	
	def pushButtonNarz7(self):
		self.qgl.setTool(7)
		
	def pushButtonNarz8(self):
		self.qgl.setTool(8)
	
#------------ GUI XY ------------#
	def knowpoint(self,nr): #ustawienie na GUI
		if(nr == 1):
			self.widgetxy.setxpyp(self.qgl.obj[-1].xp,self.qgl.obj[-1].yp)
		elif(nr == 2):
			self.widgetxy.setxkyk(self.qgl.obj[-1].xk,self.qgl.obj[-1].yk)
	
#------------ MYSZKA ------------#
	def qglMouse(self): #wczytanie pozycji myszki na scenie i umieszczenie jej w status barze
		mousepos = self.qgl.mousepos
		mousepos = "%.4f : %.4f" % (mousepos[0], mousepos[1]) #ustawienie odpowiedniego formatu
		self.ui.statusbar.showMessage(mousepos,0) #wyswietlenie infromacji w statusbar
	
#------------ KLAWIATURA ------------#
	def keyPressEvent(self, event): #wcisniecie przycisku
		key = event.key()
		
		#-- usuwanie --#
		if(key == QtCore.Qt.Key_Delete):
			if(self.qgl.tool==0): #zaznaczony obiekt 
				self.qgl.removeObjs(self.qgl.listclicked)
				self.qgl.listclicked = []
				self.createWidgetList()
			elif(self.qgl.tool==4): #sortowanie
				self.pushButtonRemove()
		
		#-- anulowanie akacji --#
		elif(key == QtCore.Qt.Key_Escape):
			 self.qgl.cancelDraw()
			 
		#przesuwanie sceny
		elif(key == QtCore.Qt.Key_Left):
			self.qgl.changedxView(-self.dxdy)
		
		elif(key == QtCore.Qt.Key_Right):
			self.qgl.changedxView(self.dxdy)
		
		elif(key == QtCore.Qt.Key_Up):
			self.qgl.changedyView(self.dxdy)
		
		elif(key == QtCore.Qt.Key_Down):
			self.qgl.changedyView(-self.dxdy)
		
		elif(key == QtCore.Qt.Key_Shift):
			self.qgl.f_straight = True
			self.qgl.update()
			
	def keyReleaseEvent(self, event): #puszczenie przycisku
		key = event.key()
		if(key == QtCore.Qt.Key_Shift):
			self.qgl.f_straight = False
			self.qgl.update()
		
#------------ MENUBAR  - WIDOK ------------#
	def defaultView(self): #ustawia standarowy widok
		self.ui.actionPomniejsz.setEnabled(True)
		self.ui.actionPowieksz.setEnabled(True)
		self.qgl.defaultZoomView()
	
	def zoomSignal(self,signal): #dba o to czy uzytkownik moze kliknac powieksz lub pomniejsz
		if(signal == 0):
			self.ui.actionPowieksz.setEnabled(False)
		elif(signal == 1):
			self.ui.actionPomniejsz.setEnabled(False)
			
		else:
			self.ui.actionPomniejsz.setEnabled(True)
			self.ui.actionPowieksz.setEnabled(True)
	
	def ZoomInView(self): #zmienia wielkosc sceny
		self.qgl.changeZoomView(-self.zoom)
		
	def ZoomOutView(self): #zmienia wielkosc sceny
		self.qgl.changeZoomView(self.zoom)
		
#------------ MENUBAR  - EDYCJA ------------#
	def menubarBack(self): #cofnij ctrl+z
		self.qgl.previousStepJourney()
	
	def signalMenubarBack(self,i): #zablokowuje/odblokowuje przycisk cofnij
		self.ui.actionCofnij.setEnabled(i)
		
	def signalMenubarNext(self,i): #zablokowuje/odblokowuje przycisk naprzod
		self.ui.actionPonow.setEnabled(i)
	
	def menubarForward(self): #naprzod ctrl+z+shift
		self.qgl.nextStepJourney()
	
#------------ MENUBAR  - PLIK ------------#
	#--- Czy plik zapisany ---
	def FileNotSaved(self): #zmienia tytul okna gdy wystepuje taka potrzeba
		if(self.f_saved == True):
		#ustawienie tytulu okna na niezapisana
			txt = str(self.windowTitle())
			txt = "*"+txt 
			self.setWindowTitle(txt)
			self.f_saved = False 
			self.ui.actionZapisz.setEnabled(True)
			
	#--- Nowy plik ---
	def newAction(self): #nowa scena 
		if(self.f_saved == False):
			self.doYouWantToSaveFile("Czy przed stworzeniem nowego pliku chcesz zapsiac?")
		
		self.qgl.clearMysefl()
		self.fname = ""
		self.f_saved = True
		self.setWindowTitle("PyCAD")
		self.widgetlist.ui.listWidget.clear()
		self.qgl.update()

	#---Zakmniecie programu ---
	def closeEvent(self,event): #zamkniecie aplikacji - rowniez przez krzyzyk
		if(self.f_saved == False):
			self.doYouWantToSaveFile("Czy przed wyjsciem, chcesz zapisac zmiany?")
			self.f_saved = True
		self.close()
	
	#--- Zapisanie pliku ---
	def localAskDialog(self,txt): #Message box ktory pyta czy chcesz zapisac plik 
		mbox = QtGui.QMessageBox()
		
		mbox.setWindowTitle("Zapis?")
		mbox.setText(txt)
		mbox.setIcon(QtGui.QMessageBox.Warning)
		
		mbox.setStandardButtons(QtGui.QMessageBox.Yes) 
		mbox.addButton(QtGui.QMessageBox.No)
		mbox.setDefaultButton(QtGui.QMessageBox.No)
		
	#zmiana wyswietlanych napisow na przyciskach
		buttons = mbox.buttons()
		buttons[0].setText("Tak")
		buttons[1].setText("Nie")
		
		if(mbox.exec_() == QtGui.QMessageBox.Yes):
			return True
		else:
			return False
	
	def localSaveDialog(self): #dialog wywolywany do wczytania sciezki do pliku przy zapisie
		fdialog = QtGui.QFileDialog(self)
		
		#ustawienie trybu
		fdialog.setFileMode(QtGui.QFileDialog.AnyFile)
		
		#fdialog.setNameFilters(["data exchange format (*.dxf)", "downolny plik (*.*)"]) #jak dodac inne 
		fdialog.setNameFilters(["data exchange format (*.dxf)"]) #filtry do wyboru
		fdialog.selectNameFilter("data exchange format (*.dxf)") #domyslny filtr
		
		#ustawienie tekstu na polski
		fdialog.setLabelText(QtGui.QFileDialog.LookIn,"aktualny folder")
		fdialog.setLabelText(QtGui.QFileDialog.FileName,"nazwa pliku")
		fdialog.setLabelText(QtGui.QFileDialog.FileType,"rozszerzenie")
		fdialog.setLabelText(QtGui.QFileDialog.Accept,"Zapisz")
		fdialog.setLabelText(QtGui.QFileDialog.Reject,"Anuluj")
		
		#tytul oknas
		fdialog.setWindowTitle("Zapisywanie pliku")
		
		if(fdialog.exec_()):
			fname = fdialog.selectedFiles()[0]
		
		if(fdialog.result() == 1):
			
			fname = str(fname) #konwertuje na stirng pythona, bo tak wynikiem jest QString
			tmp = fname.split(".")
			
			if(tmp[-1] != "dxf"): 
				fname = fname + ".dxf"
			
			return fname
		else:
			return ""
	
	def saveFile(self): #zapisuje plik
		self.qgl.cancelDraw()
		
		if(self.fname == ""): #odczytanie sciezki do pliku
			 
			fname = self.localSaveDialog()
			
			if(fname != ""):
				self.fname = fname
		
		if(self.fname != ""):
			if(self.qgl.DXFSave(self.fname) ==  True):
				
				self.setWindowTitle(self.fname)
				self.f_saved = True
				self.ui.actionZapisz.setEnabled(False)
	
	def saveFileAs(self): #zapisz jako (korzysta z metody saveFile)
		self.qgl.cancelDraw() 
		
		fname = self.localSaveDialog()
		if(fname != ""):
			self.fname = fname
			self.saveFile()
	
	def doYouWantToSaveFile(self,txt):
		if(self.f_saved == False): #zmiany nie zapisane
			if(self.localAskDialog(txt) == True):
				if(len(self.qgl.obj) != self.qgl.howmanyignore ): #czy plik zostal wlasnie utworzony?
					self.saveFile()
	
	#--- Wczytanie pliku ---
	def localLoadDialog(self): #dialog wywolywany do wczytania sciezki do pliku przy otwieraniu pliku
		fdialog = QtGui.QFileDialog(self)
		
		#ustawienie trybu
		fdialog.setFileMode(QtGui.QFileDialog.AnyFile)
		
		#fdialog.setNameFilters(["data exchange format (*.dxf)", "downolny plik (*.*)"]) #jak dodac inne 
		fdialog.setNameFilters(["data exchange format (*.dxf)"]) #filtry do wyboru
		fdialog.selectNameFilter("data exchange format (*.dxf)") #domyslny filtr
		
		#ustawienie tekstu na polski
		fdialog.setLabelText(QtGui.QFileDialog.LookIn,"aktualny folder")
		fdialog.setLabelText(QtGui.QFileDialog.FileName,"nazwa pliku")
		fdialog.setLabelText(QtGui.QFileDialog.FileType,"rozszerzenie")
		fdialog.setLabelText(QtGui.QFileDialog.Accept,"Wczytaj")
		fdialog.setLabelText(QtGui.QFileDialog.Reject,"Anuluj")
		
		#tytul okna
		fdialog.setWindowTitle("Wczytywanie pliku")
		
		if(fdialog.exec_()):
			fname = fdialog.selectedFiles()[0]
		
		if(fdialog.result() == 1):
			fname = str(fname) #konwertuje na stirng pythona, bo tak wynikiem jest QString
			tmp = fname.split(".")
			
			if(tmp[-1] != "dxf"): #sprawdza czy znany jest format
				return ""
				
			else:
				return fname
		else:
			return ""
	
	def loadDXF(self,fname): #wczytanie pliku
		self.qgl.clearMysefl()
		result = self.qgl.DXFLoad(fname)
		
		if(result == True):
			self.fname = fname
			self.setWindowTitle(fname)
			self.f_saved = True
			QtGui.QMessageBox.information(self, 'Wczytywanie', "Plik zostal wczytany pomyslnie",QtGui.QMessageBox.Ok)
			self.createWidgetList()
			
		elif(result == False):
			self.newAction()
			QtGui.QMessageBox.information(self, 'Wczytywanie', "Wczytywanie pliku nie powiodlo sie",QtGui.QMessageBox.Ok)
	
	def loadAction(self): #wczytywanie 
		self.doYouWantToSaveFile("Czy chcesz zapisac zmiany przed otwraciem pliku")
		fname = self.localLoadDialog()
		if(fname != ""):
			self.loadDXF(fname)
	
#------------ DRAG & DROP (do wczytania) ------------#
	def loadDrop(self,fname):  #wczytanie pliku przy uzyciu drag and drop
		self.doYouWantToSaveFile("Czy chcesz zapisac zmiany przed otwraciem pliku")
		self.loadDXF(fname)
	
	def dragEnterEvent(self, event): #przesuniecie obiektu na obszar main window
		if event.mimeData().hasUrls():
			event.acceptProposedAction()
		else:
			event.ignore()
	
	def dropEvent(self, event): #po upuszczeniu obiektu zrob cos z nim
		if ( len(event.mimeData().urls()) == 1): #sprawdza czy tylko jeden plik zostal upuszczony
			url = event.mimeData().urls()[0] #konwenture liste QUrl na QUrl
			url = str(url.path()) #konwertuje Qurl na sciezke a potem na pythonoweg stringa
			tmp = url.split(".") 
			if(tmp[-1] == "dxf"): #sprawdza czy foramt to "dxf"
				self.loadDrop(url)
			else:
				event.ignore()
		else:
			event.ignore() #ignoruje drop jesli wystapi wiecej niz jeden plik