From 9a449b9ca39fa2857eede22a220b506e02fba707 Mon Sep 17 00:00:00 2001 From: SARL ENR-68 Date: Sat, 20 Sep 2014 18:08:10 +0200 Subject: Merge branch local 'master' of david.david - rename folder 'mageiaSync' instead of 'mageiasync' - fix setup.py file - fix spec file - add a CHANGELOG file --- mageiaSync/__init__.py | 0 mageiaSync/mageiaSyncDBprefs.py | 110 ++++++++++ mageiaSync/mageiaSyncDBprefs.pyc | Bin 0 -> 4914 bytes mageiaSync/mageiaSyncDBprefs.ui | 237 +++++++++++++++++++++ mageiaSync/mageiaSyncDBrename.py | 69 ++++++ mageiaSync/mageiaSyncDBrename.pyc | Bin 0 -> 3144 bytes mageiaSync/mageiaSyncDBrename.ui | 143 +++++++++++++ mageiaSync/mageiaSyncDBupdate.py | 37 ++++ mageiaSync/mageiaSyncDBupdate.ui | 47 +++++ mageiaSync/mageiaSyncExt.py | 318 ++++++++++++++++++++++++++++ mageiaSync/mageiaSyncExt.pyc | Bin 0 -> 11006 bytes mageiaSync/mageiaSyncUI.py | 148 +++++++++++++ mageiaSync/mageiaSyncUI.pyc | Bin 0 -> 5878 bytes mageiaSync/mageiaSyncUI.ui | 250 ++++++++++++++++++++++ mageiaSync/mageiasync.py | 427 ++++++++++++++++++++++++++++++++++++++ 15 files changed, 1786 insertions(+) create mode 100644 mageiaSync/__init__.py create mode 100644 mageiaSync/mageiaSyncDBprefs.py create mode 100644 mageiaSync/mageiaSyncDBprefs.pyc create mode 100644 mageiaSync/mageiaSyncDBprefs.ui create mode 100644 mageiaSync/mageiaSyncDBrename.py create mode 100644 mageiaSync/mageiaSyncDBrename.pyc create mode 100644 mageiaSync/mageiaSyncDBrename.ui create mode 100644 mageiaSync/mageiaSyncDBupdate.py create mode 100644 mageiaSync/mageiaSyncDBupdate.ui create mode 100644 mageiaSync/mageiaSyncExt.py create mode 100644 mageiaSync/mageiaSyncExt.pyc create mode 100644 mageiaSync/mageiaSyncUI.py create mode 100644 mageiaSync/mageiaSyncUI.pyc create mode 100644 mageiaSync/mageiaSyncUI.ui create mode 100644 mageiaSync/mageiasync.py (limited to 'mageiaSync') diff --git a/mageiaSync/__init__.py b/mageiaSync/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mageiaSync/mageiaSyncDBprefs.py b/mageiaSync/mageiaSyncDBprefs.py new file mode 100644 index 0000000..7a7bcec --- /dev/null +++ b/mageiaSync/mageiaSyncDBprefs.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'mageiaSyncDBprefs.ui' +# +# Created: Fri Aug 29 10:56:43 2014 +# by: PyQt5 UI code generator 5.1.1 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_prefsDialog(object): + def setupUi(self, prefsDialog): + prefsDialog.setObjectName("prefsDialog") + prefsDialog.resize(520, 234) + self.buttonBox = QtWidgets.QDialogButtonBox(prefsDialog) + self.buttonBox.setGeometry(QtCore.QRect(10, 200, 511, 32)) + self.buttonBox.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) + self.buttonBox.setCenterButtons(True) + self.buttonBox.setObjectName("buttonBox") + self.formLayoutWidget = QtWidgets.QWidget(prefsDialog) + self.formLayoutWidget.setGeometry(QtCore.QRect(9, 9, 501, 185)) + self.formLayoutWidget.setObjectName("formLayoutWidget") + self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget) + self.formLayout.setContentsMargins(0, 0, 0, 0) + self.formLayout.setObjectName("formLayout") + self.label = QtWidgets.QLabel(self.formLayoutWidget) + self.label.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label.setObjectName("label") + self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label) + self.release = QtWidgets.QLineEdit(self.formLayoutWidget) + self.release.setToolTip("") + self.release.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.release.setObjectName("release") + self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.release) + self.label_2 = QtWidgets.QLabel(self.formLayoutWidget) + self.label_2.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_2.setObjectName("label_2") + self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2) + self.user = QtWidgets.QLineEdit(self.formLayoutWidget) + self.user.setToolTip("") + self.user.setStatusTip("") + self.user.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.user.setObjectName("user") + self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.user) + self.label_3 = QtWidgets.QLabel(self.formLayoutWidget) + self.label_3.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_3.setObjectName("label_3") + self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_3) + self.password = QtWidgets.QLineEdit(self.formLayoutWidget) + self.password.setToolTip("") + self.password.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.password.setObjectName("password") + self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.password) + self.label_4 = QtWidgets.QLabel(self.formLayoutWidget) + self.label_4.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_4.setObjectName("label_4") + self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_4) + self.location = QtWidgets.QLineEdit(self.formLayoutWidget) + self.location.setToolTip("") + self.location.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.location.setObjectName("location") + self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.location) + self.label_5 = QtWidgets.QLabel(self.formLayoutWidget) + self.label_5.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_5.setObjectName("label_5") + self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_5) + self.selectDest = QtWidgets.QPushButton(self.formLayoutWidget) + self.selectDest.setToolTip("") + self.selectDest.setObjectName("selectDest") + self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.selectDest) + self.label_6 = QtWidgets.QLabel(self.formLayoutWidget) + self.label_6.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_6.setObjectName("label_6") + self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_6) + self.bwl = QtWidgets.QSpinBox(self.formLayoutWidget) + self.bwl.setToolTip("") + self.bwl.setMaximum(100000) + self.bwl.setSingleStep(50) + self.bwl.setObjectName("bwl") + self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.bwl) + self.label_7 = QtWidgets.QLabel(self.formLayoutWidget) + self.label_7.setObjectName("label_7") + self.formLayout.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.label_7) + + self.retranslateUi(prefsDialog) + self.buttonBox.accepted.connect(prefsDialog.accept) + self.buttonBox.rejected.connect(prefsDialog.reject) + QtCore.QMetaObject.connectSlotsByName(prefsDialog) + + def retranslateUi(self, prefsDialog): + _translate = QtCore.QCoreApplication.translate + prefsDialog.setWindowTitle(_translate("prefsDialog", "Preferences")) + self.label.setToolTip(_translate("prefsDialog", "Give the release name like \"mageia5-alpha2\"")) + self.label.setText(_translate("prefsDialog", "Release:")) + self.label_2.setToolTip(_translate("prefsDialog", "User name to acces the repository. Only for testing repository.")) + self.label_2.setText(_translate("prefsDialog", "User:")) + self.label_3.setToolTip(_translate("prefsDialog", "Associated with user, if needed")) + self.label_3.setText(_translate("prefsDialog", "Password:")) + self.label_4.setToolTip(_translate("prefsDialog", "Source repository. Keep void to use the testing repo.")) + self.label_4.setText(_translate("prefsDialog", "Source:")) + self.label_5.setToolTip(_translate("prefsDialog", "The local directory where you store ISOs. Will sync your existent ISOs already present.")) + self.label_5.setText(_translate("prefsDialog", "Destination:")) + self.selectDest.setText(_translate("prefsDialog", "PushButton")) + self.label_6.setToolTip(_translate("prefsDialog", "Set to zero if you don\'t want apply limit.")) + self.label_6.setText(_translate("prefsDialog", "Bandwith limit (kB/s):")) + self.label_7.setText(_translate("prefsDialog", "Define parameters which are stored and used for rsync")) + diff --git a/mageiaSync/mageiaSyncDBprefs.pyc b/mageiaSync/mageiaSyncDBprefs.pyc new file mode 100644 index 0000000..916ed17 Binary files /dev/null and b/mageiaSync/mageiaSyncDBprefs.pyc differ diff --git a/mageiaSync/mageiaSyncDBprefs.ui b/mageiaSync/mageiaSyncDBprefs.ui new file mode 100644 index 0000000..81f947f --- /dev/null +++ b/mageiaSync/mageiaSyncDBprefs.ui @@ -0,0 +1,237 @@ + + + prefsDialog + + + + 0 + 0 + 520 + 234 + + + + Preferences + + + + + 10 + 200 + 511 + 32 + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + + + + 9 + 9 + 501 + 185 + + + + + + + Give the release name like "mageia5-alpha2" + + + + + + Release: + + + + + + + + + + + + + + + + + User name to acces the repository. Only for testing repository. + + + + + + User: + + + + + + + + + + + + + + + + + + + + Associated with user, if needed + + + + + + Password: + + + + + + + + + + + + + + + + + Source repository. Keep void to use the testing repo. + + + + + + Source: + + + + + + + + + + + + + + + + + The local directory where you store ISOs. Will sync your existent ISOs already present. + + + + + + Destination: + + + + + + + + + + PushButton + + + + + + + Set to zero if you don't want apply limit. + + + + + + Bandwith limit (kB/s): + + + + + + + + + + 100000 + + + 50 + + + + + + + Define parameters which are stored and used for rsync + + + + + + + + + + buttonBox + accepted() + prefsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + prefsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/mageiaSync/mageiaSyncDBrename.py b/mageiaSync/mageiaSyncDBrename.py new file mode 100644 index 0000000..2428721 --- /dev/null +++ b/mageiaSync/mageiaSyncDBrename.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'mageiaSyncDBrename.ui' +# +# Created: Sat Sep 20 16:27:56 2014 +# by: PyQt5 UI code generator 5.1.1 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_renameDialog(object): + def setupUi(self, renameDialog): + renameDialog.setObjectName("renameDialog") + renameDialog.resize(562, 138) + self.buttonBox = QtWidgets.QDialogButtonBox(renameDialog) + self.buttonBox.setGeometry(QtCore.QRect(10, 100, 541, 32)) + self.buttonBox.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) + self.buttonBox.setCenterButtons(True) + self.buttonBox.setObjectName("buttonBox") + self.gridLayoutWidget = QtWidgets.QWidget(renameDialog) + self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 556, 100)) + self.gridLayoutWidget.setObjectName("gridLayoutWidget") + self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.label = QtWidgets.QLabel(self.gridLayoutWidget) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 2, 0, 1, 1) + self.oldRelease = QtWidgets.QLineEdit(self.gridLayoutWidget) + self.oldRelease.setObjectName("oldRelease") + self.gridLayout.addWidget(self.oldRelease, 2, 1, 1, 1) + self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 3, 0, 1, 1) + self.label_3 = QtWidgets.QLabel(self.gridLayoutWidget) + self.label_3.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_3.setWordWrap(False) + self.label_3.setObjectName("label_3") + self.gridLayout.addWidget(self.label_3, 0, 0, 1, 2) + self.label_4 = QtWidgets.QLabel(self.gridLayoutWidget) + self.label_4.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_4.setObjectName("label_4") + self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) + self.chooseDir = QtWidgets.QPushButton(self.gridLayoutWidget) + self.chooseDir.setObjectName("chooseDir") + self.gridLayout.addWidget(self.chooseDir, 1, 1, 1, 1) + self.newRelease = QtWidgets.QComboBox(self.gridLayoutWidget) + self.newRelease.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.newRelease.setEditable(True) + self.newRelease.setObjectName("newRelease") + self.gridLayout.addWidget(self.newRelease, 3, 1, 1, 1) + + self.retranslateUi(renameDialog) + self.buttonBox.accepted.connect(renameDialog.accept) + self.buttonBox.rejected.connect(renameDialog.reject) + QtCore.QMetaObject.connectSlotsByName(renameDialog) + + def retranslateUi(self, renameDialog): + _translate = QtCore.QCoreApplication.translate + renameDialog.setWindowTitle(_translate("renameDialog", "Rename release")) + self.label.setText(_translate("renameDialog", "Old release")) + self.label_2.setText(_translate("renameDialog", "New release")) + self.label_3.setText(_translate("renameDialog", "This action renames the directories and names from a former version to a new one.")) + self.label_4.setText(_translate("renameDialog", "Base directory")) + self.chooseDir.setText(_translate("renameDialog", "PushButton")) + diff --git a/mageiaSync/mageiaSyncDBrename.pyc b/mageiaSync/mageiaSyncDBrename.pyc new file mode 100644 index 0000000..5404390 Binary files /dev/null and b/mageiaSync/mageiaSyncDBrename.pyc differ diff --git a/mageiaSync/mageiaSyncDBrename.ui b/mageiaSync/mageiaSyncDBrename.ui new file mode 100644 index 0000000..c17c528 --- /dev/null +++ b/mageiaSync/mageiaSyncDBrename.ui @@ -0,0 +1,143 @@ + + + renameDialog + + + + 0 + 0 + 562 + 138 + + + + Rename release + + + + + 10 + 100 + 541 + 32 + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + + + + 0 + 0 + 556 + 100 + + + + + + + Old release + + + + + + + + + + New release + + + + + + + + + + This action renames the directories and names from a former version to a new one. + + + false + + + + + + + + + + Base directory + + + + + + + PushButton + + + + + + + + + + true + + + + + + + + + + buttonBox + accepted() + renameDialog + accept() + + + 248 + 254 + + + 163 + 69 + + + + + buttonBox + rejected() + renameDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/mageiaSync/mageiaSyncDBupdate.py b/mageiaSync/mageiaSyncDBupdate.py new file mode 100644 index 0000000..8ec2c47 --- /dev/null +++ b/mageiaSync/mageiaSyncDBupdate.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'mageiaSyncDBupdate.ui' +# +# Created: Tue Aug 26 07:25:11 2014 +# by: PyQt5 UI code generator 5.1.1 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(382, 102) + self.verticalLayoutWidget = QtWidgets.QWidget(Dialog) + self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, -1, 381, 101)) + self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.verticalLayoutWidget) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.progressBar = QtWidgets.QProgressBar(self.verticalLayoutWidget) + self.progressBar.setProperty("value", 24) + self.progressBar.setObjectName("progressBar") + self.verticalLayout.addWidget(self.progressBar) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "Dialog")) + self.label.setText(_translate("Dialog", "Loading images list from repository...")) + diff --git a/mageiaSync/mageiaSyncDBupdate.ui b/mageiaSync/mageiaSyncDBupdate.ui new file mode 100644 index 0000000..87f3ba3 --- /dev/null +++ b/mageiaSync/mageiaSyncDBupdate.ui @@ -0,0 +1,47 @@ + + + Dialog + + + + 0 + 0 + 382 + 102 + + + + Dialog + + + + + 0 + -1 + 381 + 101 + + + + + + + Loading images list from repository... + + + + + + + 24 + + + + + + verticalLayoutWidget + label + + + + diff --git a/mageiaSync/mageiaSyncExt.py b/mageiaSync/mageiaSyncExt.py new file mode 100644 index 0000000..f344960 --- /dev/null +++ b/mageiaSync/mageiaSyncExt.py @@ -0,0 +1,318 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Jul 12 21:42:56 2014 + +@author: yves +""" + +import re, os + +from subprocess import Popen, PIPE +from PyQt5.QtCore import QDir, QFileInfo,pyqtSignal,QThread + +class checkThread(QThread): + md5Signal = pyqtSignal(int) + sha1Signal= pyqtSignal(int) + dateSignal=pyqtSignal(int) + sizeSignal=pyqtSignal(int,int) + checkStartSignal=pyqtSignal(int) + + def __init__(self, parent=None): + super(checkThread, self).__init__(parent) + + def processSum(self,sumType): + import hashlib + if sumType=='sha1': + hashfunc = hashlib.sha1() + if sumType=='md5': + hashfunc = hashlib.md5() + try: + with open(self.destination+'/'+self.path+'/'+self.name, 'rb') as f: + while True: + block = f.read(2**10) + if not block: break + hashfunc.update(block) + sumcalc=hashfunc.hexdigest() + except: + return False + try: + fs=open(self.destination+'/'+self.path+'/'+self.name+'.'+sumType,'r') + except: + # reference file not found + return False + sumcheck=(fs.readline()).split()[0] + if sumcalc==sumcheck: + return True + return False + + def processDate(self): + import datetime as datetime + import time + import locale + locale.setlocale(locale.LC_ALL, 'C') + # Get and process the date from the file DATE.txt + try: + dateFile=open(str(self.destination)+'/'+self.path+'/DATE.txt','r') + except: + return False + refDate=dateFile.readline() + lits=re.split("\W+", refDate) + nums=re.findall("([0-9]+)", refDate) + refTime=re.findall("[0-9]*:[0-9]*:[0-9]*", refDate)[0] + refDay=eval(nums[0]) + refYear=eval(nums[-1]) + refMonth=time.strptime(lits[1], "%b").tm_mon + # Date of file + info=datetime.datetime.fromtimestamp(os.path.getmtime(str(self.destination)+'/'+self.path+'/'+self.name)) + if(refDay==info.day and refMonth==info.month and refYear==info.year and refTime==info.strftime("%H:%M:%S")): + return True + else: + return False + + def setup(self, destination, path,name,isoIndex): + self.destination=destination + self.path=path + self.name=name + self.isoIndex=isoIndex + + def run(self): + signal=200+self.isoIndex + isoSize=QFileInfo(str(self.destination)+'/'+self.path+'/' +self.name).size() + self.sizeSignal.emit(signal, isoSize) + signal=500+self.isoIndex + self.checkStartSignal.emit(signal) + checkMd5=self.processSum('md5') + self.md5Signal.emit(self.isoIndex+128*checkMd5) + signal=400+self.isoIndex + self.checkStartSignal.emit(signal) + checkSha1=self.processSum('sha1') + self.sha1Signal.emit(self.isoIndex+128*checkSha1) + signal=300+self.isoIndex + self.checkStartSignal.emit(signal) + checkDate=self.processDate() + self.dateSignal.emit(self.isoIndex+128*checkDate) + self.quit() + + +class syncThread(QThread): + progressSignal = pyqtSignal(int) + speedSignal= pyqtSignal(int) + endSignal=pyqtSignal(int) + remainSignal=pyqtSignal(str) + checkSignal=pyqtSignal(int) + sizeSignal=pyqtSignal(int) + lvM=pyqtSignal(str) + + def __init__(self, parent=None): + super(syncThread, self).__init__(parent) + self.stopped=False + self.list=[] + + def setup(self,nameWithPath, destination,row,): + # row is the index in 'model' + iso={'nameWithPath':str(nameWithPath),'destination':str(destination),'row':row} + self.list.append(iso) + + def params(self, password, bwl): + self.password=password + self.bwl=bwl # Bandwith limit + + def stop(self): + self.stopped=True + try: + self.process.terminate() + self.lvM.emit("Process rsync stopped") + except: + self.lvM.emit("Process rsync already stopped") + # Init progressbar and speed counter + self.endSignal.emit(0) + + def run(self): + if len(self.list)==0: + self.lvM.emit("No entry selected") + for iso in self.list: + errorOccured=True + self.lvM.emit("Starting rsync with "+iso['nameWithPath']) + if self.bwl!=0: + commande=['rsync','-avHP',"--bwlimit="+str(self.bwl), iso['nameWithPath'], iso['destination']] + else: + commande=['rsync','-avHP', iso['nameWithPath'], iso['destination']] + try: + if self.password != "": + envir = os.environ.copy() + envir['RSYNC_PASSWORD']=str(self.password) + self.process = Popen(commande, shell=False, stdout=PIPE, stderr=PIPE, env=envir) + else: + self.process = Popen(commande, shell=False, stdout=PIPE, stderr=PIPE) + errorOccured=False + except OSError as e: + self.endSignal.emit(1) +# self.lvM.emit("Command rsync not found: "+str(e)) + except ValueError as e: + self.endSignal.emit(2) +# self.lvM.emit("Error in rsync parameters: "+str(e)) + except Exception as e : + self.endSignal.emit(3) + self.lvM.emit("Error in rsync: "+str(e)) + if not errorOccured: + buf='' + while not self.stopped: + letter=self.process.stdout.read(1).decode('unicode_escape') + buf=buf+letter + if letter=='\n' or letter=='\r': + progressL=re.findall("([0-9]*)%", buf) + speedK=re.findall("([0-9.]*)kB/s", buf) + speedM=re.findall("([0-9.]*)MB/s", buf) + remain=re.findall("[0-9]*:[0-9]*:[0-9]*",buf) + sizeB=re.findall("[1-9](?:\d{0,2})(?:,\d{3})*",buf) + if len(progressL) != 0: + progress= eval(progressL[0]) + self.progressSignal.emit(progress) + if len(sizeB) != 0: + self.sizeSignal.emit(eval(sizeB[0].replace(",",""))) + else: + if (len(buf) !=0): + self.lvM.emit(buf.rstrip()) + if len(speedK) != 0: + speed= eval(speedK[0]) + self.speedSignal.emit(speed) + if len(speedM) != 0: + speed= 1024*eval(speedM[0]) + self.speedSignal.emit(speed) + if len(remain) != 0: + self.remainSignal.emit(remain[0]) + buf="" + self.process.poll() + if self.process.returncode != None: + break + self.lvM.emit("Ending with "+iso['nameWithPath']) + self.checkSignal.emit(iso['row']) + if self.stopped: + break + self.endSignal.emit(0) + self.speedSignal.emit(0) + self.progressSignal.emit(0) + self.sizeSignal.emit(0) + self.stopped=False + self.list=[] + self.quit() + +def rename(directory,oldRelease,newRelease): + options=['d', 'f'] + for option in options: + commande=['find', directory, '-type' ,option, '-exec','rename',oldRelease,newRelease, '{}', '+'] + process = Popen(commande, shell=False, stdout=PIPE, stderr=PIPE) + process.poll() + while True : + item=process.stdout.readline().rstrip() + process.poll() + if process.returncode != None: + if process.returncode!=0: + item=process.stderr.readline().rstrip() + return 'Error ', item + break + return "Success in renaming" + +class findIsos(QThread): + endSignal=pyqtSignal(int) + lvM=pyqtSignal(str) + + def __init__(self, parent=None): + super(findIsos, self).__init__(parent) + self.list=[] + self.localList=[] + + def setup(self,path, password, destination): + self.path=path + self.password=password + self.destination=destination + self.lvM.emit(path+password+destination) + + def getList(self): + return self.list + + def getLocal(self): + return self.localList + + def run(self): + # Lists ISO files in local directory + root=QDir(self.destination) + root.setFilter(QDir.AllDirs|QDir.NoDot|QDir.NoDotDot) + dirs=root.entryList() + for dir in dirs: + sub=QDir(self.destination+'/'+dir) + sub.setNameFilters(["*.iso"]) + sub.setFilter(QDir.Files) + local=sub.entryList() + if len(local)!=0: + for iso in local: + isoSize=QFileInfo(sub.absolutePath()+'/' +iso).size() + self.localList.append([dir,iso,isoSize]) + # List the remote directory + commande = ['rsync', '-avHP', '--list-only',str(self.path)] + try: + if self.password != "": + envir = os.environ.copy() + envir['RSYNC_PASSWORD']=str(self.password) + process = Popen(commande, shell=False, stdout=PIPE, stderr=PIPE, env=envir) + else: + process = Popen(commande, shell=False, stdout=PIPE, stderr=PIPE) + except OSError as e: + self.lvM.emit("Command rsync not found: "+str(e)) + self.endSignal.emit(1) + return + except ValueError as e: + self.lvM.emit("Error in rsync parameters: "+str(e)) + self.endSignal.emit(2) + return + except Exception as e: + # Unknown error in rsync + self.lvM.emit("Error in rsync: "+str(e)) + self.endSignal.emit(3) + return + process.poll() + while True : + item=process.stdout.readline().rstrip().decode('unicode_escape') + self.lvM.emit(item) + if str(item.lower()).endswith('.iso') : + words=item.split() + self.list.append(words[-1]) + process.poll() + if process.returncode != None: + break + self.endSignal.emit(0) + +def findRelease(releasePath, password): # List the remote list of releases + releaseList =[] + code=0 + commande = ['rsync', '--list-only',str(releasePath)] + print commande + try: + if password != "": + envir = os.environ.copy() + envir['RSYNC_PASSWORD']=str(password) + process = Popen(commande, shell=False, stdout=PIPE, stderr=PIPE, env=envir) + else: + process = Popen(commande, shell=False, stdout=PIPE, stderr=PIPE) + except OSError as e: + code=1 + return code, "Command rsync not found: "+str(e) + except ValueError as e: + code=2 + return code,"Error in rsync parameters: "+str(e) + except Exception as e: + # Unknown error in rsync + code=3 + return code, "Error in rsync: "+str(e) + process.poll() + while True : + item=process.stdout.readline().rstrip().decode('unicode_escape') + words=item.split() + if words !=[]: + print item + print words + releaseList.append(words[-1]) + process.poll() + if process.returncode != None: + break + return code, releaseList diff --git a/mageiaSync/mageiaSyncExt.pyc b/mageiaSync/mageiaSyncExt.pyc new file mode 100644 index 0000000..d85b18e Binary files /dev/null and b/mageiaSync/mageiaSyncExt.pyc differ diff --git a/mageiaSync/mageiaSyncUI.py b/mageiaSync/mageiaSyncUI.py new file mode 100644 index 0000000..fed1972 --- /dev/null +++ b/mageiaSync/mageiaSyncUI.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'mageiaSyncUI.ui' +# +# Created: Sat Aug 30 20:19:01 2014 +# by: PyQt5 UI code generator 5.1.1 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_mainWindow(object): + def setupUi(self, mainWindow): + mainWindow.setObjectName("mainWindow") + mainWindow.resize(862, 587) + self.centralwidget = QtWidgets.QWidget(mainWindow) + self.centralwidget.setObjectName("centralwidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) + self.verticalLayout.setObjectName("verticalLayout") + self.remoteDirLabel = QtWidgets.QLabel(self.centralwidget) + self.remoteDirLabel.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.remoteDirLabel.setObjectName("remoteDirLabel") + self.verticalLayout.addWidget(self.remoteDirLabel) + self.selectAll = QtWidgets.QPushButton(self.centralwidget) + self.selectAll.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.selectAll.setObjectName("selectAll") + self.verticalLayout.addWidget(self.selectAll) + self.listIsos = QtWidgets.QListWidget(self.centralwidget) + self.listIsos.setAlternatingRowColors(True) + self.listIsos.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) + self.listIsos.setModelColumn(0) + self.listIsos.setObjectName("listIsos") + self.verticalLayout.addWidget(self.listIsos) + self.localDirLabel = QtWidgets.QLabel(self.centralwidget) + self.localDirLabel.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.localDirLabel.setObjectName("localDirLabel") + self.verticalLayout.addWidget(self.localDirLabel) + self.localList = QtWidgets.QTableView(self.centralwidget) + self.localList.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.localList.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) + self.localList.setAlternatingRowColors(True) + self.localList.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) + self.localList.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) + self.localList.setGridStyle(QtCore.Qt.DotLine) + self.localList.setObjectName("localList") + self.localList.verticalHeader().setVisible(False) + self.verticalLayout.addWidget(self.localList) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setContentsMargins(-1, -1, -1, 9) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.IprogressBar = QtWidgets.QProgressBar(self.centralwidget) + self.IprogressBar.setEnabled(True) + self.IprogressBar.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.IprogressBar.setProperty("value", 24) + self.IprogressBar.setObjectName("IprogressBar") + self.horizontalLayout_2.addWidget(self.IprogressBar) + self.Lsize = QtWidgets.QLabel(self.centralwidget) + self.Lsize.setObjectName("Lsize") + self.horizontalLayout_2.addWidget(self.Lsize) + self.speedLCD = QtWidgets.QLCDNumber(self.centralwidget) + self.speedLCD.setObjectName("speedLCD") + self.horizontalLayout_2.addWidget(self.speedLCD) + self.label_2 = QtWidgets.QLabel(self.centralwidget) + self.label_2.setObjectName("label_2") + self.horizontalLayout_2.addWidget(self.label_2) + self.label_3 = QtWidgets.QLabel(self.centralwidget) + self.label_3.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.label_3.setObjectName("label_3") + self.horizontalLayout_2.addWidget(self.label_3) + self.timeRemaining = QtWidgets.QTimeEdit(self.centralwidget) + self.timeRemaining.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.timeRemaining.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.timeRemaining.setReadOnly(True) + self.timeRemaining.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.timeRemaining.setObjectName("timeRemaining") + self.horizontalLayout_2.addWidget(self.timeRemaining) + self.verticalLayout.addLayout(self.horizontalLayout_2) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.syncGo = QtWidgets.QPushButton(self.centralwidget) + self.syncGo.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.syncGo.setObjectName("syncGo") + self.horizontalLayout.addWidget(self.syncGo) + self.stop = QtWidgets.QPushButton(self.centralwidget) + self.stop.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.stop.setObjectName("stop") + self.horizontalLayout.addWidget(self.stop) + self.verticalLayout.addLayout(self.horizontalLayout) + self.label = QtWidgets.QLabel(self.centralwidget) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.lvText = QtWidgets.QTextEdit(self.centralwidget) + self.lvText.setReadOnly(True) + self.lvText.setObjectName("lvText") + self.verticalLayout.addWidget(self.lvText) + mainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(mainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 862, 19)) + self.menubar.setObjectName("menubar") + self.menuFile = QtWidgets.QMenu(self.menubar) + self.menuFile.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates)) + self.menuFile.setObjectName("menuFile") + self.menuSync = QtWidgets.QMenu(self.menubar) + self.menuSync.setObjectName("menuSync") + mainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(mainWindow) + self.statusbar.setObjectName("statusbar") + mainWindow.setStatusBar(self.statusbar) + self.actionUpdate = QtWidgets.QAction(mainWindow) + self.actionUpdate.setObjectName("actionUpdate") + self.actionQuit = QtWidgets.QAction(mainWindow) + self.actionQuit.setObjectName("actionQuit") + self.actionPreferences = QtWidgets.QAction(mainWindow) + self.actionPreferences.setObjectName("actionPreferences") + self.actionRename = QtWidgets.QAction(mainWindow) + self.actionRename.setObjectName("actionRename") + self.menuFile.addAction(self.actionUpdate) + self.menuFile.addAction(self.actionPreferences) + self.menuFile.addAction(self.actionQuit) + self.menuSync.addAction(self.actionRename) + self.menubar.addAction(self.menuFile.menuAction()) + self.menubar.addAction(self.menuSync.menuAction()) + + self.retranslateUi(mainWindow) + QtCore.QMetaObject.connectSlotsByName(mainWindow) + mainWindow.setTabOrder(self.syncGo, self.listIsos) + mainWindow.setTabOrder(self.listIsos, self.stop) + + def retranslateUi(self, mainWindow): + _translate = QtCore.QCoreApplication.translate + mainWindow.setWindowTitle(_translate("mainWindow", "MageiaSync")) + self.remoteDirLabel.setText(_translate("mainWindow", "Remote directory")) + self.selectAll.setText(_translate("mainWindow", "Select All")) + self.localDirLabel.setText(_translate("mainWindow", "Local directory:")) + self.Lsize.setText(_translate("mainWindow", "0 bytes")) + self.label_2.setText(_translate("mainWindow", "kB/s")) + self.label_3.setText(_translate("mainWindow", "Remaining:")) + self.timeRemaining.setDisplayFormat(_translate("mainWindow", "H:mm:ss")) + self.syncGo.setText(_translate("mainWindow", "Do sync")) + self.stop.setText(_translate("mainWindow", "Stop")) + self.label.setText(_translate("mainWindow", "Report")) + self.menuFile.setTitle(_translate("mainWindow", "File")) + self.menuSync.setTitle(_translate("mainWindow", "Sync")) + self.actionUpdate.setText(_translate("mainWindow", "Update list")) + self.actionQuit.setText(_translate("mainWindow", "Quit")) + self.actionPreferences.setText(_translate("mainWindow", "Preferences")) + self.actionRename.setText(_translate("mainWindow", "Rename archives")) + diff --git a/mageiaSync/mageiaSyncUI.pyc b/mageiaSync/mageiaSyncUI.pyc new file mode 100644 index 0000000..2c1aa92 Binary files /dev/null and b/mageiaSync/mageiaSyncUI.pyc differ diff --git a/mageiaSync/mageiaSyncUI.ui b/mageiaSync/mageiaSyncUI.ui new file mode 100644 index 0000000..a86d314 --- /dev/null +++ b/mageiaSync/mageiaSyncUI.ui @@ -0,0 +1,250 @@ + + + mainWindow + + + + 0 + 0 + 862 + 587 + + + + MageiaSync + + + + + + + + + + Remote directory + + + + + + + + + + Select All + + + + + + + true + + + QAbstractItemView::MultiSelection + + + 0 + + + + + + + + + + Local directory: + + + + + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::MultiSelection + + + QAbstractItemView::SelectRows + + + Qt::DotLine + + + false + + + + + + + 9 + + + + + true + + + + + + 24 + + + + + + + 0 bytes + + + + + + + + + + kB/s + + + + + + + + + + Remaining: + + + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + QAbstractSpinBox::NoButtons + + + H:mm:ss + + + + + + + + + + + + + + Do sync + + + + + + + + + + Stop + + + + + + + + + Report + + + + + + + true + + + + + + + + + 0 + 0 + 862 + 19 + + + + + + + + File + + + + + + + + Sync + + + + + + + + + + Update list + + + + + Quit + + + + + Preferences + + + + + Rename archives + + + + + syncGo + listIsos + stop + + + + diff --git a/mageiaSync/mageiasync.py b/mageiaSync/mageiasync.py new file mode 100644 index 0000000..dbdb5a6 --- /dev/null +++ b/mageiaSync/mageiasync.py @@ -0,0 +1,427 @@ +#!/usr/bin/python3 + +from PyQt5.QtWidgets import ( QProgressDialog, QMainWindow, + QDialog, QFileDialog, QApplication) +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).replace(","," ")) + + 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") + paramRelease="" + try: + paramRelease=params.value("release", type="QString") + # the parameters already initialised? + except: + pass + if paramRelease =="": + # Values are not yet set + self.pd=prefsDialog() + # Set values which are already defined +# self.pd.user.setText(params.value("user", type="QString")) +# self.pd.password.setText(params.value("password", type="QString")) +# self.pd.location.setText(params.value("location", type="QString")) +# self.pd.selectDest.setText(params.value("destination", type="QString")) +# self.pd.selectDest.setText(QtCore.QDir.currentPath()) +# self.pd.bwl.setValue(params.value("bwl", type="int")) +# self.pd.password.setText(params.value("password", type="QString")) + 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.user=params.value("user", 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.lvMessage("Source: "+self.nameWithPath) + 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]) + code,list=mageiaSyncExt.findRelease('rsync://'+self.user+'@bcd.mageia.org/isos/',self.password) + if code==0: + for item in list: + self.rd.newRelease.addItem(item) + self.rd.chooseDir.setText(self.destination) + answer=self.rd.exec_() + if answer: + returnMsg=mageiaSyncExt.rename(self.rd.chooseDir.text(),self.rd.oldRelease.text(),str(self.rd.newRelease.lineEdit())) + 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_()) + -- cgit v1.2.1