diff options
author | SARL ENR-68 <david@david.david> | 2014-09-08 22:12:23 +0200 |
---|---|---|
committer | SARL ENR-68 <david@david.david> | 2014-09-08 22:12:23 +0200 |
commit | 91f5e36949b12d98b62e916657aafbd547973ff5 (patch) | |
tree | 8702a0543a6200567825cd2a5c5d6c8ca9150307 /mageiasync | |
parent | 1282fb3fc4fcda3a9bea78802b5c2bff3385fe6c (diff) | |
download | MageiaSync-91f5e36949b12d98b62e916657aafbd547973ff5.tar MageiaSync-91f5e36949b12d98b62e916657aafbd547973ff5.tar.gz MageiaSync-91f5e36949b12d98b62e916657aafbd547973ff5.tar.bz2 MageiaSync-91f5e36949b12d98b62e916657aafbd547973ff5.tar.xz MageiaSync-91f5e36949b12d98b62e916657aafbd547973ff5.zip |
initial commit from david.david
- add a spec file
- add translations tools
- add a setup.py file for build and install
- add a desktop file and a desktop file in
- add an empty README.rst
- add a po folder for future translation files
- replace lib folder by mageiasync folder
Diffstat (limited to 'mageiasync')
-rw-r--r-- | mageiasync/mageiaSyncDBprefs..py | 98 | ||||
-rw-r--r-- | mageiasync/mageiaSyncDBprefs.py | 110 | ||||
-rw-r--r-- | mageiasync/mageiaSyncDBprefs.ui | 237 | ||||
-rw-r--r-- | mageiasync/mageiaSyncDBrename.py | 66 | ||||
-rw-r--r-- | mageiasync/mageiaSyncDBrename.ui | 133 | ||||
-rw-r--r-- | mageiasync/mageiaSyncDBupdate.py | 37 | ||||
-rw-r--r-- | mageiasync/mageiaSyncDBupdate.ui | 47 | ||||
-rw-r--r-- | mageiasync/mageiaSyncExt.py | 285 | ||||
-rw-r--r-- | mageiasync/mageiaSyncUI.py | 148 | ||||
-rw-r--r-- | mageiasync/mageiaSyncUI.ui | 250 | ||||
-rw-r--r-- | mageiasync/mageiasync.py | 436 |
11 files changed, 1847 insertions, 0 deletions
diff --git a/mageiasync/mageiaSyncDBprefs..py b/mageiasync/mageiaSyncDBprefs..py new file mode 100644 index 0000000..c0e081f --- /dev/null +++ b/mageiasync/mageiaSyncDBprefs..py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'mageiaSyncDBprefs.ui' +# +# Created: Sat Aug 9 09:07:51 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.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.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.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.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", "Dialog")) + self.label.setText(_translate("prefsDialog", "Release:")) + self.label_2.setText(_translate("prefsDialog", "User:")) + self.label_3.setText(_translate("prefsDialog", "Password:")) + self.label_4.setText(_translate("prefsDialog", "Source:")) + self.label_5.setText(_translate("prefsDialog", "Destination:")) + self.selectDest.setText(_translate("prefsDialog", "PushButton")) + 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.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.ui b/mageiasync/mageiaSyncDBprefs.ui new file mode 100644 index 0000000..81f947f --- /dev/null +++ b/mageiasync/mageiaSyncDBprefs.ui @@ -0,0 +1,237 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>prefsDialog</class> + <widget class="QDialog" name="prefsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>520</width> + <height>234</height> + </rect> + </property> + <property name="windowTitle"> + <string>Preferences</string> + </property> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="geometry"> + <rect> + <x>10</x> + <y>200</y> + <width>511</width> + <height>32</height> + </rect> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + <property name="centerButtons"> + <bool>true</bool> + </property> + </widget> + <widget class="QWidget" name="formLayoutWidget"> + <property name="geometry"> + <rect> + <x>9</x> + <y>9</y> + <width>501</width> + <height>185</height> + </rect> + </property> + <layout class="QFormLayout" name="formLayout"> + <item row="1" column="0"> + <widget class="QLabel" name="label"> + <property name="toolTip"> + <string>Give the release name like "mageia5-alpha2"</string> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Release:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="release"> + <property name="toolTip"> + <string/> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_2"> + <property name="toolTip"> + <string>User name to acces the repository. Only for testing repository.</string> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>User:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="user"> + <property name="toolTip"> + <string/> + </property> + <property name="statusTip"> + <string/> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_3"> + <property name="toolTip"> + <string>Associated with user, if needed</string> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Password:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="password"> + <property name="toolTip"> + <string/> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_4"> + <property name="toolTip"> + <string>Source repository. Keep void to use the testing repo.</string> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Source:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="location"> + <property name="toolTip"> + <string/> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_5"> + <property name="toolTip"> + <string>The local directory where you store ISOs. Will sync your existent ISOs already present.</string> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Destination:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QPushButton" name="selectDest"> + <property name="toolTip"> + <string/> + </property> + <property name="text"> + <string>PushButton</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_6"> + <property name="toolTip"> + <string>Set to zero if you don't want apply limit.</string> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Bandwith limit (kB/s):</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QSpinBox" name="bwl"> + <property name="toolTip"> + <string/> + </property> + <property name="maximum"> + <number>100000</number> + </property> + <property name="singleStep"> + <number>50</number> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Define parameters which are stored and used for rsync</string> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>prefsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>prefsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/mageiasync/mageiaSyncDBrename.py b/mageiasync/mageiaSyncDBrename.py new file mode 100644 index 0000000..d2b5251 --- /dev/null +++ b/mageiasync/mageiaSyncDBrename.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'mageiaSyncDBrename.ui' +# +# Created: Tue Aug 26 07:25:27 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.newRelease = QtWidgets.QLineEdit(self.gridLayoutWidget) + self.newRelease.setObjectName("newRelease") + self.gridLayout.addWidget(self.newRelease, 3, 1, 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.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.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", "TextLabel")) + self.chooseDir.setText(_translate("renameDialog", "PushButton")) + diff --git a/mageiasync/mageiaSyncDBrename.ui b/mageiasync/mageiaSyncDBrename.ui new file mode 100644 index 0000000..726bc09 --- /dev/null +++ b/mageiasync/mageiaSyncDBrename.ui @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>renameDialog</class> + <widget class="QDialog" name="renameDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>562</width> + <height>138</height> + </rect> + </property> + <property name="windowTitle"> + <string>Rename release</string> + </property> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="geometry"> + <rect> + <x>10</x> + <y>100</y> + <width>541</width> + <height>32</height> + </rect> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + <property name="centerButtons"> + <bool>true</bool> + </property> + </widget> + <widget class="QWidget" name="gridLayoutWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>556</width> + <height>100</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="2" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Old release</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="oldRelease"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>New release</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="newRelease"/> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QLabel" name="label_3"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>This action renames the directories and names from a former version to a new one.</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="chooseDir"> + <property name="text"> + <string>PushButton</string> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>renameDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>163</x> + <y>69</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>renameDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>382</width> + <height>102</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <widget class="QWidget" name="verticalLayoutWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>-1</y> + <width>381</width> + <height>101</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Loading images list from repository...</string> + </property> + </widget> + </item> + <item> + <widget class="QProgressBar" name="progressBar"> + <property name="value"> + <number>24</number> + </property> + </widget> + </item> + </layout> + </widget> + <zorder>verticalLayoutWidget</zorder> + <zorder>label</zorder> + </widget> + <resources/> + <connections/> +</ui> diff --git a/mageiasync/mageiaSyncExt.py b/mageiasync/mageiaSyncExt.py new file mode 100644 index 0000000..612dc04 --- /dev/null +++ b/mageiasync/mageiaSyncExt.py @@ -0,0 +1,285 @@ +# -*- 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) + 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() + print item + process.poll() + if process.returncode != None: + if process.returncode!=0: + item=process.stderr.readline().rstrip() + return 'Error ', item + else: + return "Success" + break + +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 + + 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() + if item.lower().endswith('.iso') : + words=item.split() + self.list.append(words[-1]) + process.poll() + if process.returncode != None: + break + self.endSignal.emit(0) + +#syncIso('rsync://ftp5.gwdg.de/pub/linux/mageia/iso/4.1/Mageia-4.1-LiveCD-GNOME-en-i586-CD/', "/documents/Mageia-4/Mageia-4.1-LiveCD-GNOME-en-i586-CD/", "y8d5qr38728128I")
\ No newline at end of file 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.ui b/mageiasync/mageiaSyncUI.ui new file mode 100644 index 0000000..a86d314 --- /dev/null +++ b/mageiasync/mageiaSyncUI.ui @@ -0,0 +1,250 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>mainWindow</class> + <widget class="QMainWindow" name="mainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>862</width> + <height>587</height> + </rect> + </property> + <property name="windowTitle"> + <string>MageiaSync</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="remoteDirLabel"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Remote directory</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="selectAll"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Select All</string> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="listIsos"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::MultiSelection</enum> + </property> + <property name="modelColumn"> + <number>0</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="localDirLabel"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Local directory:</string> + </property> + </widget> + </item> + <item> + <widget class="QTableView" name="localList"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::MultiSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="gridStyle"> + <enum>Qt::DotLine</enum> + </property> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="bottomMargin"> + <number>9</number> + </property> + <item> + <widget class="QProgressBar" name="IprogressBar"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="value"> + <number>24</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="Lsize"> + <property name="text"> + <string>0 bytes</string> + </property> + </widget> + </item> + <item> + <widget class="QLCDNumber" name="speedLCD"/> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>kB/s</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Remaining:</string> + </property> + </widget> + </item> + <item> + <widget class="QTimeEdit" name="timeRemaining"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="displayFormat"> + <string>H:mm:ss</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="syncGo"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Do sync</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="stop"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="text"> + <string>Stop</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Report</string> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="lvText"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>862</width> + <height>19</height> + </rect> + </property> + <widget class="QMenu" name="menuFile"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="title"> + <string>File</string> + </property> + <addaction name="actionUpdate"/> + <addaction name="actionPreferences"/> + <addaction name="actionQuit"/> + </widget> + <widget class="QMenu" name="menuSync"> + <property name="title"> + <string>Sync</string> + </property> + <addaction name="actionRename"/> + </widget> + <addaction name="menuFile"/> + <addaction name="menuSync"/> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <action name="actionUpdate"> + <property name="text"> + <string>Update list</string> + </property> + </action> + <action name="actionQuit"> + <property name="text"> + <string>Quit</string> + </property> + </action> + <action name="actionPreferences"> + <property name="text"> + <string>Preferences</string> + </property> + </action> + <action name="actionRename"> + <property name="text"> + <string>Rename archives</string> + </property> + </action> + </widget> + <tabstops> + <tabstop>syncGo</tabstop> + <tabstop>listIsos</tabstop> + <tabstop>stop</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> 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_()) |