############################ # **** 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)]