123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- import slicerNetwork
- import slicer
- import qt
- import ctk
- import json
- import os
- import shutil
- class fileIO(slicer.ScriptedLoadableModule.ScriptedLoadableModule):
- def __init__(self,parent):
- slicer.ScriptedLoadableModule.ScriptedLoadableModule.__init__(self, parent)
- self.className="fileIO"
- self.parent.title="fileIO"
- self.parent.categories = ["LabKey"]
- self.parent.dependencies = []
- self.parent.contributors = ["Andrej Studen (UL/FMF)"] # replace with "Firstname Lastname (Organization)"
- self.parent.helpText = """
- File IO for Labkey interface to slicer
- """
- self.parent.acknowledgementText = """
- Developed within the medical physics research programme of the Slovenian research agency.
- """ # replace with organization, grant and thanks.
- class remoteFileSelector(qt.QMainWindow):
- def __init__(self, parent=None):
- super(remoteFileSelector, self).__init__(parent)
- self.setup()
- def setMaster(self,master):
- self.master=master
- def setup(self):
- centralWidget=qt.QWidget(self)
- fileDialogFormLayout = qt.QFormLayout(centralWidget)
- #self.layout.addWidget(fileDialogFormLayout)
- #add item list for each found file/directory
- self.fileList=qt.QListWidget()
- self.fileList.toolTip="Select remote file"
- self.fileList.itemDoubleClicked.connect(self.onFileListDoubleClicked)
- self.currentRelativeDir=''
- #add dummy entry
- items=('.','..')
- self.populateFileList(items)
- fileDialogFormLayout.addWidget(self.fileList)
- self.selectedPath=qt.QLineEdit("")
- self.selectedPath.toolTip="Selected path"
- fileDialogFormLayout.addRow("Selected path :",self.selectedPath)
- self.closeButton=qt.QPushButton("Close")
- self.closeButton.toolTip="Close"
- self.closeButton.connect('clicked(bool)',self.onCloseButtonClicked)
- fileDialogFormLayout.addRow(self.closeButton)
- self.setCentralWidget(centralWidget);
- def onFileListDoubleClicked(self,item):
- if item == None:
- print("Selected items: None")
- return
- iText=item.text()
- print ("Selected items: {0} ").format(iText)
- #this is hard -> compose path string from currentRelativeDir and selection
- if item.text().find('..')==0:
- #one up
- idx=self.currentRelativeDir.rfind('/')
- if idx<0:
- self.currentRelativeDir=''
- else:
- self.currentRelativeDir=self.currentRelativeDir[:idx]
- elif item.text().find('.')==0:
- pass
- else:
- if len(self.currentRelativeDir)>0:
- self.currentRelativeDir+='/'
- self.currentRelativeDir+=item.text()
- print ("Listing {0}").format(self.currentRelativeDir)
- flist=self.master.network.toRelativePath(
- self.master.network.listRelativeDir(self.currentRelativeDir))
- print ("Got")
- print (flist)
- flist.insert(0,'..')
- flist.insert(0,'.')
- self.populateFileList(flist)
- self.selectedPath.setText(self.currentRelativeDir)
- self.master.remotePath.setText(self.master.network.GetLabkeyPathFromRelativePath(self.currentRelativeDir))
- def populateFileList(self,items):
- self.fileList.clear()
- for it_text in items:
- item=qt.QListWidgetItem(self.fileList)
- item.setText(it_text)
- item.setIcon(qt.QIcon(it_text))
- def onCloseButtonClicked(self):
- self.hide()
- class fileIOWidget(slicer.ScriptedLoadableModule.ScriptedLoadableModuleWidget):
- def __init__(self,parent):
- slicer.ScriptedLoadableModule.ScriptedLoadableModuleWidget.__init__(self, parent)
- self.selectRemote=remoteFileSelector()
- #self.selectLocal=qt.QFileDialog()
- #self.selectLocal.connect('fileSelected(QString)',self.onLocalFileSelected)
- self.selectRemote.setMaster(self)
- self.network=slicerNetwork.labkeyURIHandler()
- def setup(self):
- connectionCollapsibleButton = ctk.ctkCollapsibleButton()
- connectionCollapsibleButton.text = "Connection"
- self.layout.addWidget(connectionCollapsibleButton)
- connectionFormLayout = qt.QFormLayout(connectionCollapsibleButton)
- self.loadConfigButton=qt.QPushButton("Load configuration")
- self.loadConfigButton.toolTip="Load configuration"
- self.loadConfigButton.connect('clicked(bool)',self.onLoadConfigButtonClicked)
- connectionFormLayout.addRow("Connection:",self.loadConfigButton)
- fileDialogCollapsibleButton = ctk.ctkCollapsibleButton()
- fileDialogCollapsibleButton.text = "Paths"
- self.layout.addWidget(fileDialogCollapsibleButton)
- fileDialogFormLayout = qt.QFormLayout(fileDialogCollapsibleButton)
- self.listRemoteButton=qt.QPushButton("List Remote")
- self.listRemoteButton.toolTip="List Remote"
- self.listRemoteButton.connect('clicked(bool)',self.onListRemoteButtonClicked)
- fileDialogFormLayout.addRow(self.listRemoteButton)
- self.listLocalButton=qt.QPushButton("List Local")
- self.listLocalButton.toolTip="List Local"
- self.listLocalButton.connect('clicked(bool)',self.onListLocalButtonClicked)
- fileDialogFormLayout.addRow(self.listLocalButton)
- #add selected file display
- self.remotePath=qt.QLineEdit("")
- self.remotePath.toolTip="Remote path"
- fileDialogFormLayout.addRow("RemotePath :",self.remotePath)
- self.localPath=qt.QLineEdit("")
- self.localPath.toolTip="Local path"
- fileDialogFormLayout.addRow("LocalPath :",self.localPath)
- copyToRemoteButton=qt.QPushButton("Local->Remote")
- copyToRemoteButton.toolTip="Local -> Remote"
- copyToRemoteButton.connect('clicked(bool)',self.onCopyToRemoteButtonClicked)
- fileDialogFormLayout.addRow(copyToRemoteButton)
- copyToLocalButton=qt.QPushButton("Remote -> Local")
- copyToLocalButton.toolTip="Remote -> Local"
- copyToLocalButton.connect('clicked(bool)',self.onCopyToLocalButtonClicked)
- fileDialogFormLayout.addRow(copyToLocalButton)
- removeRemoteButton=qt.QPushButton("Remove remote")
- removeRemoteButton.toolTip="Remove Remote"
- removeRemoteButton.connect('clicked(bool)',self.onRemoveRemoteButtonClicked)
- fileDialogFormLayout.addRow(removeRemoteButton)
- mkdirRemoteButton=qt.QPushButton("Mkdir remote")
- mkdirRemoteButton.toolTip="Mkdir Remote"
- mkdirRemoteButton.connect('clicked(bool)',self.onMkdirRemoteButtonClicked)
- fileDialogFormLayout.addRow(mkdirRemoteButton)
- def onListLocalButtonClicked(self):
- self.localPath.setText(qt.QFileDialog.getOpenFileName(None,"Select local"))
- def onListRemoteButtonClicked(self):
- self.selectRemote.show()
- def onLoadConfigButtonClicked(self):
- filename=qt.QFileDialog.getOpenFileName(None,'Open configuration file (JSON)',
- '.', '*.json')
- with open(filename,'r') as f:
- dt=json.load(f)
- if dt.has_key('host'):
- self.network.hostname=dt['host']
- if dt.has_key('SSL'):
- self.network.configureSSL(dt['SSL']['user'],dt['SSL']['key'],
- dt['SSL']['keyPwd'],dt['SSL']['ca'])
- if dt.has_key('labkey'):
- if dt['labkey'].has_key('user'):
- self.network.auth_name=dt['labkey']['user']
- if dt['labkey'].has_key('password'):
- self.network.auth_pass=dt['labkey']['password']
- self.loadConfigButton.setText(os.path.basename(filename))
- self.network.initRemote()
- def copyLocalToRemote(self,localPath,remotePath):
- if os.path.isfile(localPath):
- #end recursion
- print ("Copy {} to {}").format(localPath,remotePath)
- self.network.copyLocalFileToRemote(localPath,remotePath)
- return
- dirName=os.path.basename(os.path.normpath(localPath))
- remotePath+='/'+dirName
- if not self.network.isRemoteDir(remotePath):
- self.network.mkdir(remotePath+'/')
- for f in os.listdir(localPath):
- #enter recursion
- localfile=os.path.join(localPath,f)
- self.copyLocalFileToRemote(localfile,remotePath)
- def copyRemoteToLocal(self,localPath,remotePath):
- ok,files=self.network.listRemoteDir(remotePath)
- if not ok:
- print('Troubles getting remote dir content for {}'.\
- format(remotePath))
- return
- #remove trailing slash
- for f in files:
- if f[-1]=='/':
- f=f[:-1]
- bf=f[f.rfind('/')+1:]
- dirUrl=self.network.GetLabkeyWebdavUrl()+"/"+f
- if self.network.isDir(dirUrl):
- lp=os.path.join(localPath,bf)
- if not os.path.isdir(lp):
- os.mkdir(lp)
- print('Creating {}'.format(lp))
- print('Copying directory {} to {}'.format(f,lp))
- self.copyRemoteToLocal(lp,f)
- else:
- rf=self.network.readFile(f)
- fout=os.path.join(localPath,bf)
- print('Copying file {} to {}'.format(f,fout))
- with open (fout, 'w') as fd:
- rf.seek (0)
- shutil.copyfileobj (rf, fd)
- fd.close()
- def onCopyToRemoteButtonClicked(self):
- self.copyLocalFileToRemote(self.localPath.text,self.remotePath.text)
- def onCopyToLocalButtonClicked(self):
- self.copyRemoteToLocal(self.localPath.text,self.remotePath.text)
- def onRemoveRemoteButtonClicked(self):
- remotePath=self.remotePath.text
- if self.network.isRemoteDir(remotePath):
- resp=qt.QMessageBox.question(None,'Delete directory',
- 'Do you want to delete directory {}'.format(remotePath))
- if resp == qt.QMessageBox.No:
- return
- self.network.rmdir(remotePath)
- def onMkdirRemoteButtonClicked(self):
- remotePath=self.remotePath.text
- self.network.mkdir(remotePath)
- class fileIOLogic(slicer.ScriptedLoadableModule.ScriptedLoadableModuleLogic):
- def __init__(self,parent):
- slicer.ScriptedLoadableModule.ScriptedLoadableModuleLogic.__init__(self, parent)
- class fileIOTest(slicer.ScriptedLoadableModule.ScriptedLoadableModuleTest):
- """
- This is the test case for your scripted module.
- Uses ScriptedLoadableModuleTest base class, available at:
- https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
- """
- def setUp(self):
- """ Do whatever is needed to reset the state - typically a scene clear will be enough.
- """
- slicer.mrmlScene.Clear(0)
- def runTest(self):
- """Run as few or as many tests as needed here.
- """
- self.setUp()
- self.test_fileIO()
- def test_fileIO(self):
- """ Ideally you should have several levels of tests. At the lowest level
- tests should exercise the functionality of the logic with different inputs
- (both valid andclass dataExplorerTest(ScriptedLoadableModuleTest):
- """
- pass
|