Files
linuxcncAllWasm/share/qtvcp/panels/copy/copy_handler.py
2026-08-20 06:17:39 +08:00

408 lines
15 KiB
Python

############################
# **** IMPORT SECTION **** #
############################
import sys
import os
import shutil
from qtpy.QtCore import *
from qtpy.QtGui import *
from qtpy.QtWidgets import *
from qtvcp.widgets.file_manager import FileManager as FM
from qtvcp.core import Info
###########################################
# **** instantiate libraries section **** #
###########################################
INFO = Info()
###################################
# **** HANDLER CLASS SECTION **** #
###################################
class HandlerClass:
########################
# **** INITIALIZE **** #
########################
# widgets allows access to widgets from the qtvcp files
# at this point the widgets and hal pins are not instantiated
def __init__(self, halcomp,widgets,paths):
self.w = widgets
self.paths = paths
self.help = HelpDialog()
##########################################
# Special Functions called from QTVCP
##########################################
# at this point:
# the widgets are instantiated.
# the HAL pins are built but HAL is not set ready
def initialized__(self):
self.w.setWindowTitle(' QtVCP Builtin Screen Code Copier')
self.w.filemanager.showList(True)
self.w.filemanager.model.setNameFilters([''])
self.w.filemanager.cb.hide()
self.w.filemanager.addButton.hide()
self.w.filemanager.delButton.hide()
self.w.filemanager.loadButton.hide()
self.w.filemanager.copy_control.hide()
self.w.filemanager.user_path = os.path.expanduser('~/linuxcnc/configs')
if os.path.exists(self.paths.RIPCONFIGDIR):
self.w.filemanager._jumpList.update([('RIP',self.paths.RIPCONFIGDIR)])
self.w.filemanager.addAction('RIP')
self.w.filemanager._jumpList.update([('Desktop',os.path.expanduser('~/Desktop'))])
self.w.filemanager.addAction('Desktop')
self.w.filemanager.updateDirectoryView(self.w.filemanager.user_path)
self.list_screen_files()
self.w.comboBox.currentIndexChanged.connect(self.selectionchange)
self.w.lineEdit.setText(self.w.comboBox.currentText())
########################
# callbacks #
########################
def selectionchange(self,i):
self.w.lineEdit.setText(self.w.comboBox.currentText())
#######################
# callbacks from form #
#######################
def applyClicked(self):
basename = self.w.lineEdit.text()
if basename == '': basename = self.w.comboBox.currentText()
# VCP panel
if self.w.radiobutton_vcp.isChecked():
path = os.path.join(self.paths.PANELDIR, self.w.comboBox.currentText())
# vismach
elif self.w.radiobutton_vismach.isChecked():
self.copyVismachFiles(self.paths.VISMACHDIR, self.w.filemanager.textLine.text(),
basename, self.w.comboBox.currentText() )
# check for vismach object directory
objname = self.w.comboBox.currentText().strip('.py')
objname = objname + '_obj'
objpath = os.path.join(self.paths.VISMACHDIR, objname)
objbasename = basename.strip('.py') + '_obj'
if os.path.exists(objpath):
self.copyVismachFiles(self.paths.VISMACHDIR, self.w.filemanager.textLine.text(),
objbasename, objname )
return
# screen
else:
path = os.path.join(self.paths.SCREENDIR, self.w.comboBox.currentText())
self.copyFilesWithCheck(path, self.w.filemanager.textLine.text(),
basename, self.w.comboBox.currentText() )
def updateCombo(self, value):
rbtn = self.w.sender()
if rbtn.isChecked() == True:
self.w.groupBoxType.setEnabled(False)
if rbtn == self.w.radiobutton_vcp:
self.list_vcp_files()
elif rbtn == self.w.radiobutton_vismach:
self.list_vismach_files()
else:
self.list_screen_files()
self.w.groupBoxType.setEnabled(True)
def helpClicked(self):
self.help.showDialog()
#####################
# general functions #
#####################
def list_screen_files(self):
self.w.comboBox.clear()
for i in sorted(self.paths.find_screen_dirs()):
self.w.comboBox.addItem(i)
def list_vcp_files(self):
self.w.comboBox.clear()
for i in sorted(self.paths.find_panel_dirs()):
self.w.comboBox.addItem(i)
def list_vismach_files(self):
self.w.comboBox.clear()
for i in sorted(self.paths.find_vismach_files()):
if '.py' in i:
self.w.comboBox.addItem(i)
def makedirs(self, dest):
if not os.path.exists(dest):
os.makedirs(dest)
def copyVismachFiles(self, src, dest, baseName, fileName):
rtn = self.confirmDialog(dest, baseName)
if not rtn: return
fromPath = os.path.join(src, fileName)
toPath = os.path.join(dest, baseName)
# make any needed directory
if not os.path.exists(os.path.dirname(toPath)):
self.makedirs(os.path.dirname(toPath))
if not os.path.exists(toPath):
if os.path.isfile(fromPath):
shutil.copy(fromPath, toPath)
# probably vismach object folder
elif os.path.isdir(fromPath):
shutil.copytree(fromPath, toPath)
def copyFilesWithCheck(self, src, dest, baseName, srcDirName):
# make a copy of the user pick destination path
ndest = os.path.join(dest)
# check for lack of standard folders in path
folder = ''
if self.w.radiobutton_vcp.isChecked():
folder = 'panels'
elif self.w.radiobutton_screen.isChecked():
folder = 'screens'
if not folder in dest:
r = self.confirmPathDialog('qtvcp/' + folder)
if r:
if not 'qtvcp' in dest:
dest = os.path.join(dest, 'qtvcp')
if not folder in dest:
dest = os.path.join(dest, folder)
# overwrite with the new path
ndest = dest
if os.path.exists(dest):
self.w.filemanager.updateDirectoryView(dest)
# confirm user wants to copy
rtn = self.confirmDialog(ndest, baseName)
if not rtn: return
# add in the basename
ndest = os.path.join(ndest, baseName)
# make any needed initial directory
if not os.path.exists(os.path.dirname(ndest)):
self.makedirs(os.path.dirname(ndest))
# update the file manager path
if os.path.exists(dest):
self.w.filemanager.updateDirectoryView(dest)
# walk the folder and copy everything
for path, dirs, filenames in os.walk(src):
if dirs == []:
destDir = path.replace(src,ndest)
self.makedirs(destDir)
else:
for directory in dirs:
destDir = path.replace(src,ndest)
self.makedirs(os.path.join(destDir, directory))
# files
for sfile in filenames:
if sfile == 'resources.py': continue
# if source directory name is in file name, rename it.
if srcDirName in os.path.splitext(sfile)[0]:
dfile = sfile.replace(srcDirName, baseName)
else:
dfile = sfile
# use original or subclassed handler?
if self.w.checkBoxSubclassHandler.isChecked() and self.w.radiobutton_screen.isChecked():
if not '_handler.py' in sfile and not '.ui' in sfile:
continue
if '_handler.py' in sfile:
# substitute subclass handler.py for original handler
here = os.path.dirname(os.path.realpath(__file__))
srcFile = os.path.join(here, 'subclass_handler.py')
destFile = os.path.join(path.replace(src, ndest), dfile)
shutil.copy(srcFile, destFile)
continue
srcFile = os.path.join(path, sfile)
destFile = os.path.join(path.replace(src, ndest), dfile)
shutil.copy(srcFile, destFile)
# last confirm before copying -check for file overwriting
def confirmDialog(self, srcPath, name):
dest = os.path.join(srcPath, name)
info = 'Copy {} Code?'.format(name)
if os.path.exists(dest):
title = "Confirm: Will Overwrite Existing Files!"
else:
title = 'Please Confirm:'
rtn = self.w.messageDialog_.showdialog(
title,
more_info=info,
details=' To Folder:\n {}'.format(dest),
display_type='YESNO',
icon=QMessageBox.Information, pinname=None,
focus_text=None,
focus_color=None,
play_alert=None,
nblock=False,
use_exec =True)
if not rtn:
return False
return True
# confirm that qtvcp/screens or panels is not needed in path
def confirmPathDialog(self, srcPath):
dest = os.path.join(srcPath)
info = "Destination does not have {} folders in path. This is the usual way for qtvcp to find them. Do you wish to add the folders".format(srcPath)
title = 'Add {} to Path?'.format(srcPath)
rtn = self.w.messageDialog_.showdialog(
title,
more_info=info,
details=' To Folder:\n {}'.format(dest),
display_type='YESNO',
icon=QMessageBox.Information, pinname=None,
focus_text=None,
focus_color=None,
play_alert=None,
nblock=False,
use_exec =True)
if not rtn:
return False
return True
class HelpDialog(QDialog):
def __init__(self, parent=None):
super(HelpDialog, self).__init__(parent)
self._title = 'Copy Help'
self.setWindowFlags(self.windowFlags() | Qt.Tool |
Qt.Dialog | Qt.WindowStaysOnTopHint |
Qt.WindowSystemMenuHint)
self.currentHelpPage=-1
self.setMinimumWidth(400)
self.setMinimumHeight(400)
self.helpPages = ['copy_help1.html','copy_help2.html',
'copy_help3.html', 'copy_help4.html']
self.buildWidget()
def buildWidget(self):
l = QVBoxLayout()
t = QTextEdit('Qtvcp Copy Help')
t.setReadOnly(True)
l.addWidget(t)
buttons = QDialogButtonBox()
closebutton = QPushButton()
closebutton.setIconSize(QSize(38, 38))
closebutton.setIcon(QIcon(':/qt-project.org/styles/commonstyle/images/standardbutton-cancel-128.png'))
closebutton.clicked.connect(lambda : self.close())
nextbutton = QPushButton()
nextbutton.setIconSize(QSize(38, 38))
nextbutton.setIcon(QIcon(':/qt-project.org/styles/commonstyle/images/right-32.png'))
nextbutton.clicked.connect(lambda : self.next(t,True))
previousbutton = QPushButton()
previousbutton.setIconSize(QSize(38, 38))
previousbutton.setIcon(QIcon(':/qt-project.org/styles/commonstyle/images/left-32.png'))
previousbutton.clicked.connect(lambda : self.next(t,False))
self.pageStepUpbutton = QPushButton()
self.pageStepUpbutton.setIconSize(QSize(38, 38))
self.pageStepUpbutton.setIcon(QIcon(':/qt-project.org/styles/commonstyle/images/up-32.png'))
self.pageStepUpbutton.clicked.connect(lambda : self.pageStep(t,False))
self.pageStepDwnbutton = QPushButton()
self.pageStepDwnbutton.setIconSize(QSize(38, 38))
self.pageStepDwnbutton.setIcon(QIcon(':/qt-project.org/styles/commonstyle/images/down-32.png'))
self.pageStepDwnbutton.clicked.connect(lambda : self.pageStep(t,True))
bBox = QDialogButtonBox(buttons)
#bBox.addButton(self.pageStepUpbutton, QDialogButtonBox.ActionRole)
#bBox.addButton(self.pageStepDwnbutton, QDialogButtonBox.ActionRole)
bBox.addButton(previousbutton, QDialogButtonBox.ActionRole)
bBox.addButton(nextbutton, QDialogButtonBox.ActionRole)
bBox.addButton(closebutton, QDialogButtonBox.DestructiveRole)
bBox.rejected.connect(self.reject)
l.addWidget(bBox)
self.setLayout(l)
try:
self.next(t)
except Exception as e:
t.setText('Qtvcp Copy Help file Unavailable:\n\n{}'.format(e))
def next(self,t,direction=None):
if direction is None:
self.currentHelpPage = 0
elif direction:
self.currentHelpPage +=1
if self.currentHelpPage > len(self.helpPages)-1:
self.currentHelpPage = len(self.helpPages)-1
else:
self.currentHelpPage -=1
if self.currentHelpPage < 0:
self.currentHelpPage = 0
try:
pagePath = os.path.join( os.path.dirname(__file__), self.helpPages[self.currentHelpPage])
file = QFile(pagePath)
file.open(QFile.ReadOnly)
html = file.readAll()
html = str(html, encoding='utf8')
html = html.replace("../images/probe_icons/","{}/probe_icons/".format(INFO.IMAGE_PATH))
t.setHtml(html)
if t.verticalScrollBar().isVisible():
t.verticalScrollBar().setPageStep(20)
self.pageStepDwnbutton.show()
self.pageStepUpbutton.show()
else:
self.pageStepDwnbutton.hide()
self.pageStepUpbutton.hide()
except Exception as e:
t.setText('Qtvcp Copy file Unavailable:\n\n{}'.format(e))
if direction is None:
return
self.show()
def pageStep(self, t, state):
if state:
t.verticalScrollBar().triggerAction (QAbstractSlider.SliderPageStepAdd)
else:
t.verticalScrollBar().triggerAction (QAbstractSlider.SliderPageStepSub)
def showDialog(self):
self.setWindowTitle(self._title);
retval = self.exec_()
#####################
# KEY BINDING CALLS #
#####################
###########################
# **** closing event **** #
###########################
##############################
# required class boiler code #
##############################
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
################################
# required handler boiler code #
################################
def get_handlers(halcomp,widgets,paths):
return [HandlerClass(halcomp,widgets,paths)]