Commit 1b04a3dd authored by Julien Lepiller's avatar Julien Lepiller

Add initial support for git and gitlab

parent 4d70ab5a
......@@ -25,6 +25,7 @@
"python-neovim"
"python-polib"
"python-pyenchant"
"python-pygit2"
"python-pyqt"
"python-ruamel.yaml"
"python-sphinx"
......
......@@ -7,6 +7,7 @@
"python-lxml"
"python-polib"
"python-pyenchant"
"python-pygit2"
"python-pyqt"
"python-ruamel.yaml"
"python-sphinx"
......
This diff is collapsed.
# Copyright (c) 2018 Julien Lepiller <julien@lepiller.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
####
""" The list of available formats. """
GETTEXT = 0
YAML = 1
format_list = [
"Gettext (.po)",
"YAML (.yml)",
"Qt (.ts)"
]
......@@ -17,7 +17,9 @@
from pathlib import Path
from .systems.tp import TPProject
from .systems.transifex import TransifexProject
from .systems.gitlab import GitlabProject
from .formats.formatException import UnsupportedFormatException
from .systems.list import *
import json
import os
......@@ -62,18 +64,24 @@ class ProjectManager:
with open(self.basedir + '/projects.json') as f:
self.projects = json.load(f)
for p in self.projects:
if p['system'] == 0:
if p['system'] == TRANSLATION_PROJECT:
if not "TP" in self.settings.conf:
self.settings.conf["TP"] = {}
self.project_list[p['name']] = \
TPProject(self.settings.conf["TP"], p['name'], p['lang'], p['info'])
self.project_list[p['name']].open(self.basedir+'/'+p['name'])
if p['system'] == 1:
if p['system'] == TRANSIFEX:
if not "Transifex" in self.settings.conf:
self.settings.conf['Transifex'] = {}
self.project_list[p['name']] = \
TransifexProject(self.settings.conf['Transifex'], p['name'], p['lang'], p['info'])
self.project_list[p['name']].open(self.basedir+'/'+p['name'])
if p['system'] == GITLAB:
if not "Gitlab" in self.settings.conf:
self.settings.conf['Gitlab'] = {}
self.project_list[p['name']] = \
GitlabProject(self.settings.conf['Gitlab'], p['name'], p['lang'], p['info'])
self.project_list[p['name']].open(self.basedir+'/'+p['name'])
except Exception as e:
print(e)
with open(self.basedir + '/projects.json', 'w') as f:
......@@ -83,7 +91,7 @@ class ProjectManager:
projectpath = self.basedir + '/' + name
Path(projectpath).mkdir(parents=True)
try:
if system == 0: #TP
if system == TRANSLATION_PROJECT:
if not "TP" in self.settings.conf:
self.settings.conf["TP"] = {}
proj = TPProject(self.settings.conf["TP"], name, lang)
......@@ -91,7 +99,7 @@ class ProjectManager:
self.project_list[name] = proj
self.projects.append({"name": name, "lang": lang, "system": system,
"info": {"version": proj.version}})
if system == 1: #Transifex
if system == TRANSIFEX:
if not 'Transifex' in self.settings.conf:
self.settings.conf['Transifex'] = {}
proj = TransifexProject(self.settings.conf['Transifex'], name, lang, data)
......@@ -99,6 +107,14 @@ class ProjectManager:
self.project_list[name] = proj
self.projects.append({"name": name, "lang": lang, "system": system,
"info": data})
if system == GITLAB:
if not 'Gitlab' in self.settings.conf:
self.settings.conf['Gitlab'] = {}
proj = GitlabProject(self.settings.conf['Gitlab'], name, lang, data)
proj.initialize(projectpath)
self.project_list[name] = proj
self.projects.append({"name": name, "lang": lang, "system": system,
"info": data})
except UnsupportedFormatException:
rmdir(projectpath)
self.writeProjects()
......
# Copyright (c) 2018 Julien Lepiller <julien@lepiller.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
####
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class MultipleLineEdit(QWidget):
textChanged = pyqtSignal()
def __init__(self, parent = None):
super(MultipleLineEdit, self).__init__(parent)
self.initUI()
def setText(self, texts):
self.treeWidget.clear()
items = []
for text in texts:
item = QTreeWidgetItem([text])
items.append(item)
self.treeWidget.insertTopLevelItems(0, items)
def addLine(self, args):
text = self.newtext.text()
items = [QTreeWidgetItem([text])]
self.treeWidget.insertTopLevelItems(0, items)
def deleteLine(self, args):
self.treeWidget.takeTopLevelItem(self.treeWidget.currentIndex().row())
def content(self):
number = self.treeWidget.topLevelItemCount()
items = []
for i in range(0, number):
items.append(self.treeWidget.topLevelItem(i).text(0))
return items
def initUI(self):
vbox = QVBoxLayout()
hbox = QHBoxLayout()
self.setLayout(vbox)
self.treeWidget = QTreeWidget()
self.treeWidget.setColumnCount(1)
vbox.addWidget(self.treeWidget)
self.newtext = QLineEdit()
addbutton = QPushButton(self.tr("Add"))
addbutton.clicked.connect(self.addLine)
removebutton = QPushButton(self.tr("Remove"))
removebutton.clicked.connect(self.deleteLine, 0)
hbox.addWidget(self.newtext)
hbox.addWidget(addbutton)
hbox.addWidget(removebutton)
vbox.addLayout(hbox)
# Copyright (c) 2018 Julien Lepiller <julien@lepiller.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
####
""" The git abstract system connector. """
import pygit2
from os import rename, remove
class Progress(pygit2.remote.RemoteCallbacks):
def transfer_progress(self, stats):
try:
print("{}/{}\r".format(stats.received_objects, stats.total_objects), file=sys.stderr, end='')
except:
pass
class GitProject:
def __init__(self, conf, name, lang, data = {}):
self.conf = conf
self.name = name
self.lang = lang
self.data = data
def open(self, basedir):
self.basedir = basedir
self.updateURI()
def initialize(self, basedir):
self.basedir = basedir
self.updateURI()
self.clone(basedir + "/current")
def updateURI(self):
raise Exception("Unimplemented method in concrete class: updateURI")
def clone(self, directory):
print("Cloning {} in {}".format(self.uri, directory))
pygit2.clone_repository(self.uri, directory, callbacks=Progress())
def update(self, callback):
os.rename(self.basedir + "/current", self.basedir + "/old")
self.clone(self.basedir + "/current")
# TODO: merge
os.remove(self.basedir + "/old")
def send(self, interface):
pass
def save(self):
pass
def content(self):
return {'default': []}
# Copyright (c) 2018 Julien Lepiller <julien@lepiller.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
####
""" The gitlab system connector. """
from .git import GitProject
class GitlabProject(GitProject):
def __init__(self, conf, name, lang, data = {}):
GitProject.__init__(self, conf, name, lang, data)
def updateURI(self):
self.uri = self.data['site'] + "/" + self.data['project'] + ".git"
# Copyright (c) 2018 Julien Lepiller <julien@lepiller.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
####
""" The listo of system connectors. """
TRANSLATION_PROJECT = 0
TRANSIFEX = 1
GITLAB = 2
......@@ -28,6 +28,10 @@ from urllib.parse import unquote
from .manager import ProjectManager
from .spellcheckedit import SpellCheckEdit
from .tagclickedit import TagClickEdit
from .multiplelineedit import MultipleLineEdit
from .systems.list import *
from .formats.list import *
class ProjectTab(QTabWidget):
def __init__(self, parent = None):
......@@ -305,6 +309,7 @@ class NewWindow(QDialog):
self.combo = QComboBox()
self.combo.addItem(self.tr("The Translation Project"))
self.combo.addItem(self.tr("Transifex"))
self.combo.addItem(self.tr("Gitlab"))
self.formLayout.addRow(self.combo)
self.nameWidget.textChanged.connect(self.modify)
......@@ -324,12 +329,40 @@ class NewWindow(QDialog):
self.additionalFields = []
self.additionalFields.append([])
self.additionalFields.append([])
self.additionalFields.append([])
# Transifex
self.transifexOrganisation = QLineEdit()
self.transifexOrganisation.textChanged.connect(self.modify)
transifexOrganisationLabel = QLabel(self.tr("Organization"))
self.additionalFields[1].append({'label': transifexOrganisationLabel,
self.additionalFields[TRANSIFEX].append({'label': transifexOrganisationLabel,
'widget': self.transifexOrganisation})
# Gitlab
self.gitlabSite = QLineEdit()
self.gitlabSite.textChanged.connect(self.modify)
gitlabSiteLabel = QLabel(self.tr('hosting website'))
self.additionalFields[GITLAB].append({'label': gitlabSiteLabel,
'widget': self.gitlabSite})
self.gitlabProject = QLineEdit()
self.gitlabProject.textChanged.connect(self.modify)
gitlabProjectLabel = QLabel(self.tr('project part'))
self.additionalFields[GITLAB].append({'label': gitlabProjectLabel,
'widget': self.gitlabProject})
self.gitlabFileTypeCombo = QComboBox()
self.gitlabFileTypeCombo.addItem(format_list[0])
self.gitlabFileTypeCombo.addItem(format_list[1])
self.gitlabFileTypeCombo.addItem(format_list[2])
self.gitlabFileTypeCombo.currentIndexChanged.connect(self.modify)
gitlabFileTypeLabel = QLabel(self.tr('Translation type'))
self.additionalFields[GITLAB].append({'label': gitlabFileTypeLabel,
'widget': self.gitlabFileTypeCombo})
self.gitlabLocations = MultipleLineEdit()
self.gitlabLocations.textChanged.connect(self.modify)
gitlabLocationsLabel = QLabel(self.tr('Locations'))
self.additionalFields[GITLAB].append({'label': gitlabLocationsLabel,
'widget': self.gitlabLocations})
self.setLayout(hbox)
self.predefinedprojects.currentItemChanged.connect(self.fill)
......@@ -347,8 +380,13 @@ class NewWindow(QDialog):
data = item.data(Qt.UserRole)
self.nameWidget.setText(data['name'])
self.combo.setCurrentIndex(int(data['system']))
if data['system'] == 1:
if data['system'] == TRANSIFEX:
self.transifexOrganisation.setText(data['organisation'])
if data['system'] == GITLAB:
self.gitlabSite.setText(data['site'])
self.gitlabProject.setText(data['project'])
self.gitlabFileTypeCombo.setCurrentIndex(data['format'])
self.gitlabLocations.setText(data['locations'])
def filter(self):
search = self.searchfield.text()
......@@ -365,7 +403,7 @@ class NewWindow(QDialog):
if self.nameWidget.text() != '' and self.langWidget.text() != '':
enable = True
for widget in self.additionalFields[self.combo.currentIndex()]:
if widget['widget'].text() == '':
if isinstance(widget['widget'], QLineEdit) and widget['widget'].text() == '':
enable = False
break
self.okbutton.setEnabled(enable)
......@@ -383,10 +421,15 @@ class NewWindow(QDialog):
return self.combo.currentIndex()
def getProjectInfo(self):
if self.getProjectSystem() == 0:
if self.getProjectSystem() == TRANSLATION_PROJECT:
return {}
if self.getProjectSystem() == 1:
return {'organization': self.additionalFields[1][0]['widget'].text()}
if self.getProjectSystem() == TRANSIFEX:
return {'organization': self.additionalFields[TRANSIFEX][0]['widget'].text()}
if self.getProjectSystem() == GITLAB:
return {'site': self.additionalFields[GITLAB][0]['widget'].text(),
'project': self.additionalFields[GITLAB][1]['widget'].text(),
'format': self.additionalFields[GITLAB][2]['widget'].currentIndex(),
'locations': self.additionalFields[GITLAB][3]['widget'].content()}
return {}
def othersystem(self):
......
......@@ -12,7 +12,7 @@ setup (
version="0.2.0",
packages=find_packages(exclude=['.guix-profile*']),
python_requires = '>=3',
install_requires=['polib', 'ruamel.yaml', 'python-dateutil', 'PyQt5'],
install_requires=['polib', 'ruamel.yaml', 'python-dateutil', 'PyQt5', 'pygit2'],
entry_points={
'gui_scripts': [
'offlate=offlate.window:main',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment