aboutsummaryrefslogtreecommitdiffstats
path: root/mageiasync/mageiasync.py
diff options
context:
space:
mode:
Diffstat (limited to 'mageiasync/mageiasync.py')
-rw-r--r--mageiasync/mageiasync.py436
1 files changed, 436 insertions, 0 deletions
diff --git a/mageiasync/mageiasync.py b/mageiasync/mageiasync.py
new file mode 100644
index 0000000..2e15151
--- /dev/null
+++ b/mageiasync/mageiasync.py
@@ -0,0 +1,436 @@
+#!/usr/bin/python3
+
+from PyQt5.QtWidgets import ( QApplication, QProgressDialog, QMainWindow,
+ QDialog, QFileDialog,)
+from PyQt5.QtGui import ( QStandardItemModel,QStandardItem, )
+from PyQt5 import QtCore # , Qt, QThread, QObject, pyqtSignal)
+import sys
+import mageiaSyncUI
+import mageiaSyncExt
+import mageiaSyncDBprefs
+import mageiaSyncDBrename
+
+
+class prefsDialog(QDialog,mageiaSyncDBprefs.Ui_prefsDialog ):
+
+ def __init__(self, parent=None):
+ QDialog.__init__(self,parent)
+ self.setupUi(self)
+ self.selectDest.clicked.connect(isosSync.selectDestination)
+
+class renameDialog(QDialog,mageiaSyncDBrename.Ui_renameDialog ):
+ # Display a dialog box to choose to rename an old collection of ISOs to a new one
+
+ def __init__(self, parent=None):
+ QDialog.__init__(self,parent)
+ self.setupUi(self)
+ self.chooseDir.clicked.connect(isosSync.renameDir)
+
+
+class LogWindow(QProgressDialog):
+ # Display a box at start during the remote directory list loading
+
+ def __init__(self, parent=None):
+ super(LogWindow, self).__init__(parent)
+ self.setWindowModality(QtCore.Qt.WindowModal)
+ self.setWindowTitle('Loading...')
+ self.setLabelText('Loading images list from repository.')
+ self.setMinimum(0)
+ self.setMaximum(0)
+ self.setAutoReset(False)
+ self.setAutoClose(False)
+ self.setMinimumDuration(1)
+
+ def perform(self):
+ self.progressDialog.setValue(self.progress)
+
+class dbWarning(QProgressDialog):
+ # Display a box at start during the remote directory list loading
+
+ def __init__(self, parent=None):
+ super(dbWarning, self).__init__(parent)
+ self.setWindowModality(QtCore.Qt.WindowModal)
+ self.setWindowTitle('Loading...')
+ self.setLabelText('Loading images list from repository.')
+ self.setMinimum(0)
+ self.setMaximum(0)
+ self.setAutoReset(False)
+ self.setAutoClose(False)
+ self.setMinimumDuration(1)
+
+ def perform(self):
+ self.progressDialog.setValue(self.progress)
+
+class IsosViewer(QMainWindow, mageiaSyncUI.Ui_mainWindow):
+ # Display the main window
+ def __init__(self, parent=None):
+ super(IsosViewer, self).__init__(parent)
+ self.setupUi(self)
+ self.connectActions()
+ self.IprogressBar.setMinimum(0)
+ self.IprogressBar.setMaximum(100)
+ self.IprogressBar.setValue(0)
+ self.IprogressBar.setEnabled(False)
+ self.selectAllState=True
+ self.stop.setEnabled(False)
+ self.destination=''
+ self.rsyncThread = mageiaSyncExt.syncThread(self) # create a thread to launch rsync
+ self.rsyncThread.progressSignal.connect(self.setProgress)
+ self.rsyncThread.speedSignal.connect(self.setSpeed)
+ self.rsyncThread.sizeSignal.connect(self.setSize)
+ self.rsyncThread.remainSignal.connect(self.setRemain)
+ self.rsyncThread.endSignal.connect(self.syncEnd)
+ self.rsyncThread.lvM.connect(self.lvMessage)
+ self.rsyncThread.checkSignal.connect(self.checks)
+ self.checkThreads=[] # A list of thread for each iso
+
+ # Model for list view in a table
+ self.model = QStandardItemModel(0, 6, self)
+ headers=["Directory","Name","Size","Date","SHA1","MD5"]
+ i=0
+ for label in headers:
+ self.model.setHeaderData(i, QtCore.Qt.Horizontal,label )
+ i+=1
+
+# settings for the list view
+ self.localList.setModel(self.model)
+ self.localList.setColumnWidth(0,220)
+ self.localList.setColumnWidth(1,220)
+ self.localList.horizontalHeader().setStretchLastSection(True)
+ # settings for local iso names management
+ self.localListNames=[]
+
+ def multiSelect(self):
+ # allows to select multiple lines in remote ISOs list
+ self.listIsos.setSelectionMode(2)
+
+ def add(self, iso):
+ # Add an remote ISO in list
+ self.listIsos.addItem(iso)
+
+ def localAdd(self, path,iso,isoSize):
+ # Add an entry in local ISOs list, with indications about checking
+ itemPath=QStandardItem(path)
+ itemIso=QStandardItem(iso)
+ if isoSize==0:
+ itemSize=QStandardItem('--')
+ else:
+ formatedSize='{:n}'.format(isoSize) #.replace(","," ")
+ itemSize=QStandardItem(formatedSize)
+ itemSize.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
+ itemDate=QStandardItem("--/--/--")
+ itemDate.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
+ itemCheck1=QStandardItem("--")
+ itemCheck1.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
+ itemCheck5=QStandardItem("--")
+ itemCheck5.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
+ self.model.appendRow([itemPath,itemIso,itemSize,itemDate, itemCheck1, itemCheck5,])
+ self.localListNames.append([path,iso])
+
+ def setProgress(self, value):
+ # Update the progress bar
+ self.IprogressBar.setValue(value)
+
+ def setSpeed(self, value):
+ # Update the speed field
+ self.speedLCD.display(value)
+
+ def setSize(self, value):
+ # Update the size field
+ self.Lsize.setText(str(value)+" bytes")
+
+ def setRemain(self,remainTime):
+ content=QtCore.QTime.fromString(remainTime,"h:mm:ss")
+ self.timeRemaining.setTime(content)
+
+ def checks(self,isoIndex):
+ # process a checking for each iso
+ # launches a thread for each iso
+ newThread=mageiaSyncExt.checkThread(self)
+ self.checkThreads.append(newThread)
+ self.checkThreads[-1].setup(self.destination,self.model.data(self.model.index(isoIndex,0)) ,self.model.data(self.model.index(isoIndex,1)),isoIndex)
+ self.checkThreads[-1].md5Signal.connect(self.md5Check)
+ self.checkThreads[-1].sha1Signal.connect(self.sha1Check)
+ self.checkThreads[-1].dateSignal.connect(self.dateCheck)
+ self.checkThreads[-1].sizeSignal.connect(self.sizeUpdate)
+ self.checkThreads[-1].checkStartSignal.connect(self.checkStart)
+ self.checkThreads[-1].start()
+
+ def checkStart(self,isoIndex):
+ # the function indicates that checking is in progress
+ # the hundred contains index of the value to check, the minor value contains the row
+ col=(int)(isoIndex/100)
+ row=isoIndex-col*100
+ self.model.setData(self.model.index(row, col, QtCore.QModelIndex()), "Checking")
+
+ def md5Check(self,check):
+ if check>=128:
+ val="OK"
+ row=check-128
+ else:
+ val="Failed"
+ row=check
+ self.model.setData(self.model.index(row, 5, QtCore.QModelIndex()), val)
+
+ def sha1Check(self,check):
+ if check>=128:
+ val="OK"
+ row=check-128
+ else:
+ val="Failed"
+ row=check
+ self.model.setData(self.model.index(row, 4, QtCore.QModelIndex()), val)
+
+ def dateCheck(self,check):
+ if check>=128:
+ val="OK"
+ row=check-128
+ else:
+ val="Failed"
+ row=check
+ self.model.setData(self.model.index(row, 3, QtCore.QModelIndex()), val)
+
+ def sizeUpdate(self,signal,isoSize):
+ col=(int)(signal/100)
+ row=signal-col*100
+ self.model.setData(self.model.index(row, col, QtCore.QModelIndex()), '{:n}'.format(isoSize))
+
+ def syncEnd(self, rc):
+ if rc==1:
+ self.lvMessage("Command rsync not found")
+ elif rc==2:
+ self.lvMessage("Error in rsync parameters")
+ elif rc==3:
+ self.lvMessage("Unknown error in rsync")
+ self.IprogressBar.setEnabled(False)
+ self.syncGo.setEnabled(True)
+ self.listIsos.setEnabled(True)
+ self.selectAll.setEnabled(True)
+ self.stop.setEnabled(False)
+
+ def prefsInit(self):
+ # Load the parameters at first
+ params=QtCore.QSettings("Mageia","mageiaSync")
+ try:
+ # the parameters already initilised?
+ self.user=params.value("user", type="QString")
+ except:
+ # Values are not yet set
+ self.pd=prefsDialog()
+ # Set values which are already defined
+ try:
+ self.pd.release.setText(params.value("release", type="QString"))
+ except:
+ pass
+ try:
+ self.pd.password.setText(params.value("password", type="QString"))
+ except:
+ pass
+ try:
+ self.pd.location.setText(params.value("location", type="QString"))
+ except:
+ pass
+ try:
+ self.pd.selectDest.setText(params.value("destination", type="QString"))
+ except:
+ self.pd.selectDest.setText(QtCore.QDir.currentPath())
+ try:
+ self.pd.bwl.setText(params.value("bwl", type="QInt"))
+ except:
+ pass
+ try:
+ self.pd.password.setText(params.value("password", type="QString"))
+ except:
+ pass
+ answer=self.pd.exec_()
+ if answer:
+ # Update params
+ params=QtCore.QSettings("Mageia","mageiaSync")
+ params.setValue("release", self.pd.release.text())
+ params.setValue("user",self.pd.user.text())
+ params.setValue("password",self.pd.password.text())
+ params.setValue("location",self.pd.location.text())
+ params.setValue("destination",self.pd.selectDest.text())
+ params.setValue("bwl",str(self.pd.bwl.value()))
+ self.user=self.pd.user.text()
+ else:
+ pass
+# answer=QDialogButtonBox(QDialogButtonBox.Ok)
+ # the user must set values or default values
+ self.pd.close()
+ self.release=params.value("release", type="QString")
+ self.location=params.value("location", type="QString")
+ self.password=params.value("password", type="QString")
+ self.destination=params.value("destination", type="QString")
+ self.bwl=params.value("bwl",type=int)
+ self.localDirLabel.setText("Local directory: "+self.destination)
+ if self.location !="":
+ self.remoteDirLabel.setText("Remote directory: "+self.location)
+
+ def selectDestination(self):
+ # dialog box to select the destination (local directory)
+ directory = QFileDialog.getExistingDirectory(self, 'Select a directory','~/')
+ isosSync.destination = directory
+ self.pd.selectDest.setText(isosSync.destination)
+
+
+ def selectAllIsos(self):
+ # Select or unselect the ISOs in remote list
+ if self.selectAllState :
+ for i in range(self.listIsos.count()):
+ self.listIsos.item(i).setSelected(True)
+ self.selectAll.setText("Unselect all")
+ else:
+ for i in range(self.listIsos.count()):
+ self.listIsos.item(i).setSelected(False)
+ self.selectAll.setText("Select all")
+ self.selectAllState=not self.selectAllState
+
+ def connectActions(self):
+ self.actionQuit.triggered.connect(app.quit)
+ self.actionRename.triggered.connect(self.rename)
+ self.actionUpdate.triggered.connect(self.updateList)
+ self.actionPreferences.triggered.connect(self.prefs)
+ self.syncGo.clicked.connect(self.launchSync)
+ self.selectAll.clicked.connect(self.selectAllIsos)
+
+ def updateList(self):
+ # From the menu entry
+ self.lw = LogWindow()
+ self.lw.show()
+ self.listIsos.clear()
+ self.model.removeRows(0,self.model.rowCount())
+ if self.location == "" :
+ self.nameWithPath='rsync://'+self.user+'@bcd.mageia.org/isos/'+self.release+'/'
+ print self.nameWithPath
+ else:
+ self.nameWithPath=self.location+'/'
+ self.fillList = mageiaSyncExt.findIsos()
+ self.fillList.setup(self.nameWithPath, self.password,self.destination)
+ self.fillList.endSignal.connect(self.closeFill)
+ self.fillList.start()
+
+ def lvMessage( self,message):
+ # Add a line in the logview
+ self.lvText.append(message)
+
+ def renameDir(self):
+ # Choose the directory where isos are stored
+ directory = QFileDialog.getExistingDirectory(self, 'Select a directory',self.destination)
+ self.rd.chooseDir.setText(directory)
+
+ def rename(self):
+ # rename old isos and directories to a new release
+ self.rd=renameDialog()
+ loc=[]
+ loc=self.location.split('/')
+ self.rd.oldRelease.setText(loc[-1])
+ self.rd.newRelease.setText(loc[-1])
+ self.rd.chooseDir.setText(self.location)
+ answer=self.rd.exec_()
+ if answer:
+ returnMsg=mageiaSyncExt.rename(self.rd.chooseDir.text(),self.rd.oldRelease.text(),self.rd.newRelease.text())
+ self.lvMessage(returnMsg)
+ self.rd.close()
+
+ def prefs(self):
+ # From the menu entry
+ self.pd=prefsDialog()
+ self.pd.release.setText(self.release)
+ self.pd.password.setText(self.password)
+ self.pd.user.setText(self.user)
+ self.pd.location.setText(self.location)
+ self.pd.selectDest.setText(self.destination)
+ self.pd.bwl.setValue(self.bwl)
+ params=QtCore.QSettings("Mageia","mageiaSync")
+ answer=self.pd.exec_()
+ if answer:
+ params.setValue("release", self.pd.release.text())
+ params.setValue("user",self.pd.user.text())
+ params.setValue("password",self.pd.password.text())
+ params.setValue("location",self.pd.location.text())
+ params.setValue("destination",self.pd.selectDest.text())
+ params.setValue("bwl",str(self.pd.bwl.value()))
+ self.prefsInit()
+ self.pd.close()
+
+
+ def launchSync(self):
+ self.IprogressBar.setEnabled(True)
+ self.stop.setEnabled(True)
+ self.syncGo.setEnabled(False)
+ self.listIsos.setEnabled(False)
+ self.selectAll.setEnabled(False)
+ # Connect the button Stop
+ self.stop.clicked.connect(self.stopSync)
+ self.rsyncThread.params(self.password, self.bwl)
+ for iso in self.listIsos.selectedItems():
+ path,name=iso.text().split('/')
+ try:
+ # Look for ISO in local list
+ item=self.model.findItems(name,QtCore.Qt.MatchExactly,1)[0]
+ except:
+ # Remote ISO is not yet in local directory. We add it in localList and create the directory
+ self.localAdd(path,name,0)
+ basedir=QtCore.QDir(self.destination)
+ basedir.mkdir(path)
+ item=self.model.findItems(name,QtCore.Qt.MatchExactly,1)[0]
+ row=self.model.indexFromItem(item).row()
+ if self.location == "" :
+ self.nameWithPath='rsync://'+self.user+'@bcd.mageia.org/isos/'+self.release+'/'+path
+ else:
+ self.nameWithPath=self.location+path
+ if (not str(path).endswith('/')):
+ self.nameWithPath+='/'
+ self.rsyncThread.setup(self.nameWithPath, self.destination+'/'+path+'/',row)
+ self.rsyncThread.start() # start the thread
+ # Pour les tests uniquement
+ #rsync://$user@bcd.mageia.org/isos/$release/
+ #self.nameWithPath='rsync://ftp5.gwdg.de/pub/linux/mageia/iso/4.1/Mageia-4.1-LiveCD-GNOME-en-i586-CD/'
+
+ def closeFill(self,code):
+ if code==0: # list returned
+ list=self.fillList.getList()
+ for iso in list:
+ self.add(iso)
+ elif code==1:
+ self.lvMessage("Command rsync not found")
+ elif code==2:
+ self.lvMessage("Error in rsync parameters")
+ elif code==3:
+ self.lvMessage("Unknown error in rsync")
+ list=self.fillList.getList()
+
+ list=self.fillList.getLocal()
+ for path,iso,isoSize in list:
+ self.localAdd(path,iso, isoSize)
+ self.fillList.quit()
+ self.lw.hide()
+
+ def stopSync(self):
+ self.rsyncThread.stop()
+ self.IprogressBar.setEnabled(False)
+ self.stop.setEnabled(False)
+ self.syncGo.setEnabled(True)
+ self.listIsos.setEnabled(True)
+ self.selectAll.setEnabled(True)
+
+
+ def main(self):
+ self.show()
+ # Load or look for intitial parameters
+ self.prefsInit()
+ # look for Isos list and add it to the isoSync list. Update preferences
+ self.updateList()
+ self.multiSelect()
+
+ def close(self):
+ self.rsyncThread.stop()
+ exit(0)
+
+
+if __name__=='__main__':
+ app = QApplication(sys.argv)
+ isosSync = IsosViewer()
+ isosSync.main()
+ sys.exit(app.exec_())