Skip to content
Snippets Groups Projects
Commit f7c18d29 authored by Thiago H. S. Picharski's avatar Thiago H. S. Picharski
Browse files

Merge remote branch 'le-installpkgs/master'

parents 8c00258b b244079b
No related branches found
No related tags found
No related merge requests found
Showing
with 2261 additions and 0 deletions
1.0.2
#!/bin/bash
# gerar.sh
# Copyright (c) 2006 by Bruno Ribas <ribas@ufpr.br>
DIRTMP=$(mktemp -d)
VERSAO=$(cat VERSAO)
#arrumar versao
#$1 tipo de incremento
MAJOR=$(echo $VERSAO| cut -d'.' -f1)
MINOR=$(echo $VERSAO| cut -d'.' -f2)
REVISION=$(echo $VERSAO| cut -d'.' -f3)
case $1 in
Minor)
((MINOR++))
REVISION=0
;;
Major)
((MAJOR++))
MINOR=0
REVISION=0
;;
help)
echo "Uso: $0 Major|Minor|Revision"
echo ' Major - Altera versao Major'
echo ' Minor - Altera versao Minor'
exit
;;
*)
((REVISION++))
;;
esac
VERSAO="${MAJOR}.${MINOR}.${REVISION}"
echo "$VERSAO" > VERSAO
#Compila a documentacao do pacote no diretorio doc/
#cd doc/
#hevea -text *.tex
#hevea -text *.tex
#cd ../
cp -a pacote $DIRTMP
#Copia a documentacao compilada para dentro do pacote.
#cp doc/*.txt $DIRTMP/pacote/usr/share/doc/prd-*
cd $DIRTMP
find . -name ".git" -exec rm -rf {} \; &>/dev/null
sed -i -e "s/Version:/Version: $VERSAO/" pacote/DEBIAN/control
fakeroot dpkg -b pacote .
cd -
cp $DIRTMP/*deb .
rm -rf $DIRTMP
# vim:tabstop=4:shiftwidth=4:encoding=iso-8859-1
Package: le-installpkgs
Priority: important
Section: main
Version:
Architecture: i386
Maintainer: LE Maintainer <le-maintainer@c3sl.ufpr.br>
Depends: python (>=2.6), python-apt, python-qt4
Description: Application to help LE users to install educational contents
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from leinstallpkgs import main
from PyQt4 import QtGui
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mainwindow = main.MainWindow()
mainwindow.show()
sys.exit(app.exec_())
Metadata-Version: 1.1
Name: le-installpkgs
Version: 1.0
Summary: Install educational content on LE
Home-page: http://www.inf.ufpr.br/dgp06
Author: Diego Giovane Pasqualin
Author-email: dpasqualin@gmail.com
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
Requires: apt
Requires: PyQt4
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'interface.ui'
#
# Created: Mon Oct 24 12:07:20 2011
# by: PyQt4 UI code generator 4.8.5
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(605, 556)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "Ferramenta de Instalação de Conteúdos Educacionais", None, QtGui.QApplication.UnicodeUTF8))
MainWindow.setLayoutDirection(QtCore.Qt.LeftToRight)
MainWindow.setAutoFillBackground(False)
MainWindow.setTabShape(QtGui.QTabWidget.Rounded)
MainWindow.setDockOptions(QtGui.QMainWindow.AllowTabbedDocks|QtGui.QMainWindow.AnimatedDocks)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.verticalLayout_5 = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout_5.setObjectName(_fromUtf8("verticalLayout_5"))
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setContentsMargins(10, -1, 10, -1)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.label_4 = QtGui.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setItalic(True)
self.label_4.setFont(font)
self.label_4.setText(QtGui.QApplication.translate("MainWindow", "Selecione os pacotes do seu interesse (clique em \">\") e pressione o botão Instalar", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setObjectName(_fromUtf8("label_4"))
self.verticalLayout.addWidget(self.label_4)
spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
self.verticalLayout.addItem(spacerItem)
self.horizontalLayout_3 = QtGui.QHBoxLayout()
self.horizontalLayout_3.setContentsMargins(0, -1, 0, 5)
self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
self.verticalLayout_2 = QtGui.QVBoxLayout()
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.label = QtGui.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label.setFont(font)
self.label.setText(QtGui.QApplication.translate("MainWindow", "Pacotes disponíveis para download", None, QtGui.QApplication.UnicodeUTF8))
self.label.setObjectName(_fromUtf8("label"))
self.verticalLayout_2.addWidget(self.label)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.searchField = QtGui.QLineEdit(self.centralwidget)
self.searchField.setObjectName(_fromUtf8("searchField"))
self.horizontalLayout.addWidget(self.searchField)
self.searchButton = QtGui.QPushButton(self.centralwidget)
self.searchButton.setText(QtGui.QApplication.translate("MainWindow", "Buscar", None, QtGui.QApplication.UnicodeUTF8))
self.searchButton.setObjectName(_fromUtf8("searchButton"))
self.horizontalLayout.addWidget(self.searchButton)
self.verticalLayout_2.addLayout(self.horizontalLayout)
self.viewAvailablePackages = QtGui.QListView(self.centralwidget)
self.viewAvailablePackages.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.viewAvailablePackages.setObjectName(_fromUtf8("viewAvailablePackages"))
self.verticalLayout_2.addWidget(self.viewAvailablePackages)
self.horizontalLayout_3.addLayout(self.verticalLayout_2)
self._2 = QtGui.QVBoxLayout()
self._2.setSpacing(0)
self._2.setSizeConstraint(QtGui.QLayout.SetFixedSize)
self._2.setContentsMargins(-1, 0, -1, 0)
self._2.setObjectName(_fromUtf8("_2"))
spacerItem1 = QtGui.QSpacerItem(0, 80, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
self._2.addItem(spacerItem1)
self.addPackageButton = QtGui.QPushButton(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.addPackageButton.sizePolicy().hasHeightForWidth())
self.addPackageButton.setSizePolicy(sizePolicy)
self.addPackageButton.setMaximumSize(QtCore.QSize(25, 16777215))
self.addPackageButton.setText(QtGui.QApplication.translate("MainWindow", ">", None, QtGui.QApplication.UnicodeUTF8))
self.addPackageButton.setObjectName(_fromUtf8("addPackageButton"))
self._2.addWidget(self.addPackageButton)
self.rmPackageButton = QtGui.QPushButton(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.rmPackageButton.sizePolicy().hasHeightForWidth())
self.rmPackageButton.setSizePolicy(sizePolicy)
self.rmPackageButton.setMinimumSize(QtCore.QSize(0, 0))
self.rmPackageButton.setMaximumSize(QtCore.QSize(25, 16777215))
self.rmPackageButton.setText(QtGui.QApplication.translate("MainWindow", "<", None, QtGui.QApplication.UnicodeUTF8))
self.rmPackageButton.setObjectName(_fromUtf8("rmPackageButton"))
self._2.addWidget(self.rmPackageButton)
self.horizontalLayout_3.addLayout(self._2)
self.verticalLayout_3 = QtGui.QVBoxLayout()
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
self.label_2 = QtGui.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_2.setFont(font)
self.label_2.setText(QtGui.QApplication.translate("MainWindow", "Pacotes selecionados para instalação", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setObjectName(_fromUtf8("label_2"))
self.verticalLayout_3.addWidget(self.label_2)
spacerItem2 = QtGui.QSpacerItem(20, 30, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
self.verticalLayout_3.addItem(spacerItem2)
self.viewSelectedPackages = QtGui.QListView(self.centralwidget)
self.viewSelectedPackages.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.viewSelectedPackages.setObjectName(_fromUtf8("viewSelectedPackages"))
self.verticalLayout_3.addWidget(self.viewSelectedPackages)
self.horizontalLayout_3.addLayout(self.verticalLayout_3)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.verticalLayout_4 = QtGui.QVBoxLayout()
self.verticalLayout_4.setContentsMargins(0, -1, 0, 0)
self.verticalLayout_4.setObjectName(_fromUtf8("verticalLayout_4"))
self.label_3 = QtGui.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_3.setFont(font)
self.label_3.setText(QtGui.QApplication.translate("MainWindow", "Descrição:", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setObjectName(_fromUtf8("label_3"))
self.verticalLayout_4.addWidget(self.label_3)
self.packageDescription = QtGui.QPlainTextEdit(self.centralwidget)
self.packageDescription.setSizeIncrement(QtCore.QSize(0, 0))
self.packageDescription.setBaseSize(QtCore.QSize(0, 0))
self.packageDescription.setAutoFillBackground(True)
self.packageDescription.setReadOnly(True)
self.packageDescription.setObjectName(_fromUtf8("packageDescription"))
self.verticalLayout_4.addWidget(self.packageDescription)
self.horizontalLayout_2 = QtGui.QHBoxLayout()
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
spacerItem3 = QtGui.QSpacerItem(488, 13, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem3)
self.installPackagesButton = QtGui.QPushButton(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.installPackagesButton.sizePolicy().hasHeightForWidth())
self.installPackagesButton.setSizePolicy(sizePolicy)
self.installPackagesButton.setLayoutDirection(QtCore.Qt.RightToLeft)
self.installPackagesButton.setText(QtGui.QApplication.translate("MainWindow", "Instalar", None, QtGui.QApplication.UnicodeUTF8))
self.installPackagesButton.setObjectName(_fromUtf8("installPackagesButton"))
self.horizontalLayout_2.addWidget(self.installPackagesButton)
self.verticalLayout_4.addLayout(self.horizontalLayout_2)
self.verticalLayout.addLayout(self.verticalLayout_4)
self.verticalLayout_5.addLayout(self.verticalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.statusBar = QtGui.QStatusBar(MainWindow)
self.statusBar.setMinimumSize(QtCore.QSize(0, 0))
font = QtGui.QFont()
font.setItalic(False)
self.statusBar.setFont(font)
self.statusBar.setToolTip(_fromUtf8(""))
self.statusBar.setStatusTip(_fromUtf8(""))
self.statusBar.setLayoutDirection(QtCore.Qt.RightToLeft)
self.statusBar.setAutoFillBackground(True)
self.statusBar.setObjectName(_fromUtf8("statusBar"))
MainWindow.setStatusBar(self.statusBar)
self.retranslateUi(MainWindow)
QtCore.QObject.connect(self.searchField, QtCore.SIGNAL(_fromUtf8("returnPressed()")), self.searchButton.click)
QtCore.QObject.connect(self.searchField, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), self.searchButton.click)
QtCore.QObject.connect(self.viewAvailablePackages, QtCore.SIGNAL(_fromUtf8("doubleClicked(QModelIndex)")), self.addPackageButton.click)
QtCore.QObject.connect(self.viewSelectedPackages, QtCore.SIGNAL(_fromUtf8("doubleClicked(QModelIndex)")), self.rmPackageButton.click)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
pass
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'uifiles/progress.ui'
#
# Created: Wed Feb 23 12:31:58 2011
# by: PyQt4 UI code generator 4.7.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
mainWindow.resize(441, 260)
self.statusLabel = QtGui.QLabel(mainWindow)
self.statusLabel.setGeometry(QtCore.QRect(20, 20, 101, 16))
font = QtGui.QFont()
font.setWeight(75)
font.setBold(True)
self.statusLabel.setFont(font)
self.statusLabel.setObjectName("statusLabel")
self.progressBar = QtGui.QProgressBar(mainWindow)
self.progressBar.setGeometry(QtCore.QRect(20, 40, 401, 23))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.progressText = QtGui.QPlainTextEdit(mainWindow)
self.progressText.setGeometry(QtCore.QRect(20, 80, 401, 131))
self.progressText.setUndoRedoEnabled(False)
self.progressText.setReadOnly(True)
self.progressText.setObjectName("progressText")
self.pkgInstallingLabel = QtGui.QLabel(mainWindow)
self.pkgInstallingLabel.setGeometry(QtCore.QRect(120, 20, 301, 17))
self.pkgInstallingLabel.setText("")
self.pkgInstallingLabel.setObjectName("pkgInstallingLabel")
self.buttonOK = QtGui.QPushButton(mainWindow)
self.buttonOK.setGeometry(QtCore.QRect(330, 220, 91, 27))
self.buttonOK.setObjectName("buttonOK")
self.buttonCancel = QtGui.QPushButton(mainWindow)
self.buttonCancel.setGeometry(QtCore.QRect(220, 220, 98, 27))
self.buttonCancel.setObjectName("buttonCancel")
self.retranslateUi(mainWindow)
QtCore.QObject.connect(self.buttonOK, QtCore.SIGNAL("clicked()"), mainWindow.accept)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
def retranslateUi(self, mainWindow):
mainWindow.setWindowTitle(QtGui.QApplication.translate("mainWindow", "Instalação Pacotes Educacionais", None, QtGui.QApplication.UnicodeUTF8))
self.statusLabel.setText(QtGui.QApplication.translate("mainWindow", "Instalando...", None, QtGui.QApplication.UnicodeUTF8))
self.buttonOK.setText(QtGui.QApplication.translate("mainWindow", "OK", None, QtGui.QApplication.UnicodeUTF8))
self.buttonCancel.setText(QtGui.QApplication.translate("mainWindow", "Cancelar", None, QtGui.QApplication.UnicodeUTF8))
MAIN=../interface.py
PROG=../progressUI.py
UIFILES=.
all: interface progress
interface: $(UIFILES)/interface.ui
pyuic4 $^ -o $(MAIN)
progress: $(UIFILES)/progress.ui
pyuic4 $^ -o $(PROG)
<?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>605</width>
<height>556</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Ferramenta de Instalação de Conteúdos Educacionais</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="dockOptions">
<set>QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks</set>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Selecione os pacotes do seu interesse (clique em &quot;&gt;&quot;) e pressione o botão Instalar</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Pacotes disponíveis para download</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="searchField"/>
</item>
<item>
<widget class="QPushButton" name="searchButton">
<property name="text">
<string>Buscar</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListView" name="viewAvailablePackages">
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="_2" stretch="0,0,0">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>80</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="addPackageButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="rmPackageButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&lt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Pacotes selecionados para instalação</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>30</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QListView" name="viewSelectedPackages">
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Descrição:</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="packageDescription">
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>488</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="installPackagesButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Instalar</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<italic>false</italic>
</font>
</property>
<property name="toolTip">
<string/>
</property>
<property name="statusTip">
<string/>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>searchField</sender>
<signal>returnPressed()</signal>
<receiver>searchButton</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>185</x>
<y>83</y>
</hint>
<hint type="destinationlabel">
<x>265</x>
<y>84</y>
</hint>
</hints>
</connection>
<connection>
<sender>searchField</sender>
<signal>textChanged(QString)</signal>
<receiver>searchButton</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>125</x>
<y>83</y>
</hint>
<hint type="destinationlabel">
<x>272</x>
<y>83</y>
</hint>
</hints>
</connection>
<connection>
<sender>viewAvailablePackages</sender>
<signal>doubleClicked(QModelIndex)</signal>
<receiver>addPackageButton</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>261</x>
<y>166</y>
</hint>
<hint type="destinationlabel">
<x>355</x>
<y>163</y>
</hint>
</hints>
</connection>
<connection>
<sender>viewSelectedPackages</sender>
<signal>doubleClicked(QModelIndex)</signal>
<receiver>rmPackageButton</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>452</x>
<y>220</y>
</hint>
<hint type="destinationlabel">
<x>351</x>
<y>210</y>
</hint>
</hints>
</connection>
</connections>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>mainWindow</class>
<widget class="QDialog" name="mainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>441</width>
<height>260</height>
</rect>
</property>
<property name="windowTitle">
<string>Instalação Pacotes Educacionais</string>
</property>
<widget class="QLabel" name="statusLabel">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>101</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Instalando...</string>
</property>
</widget>
<widget class="QProgressBar" name="progressBar">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>401</width>
<height>23</height>
</rect>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
<widget class="QPlainTextEdit" name="progressText">
<property name="geometry">
<rect>
<x>20</x>
<y>80</y>
<width>401</width>
<height>131</height>
</rect>
</property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="pkgInstallingLabel">
<property name="geometry">
<rect>
<x>120</x>
<y>20</y>
<width>301</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QPushButton" name="buttonOK">
<property name="geometry">
<rect>
<x>330</x>
<y>220</y>
<width>91</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton" name="buttonCancel">
<property name="geometry">
<rect>
<x>220</x>
<y>220</y>
<width>98</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>Cancelar</string>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonOK</sender>
<signal>clicked()</signal>
<receiver>mainWindow</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>375</x>
<y>233</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, re, apt, threading, os
from PyQt4 import QtGui,QtCore,Qt
from PyQt4.QtCore import *
from leinstallpkgs.gui.interface import Ui_MainWindow
from leinstallpkgs.myprogress import Qt4AptProgress
from threading import Thread
class MyApt(apt.Cache,apt.Package):
def __init__(self, progressopen=None):
apt.Cache.__init__(self,progressopen)
def getInstalledPackages(self, regex=None):
""" Returns installed packages according to regex, or all installed
packages if regex is None """
if regex:
regex = re.compile(regex)
lf = lambda pkg: pkg.is_installed and regex.match(pkg.name)
else:
lf = lambda pkg: pkg.is_installed
return [pkg.name for pkg in self if lf(pkg) ]
def getAvailablePackages(self, regex=None):
""" Returns available packages according to regex, or all available
packages if regex is None """
if regex:
regex = re.compile(regex)
lf = lambda pkg: regex.match(pkg.name)
return [ pkg.name for pkg in self if lf(pkg) ]
else:
return self.keys()
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Set up the user interface from Designer
self.setupUi(self)
# Only root can install new packages
if not self.imRoot():
QtGui.QMessageBox.information(self,
u"Informação",
u"Você precisa ser root para instalar novos pacotes. O aplicativo irá iniciar com recursos limitados.")
self.installPackagesButton.setEnabled(False)
self.statusBarChangeMessage("Carregando lista de pacotes...", 0)
# Progress Dialog
self.progress = Qt4AptProgress(self)
# Configuring widgets
self.mainViewModel = QtGui.QStandardItemModel()
self.viewAvailablePackages.setModel(self.mainViewModel)
self.viewSelectedPackages.setModel(QtGui.QStandardItemModel())
# Load packages list using a different thread
Thread(None,self.loadAptCache).start()
def imRoot(self):
return os.geteuid() == 0 and True or False
def loadAptCache(self):
""" This method loads apt cache into self.__myapt var and fills the
listview with the packages found. """
self.__myapt = MyApt(self.progress.open())
self.fillAvailablePackagesList()
# Connect signals
self.connectSignals()
self.emit(QtCore.SIGNAL("messageChanged(PyQt_PyObject)"), "Pronto...")
def statusBarChangeMessage(self, msg, timeout=2000):
""" Called to change statusBar displaying message """
self.statusBar.showMessage(msg, timeout)
def connectSignals(self):
""" Connect the signals that couldn't be connected on qtdesigner
Tuple: (widget, signal, handler) """
connectList = [(self,
"messageChanged(PyQt_PyObject)",
self.statusBarChangeMessage),
(self.searchButton,
"clicked()",
self.searchButtonClicked),
(self.viewAvailablePackages.selectionModel(),
"selectionChanged(QItemSelection,QItemSelection)",
self.viewAvailablePackagesSelected),
(self.addPackageButton,
"clicked()",
self.addPackageButtonClicked),
(self.rmPackageButton,
"clicked()",
self.rmPackageButtonClicked),
(self.installPackagesButton,
"clicked()",
self.installPackagesButtonClicked)
]
for widget,sig,handler in connectList:
self.connect(widget,QtCore.SIGNAL(sig),handler)
def viewAvailablePackagesSelected(self, selected, deselected):
""" This method is called when the user selects a package from
available packages list. The effect is print the package description
into the description text widget. """
items = self.getSelectedItemString()
if (items and (len(items) == 1)):
description = self.getPackageDescription(items[0])
else:
description = ""
self.setPackageDescription(description)
def setPackageDescription(self, description):
""" Write description received into package description widget """
self.packageDescription.setPlainText(description)
def getPackageDescription(self, pkg):
""" Returns the description of package pkg """
return self.__myapt[pkg].description
def fillAvailablePackagesList(self):
""" Fill the availablePackagesList widget """
for pkg in self.getMECPackages():
self.addItemToModel(self.mainViewModel, pkg)
self.sortModel(self.viewAvailablePackages.model())
def sortModel(self, model):
""" Sort a QListView alphabetically """
model.sort(0)
def findItemFromModel(self, model, text):
""" Find an item named "text" from a QListView and return its index """
matches = model.match(model.index(0, 0), Qt.DisplayRole, text);
if (len(matches) > 0):
return matches[0]
else:
return None
def rmItemFromModel(self, model, text):
""" Remove the item with the content "text" from a QListView """
item = self.findItemFromModel(model, text);
if item:
model.removeRow(item.row())
def addItemToModel(self, model, text, idx=None):
""" Add an item named "text" to a model "model" at index "idx" """
item = QtGui.QStandardItem(text)
item.setEditable(False)
if idx:
model.setItem(idx, item)
else:
model.appendRow(item)
def getDataFromIndexes(self, indexes):
""" Return a list with text found in each index (probably from a
selection on a listView) """
return [ str(i.data().toString()) for i in indexes ]
def getSelectedItem(self, listview=None):
""" Returns selected item at ListView, or None if there is any """
if listview == None:
listview = self.viewAvailablePackages
idxs = listview.selectedIndexes()
if (len(idxs) > 0):
return idxs
else:
return None
def getSelectedItemString(self, model=None):
""" Returns the string associated with the selected item at ListView,
or None if there is any selected item """
if model == None:
model = self.viewAvailablePackages
idxs = model.selectedIndexes()
if (len(idxs) > 0):
return self.getDataFromIndexes(idxs)
else:
return None
def getMECPackages(self):
""" Returns a list with all MEC packages available which if not
installed on system """
regex = "mec-.*"
available = self.__myapt.getAvailablePackages(regex)
installed = self.__myapt.getInstalledPackages(regex)
return [ i for i in available if i not in installed ]
def getSearchParam(self):
""" Return text typed on searchField formatted """
return str(self.searchField.text()).strip().lower().decode()
def searchPackages(self, param):
""" Return packages that matchs param, using the name and
description of it """
model = self.mainViewModel
result = []
for i in range(model.rowCount()):
pkgname = str(model.item(i).text()).lower()
pkgdesc = self.getPackageDescription(pkgname).lower()
if param in pkgname or param in pkgdesc:
result.append(model.item(i))
return result
def searchButtonClicked(self):
""" This method is called when the user clicks on "Search" button,
and its purpose is find a package matching the given string """
param = self.getSearchParam()
if not param:
newmodel = self.mainViewModel
else:
items = self.searchPackages(param)
newmodel = QtGui.QStandardItemModel()
for i in items:
newmodel.appendRow(i.clone())
self.viewAvailablePackages.setModel(newmodel)
ism = QtGui.QItemSelectionModel(newmodel)
self.viewAvailablePackages.setSelectionModel(ism)
sig = "selectionChanged(QItemSelection,QItemSelection)"
self.connect(self.viewAvailablePackages.selectionModel(),
QtCore.SIGNAL(sig),
self.viewAvailablePackagesSelected)
def addPackageButtonClicked(self):
""" Method called when user selects a new package to install """
items = self.getSelectedItemString(self.viewAvailablePackages)
for i in items:
self.rmItemFromModel(self.mainViewModel, i)
self.addItemToModel(self.viewSelectedPackages.model(), i)
self.sortModel(self.viewSelectedPackages.model())
def rmPackageButtonClicked(self):
""" Method called when user removes a package from selection to
install """
items = self.getSelectedItemString(self.viewSelectedPackages)
for i in items:
self.rmItemFromModel(self.viewSelectedPackages.model(), i)
self.addItemToModel(self.mainViewModel, i)
self.sortModel(self.mainViewModel)
def myapt(self):
return self.__myapt
def installPackagesButtonClicked(self):
""" Method called when user clicks on install button """
n = self.viewSelectedPackages.model().rowCount()
for i in range(n):
pkg = str(self.viewSelectedPackages.model().item(i).text())
self.__myapt[pkg].mark_install()
if self.__myapt.get_changes():
f, i = self.progress.acquire(), self.progress.install()
thread = MyAptCommitThread(self)
thread.start()
# Wait for dialog finish and check return result
# If everything went ok, clear listview
if self.progress.exec_() == self.progress.Accepted:
for i in range(n):
self.viewSelectedPackages.model().removeRow(0)
class MyAptCommitThread(QtCore.QThread):
""" Use a differente thread to commit apt changes """
def __init__(self, parent):
QtCore.QThread.__init__(self, parent)
self.myapt = parent.myapt()
self.progress = parent.progress
def run(self):
try:
acquire = self.progress.acquire()
install = self.progress.install()
self.myapt.commit(acquire, install)
# TODO: Only clear the list if the process went OK
self.myapt.clear()
except apt.cache.LockFailedException:
text = "Aplicativo de instalação de pacotes já em uso, tente\
novamente em alguns minutos."
self.progress.error(text)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, re, os, apt, time
from PyQt4 import QtGui,QtCore
from leinstallpkgs.gui.progressUI import Ui_mainWindow
from apt.progress import base
class Qt4InstallProgress(QtCore.QObject, base.InstallProgress):
""" Installation progress with Qt4 signals"""
INSTALL_TIMEOUT = 5*60
def __init__(self):
base.InstallProgress.__init__(self)
QtCore.QObject.__init__(self)
self.apt_status = -1
self.finished = False
self.time_last_update = time.time()
def error(self, pkg, errormsg):
""" Called when a error is detected during the install """
#base.InstallProgress.error(self, pkg, errormsg)
self.emit(QtCore.SIGNAL("statusError()"))
print "error", self, pkg, errormsg
def processing(self, pkg, stage):
""" This method is called just before a processing stage starts.
The parameter pkg is the name of the package and the parameter
stage is one of the stages listed in the dpkg manual under the
status-fd option, i.e. "upgrade", "install" (both sent before
unpacking), "configure", "trigproc", "remove", "purge". """
#base.InstallProgress.processing(self, pkg, state)
self.emit(QtCore.SIGNAL("statusChanged(PyQt_PyObject)", pkg))
print "Processing", self, pkg, stage
def start_update(self):
""" Called when the update starts. """
print "start_update"
self.emit(QtCore.SIGNAL("statusStarted()"))
def run(self, obj):
""" Run. """
self.finished = False
return base.InstallProgress.run(self, obj)
print "run"
def finish_update(self):
""" Called when the update finished. """
self.emit(QtCore.SIGNAL("statusFinished()"))
print "finish_update"
def processing(self, pkg, stage):
""" Called when entering a new stage in dpkg. """
# We have no porcentage or alike send -1 to let the bar pulse.
self.emit(QtCore.SIGNAL("statusChanged(PyQt_PyObject)"), pkg)
print "processing"
def status_change(self, pkg, percent, status):
""" This method implements progress reporting for package
installation by APT and may be extended to dpkg at a later time.
This method takes two parameters: The parameter percent is a float
value describing the overall progress and the parameter status is a
string describing the current status in an human-readable manner """
base.InstallProgress.status_change(self, pkg, percent, status)
self.time_last_update = time.time()
self.emit(QtCore.SIGNAL("statusChanged(PyQt_PyObject,PyQt_PyObject)"),
status, percent)
print "status_change"
def update_interface(self):
""" Called periodically to update the interface. """
base.InstallProgress.update_interface(self)
if self.time_last_update + self.INSTALL_TIMEOUT < time.time():
self.emit(QtCore.SIGNAL("statusTimeout()"))
def child_exited(self, term, pid, status):
""" Called when a child process exits """
self.apt_status = os.WEXITSTATUS(status)
self.finished = True
print "child_exited"
class Qt4AcquireProgress(QtCore.QObject, base.AcquireProgress):
""" A Fetch Progress with Qt4 signals"""
def __init__(self):
base.AcquireProgress.__init__(self)
QtCore.QObject.__init__(self)
self._continue = True
def cancel(self):
self._continue = False
def done(self, item):
"""Invoked when an item is successfully and completely fetched """
base.AcquireProgress.done(self, item)
print "Done:", self, item
def fail(self, item):
base.AcquireProgress.fail(self, item)
self.emit(QtCore.SIGNAL("statusError()"))
print "Fail", self, item
def fetch(self, item):
base.AcquireProgress.fetch(self, item)
print "Fetch", self, item
def pulse(self, owner):
base.AcquireProgress.pulse(self, owner)
current_item = self.current_items + 1
if current_item > self.total_items:
current_item = self.total_items
if self.current_cps > 0:
text = ("Baixando arquivo %(current)li de %(total)li a "
"%(speed)s/s") % \
{"current": current_item,
"total": self.total_items,
"speed": apt.apt_pkg.size_to_str(self.current_cps)}
else:
text = ("Baixando arquivo %(current)li de %(total)li") % \
{"current": current_item,
"total": self.total_items}
percent = (((self.current_bytes + self.current_items) * 100.0) /
float(self.total_bytes + self.total_items))
self.emit(QtCore.SIGNAL("statusChanged(PyQt_PyObject,PyQt_PyObject)"),
text, percent)
return self._continue
def start(self):
base.AcquireProgress.start(self)
self.emit(QtCore.SIGNAL("statusStarted()"))
print "Start", self
def stop(self):
base.AcquireProgress.stop(self)
self.emit(QtCore.SIGNAL("statusFinished()"))
print "Stop", self
class Qt4OpProgress(QtCore.QObject, base.OpProgress):
""" Operation progress with Qt4 signals. """
def __init__(self):
base.OpProgress.__init__(self)
QtCore.QObject.__init__(self)
def done(self):
""" Called when all operation have finished. """
base.OpProgress.done(self)
self.emit(QtCore.SIGNAL("statusFinished()"))
print "Done", self
def update(self, percent=None):
""" Called to update the percentage done. """
base.OpProgress.update(self, percent)
self.emit(QtCore.SIGNAL("statusChanged(PyQt_PyObject,PyQt_PyObject)"),
self.op, self.percent)
class Qt4AptProgress(QtCore.QObject):
""" Graphical progress for installation/fetch/operations.
This widget provides a progress bar, a terminal and a status bar for
showing the progress of package manipulation tasks. """
def __init__(self, parent=None):
QtCore.QObject.__init__(self)
self._dialog = Qt4ProgressGui(parent)
self._progress_open = Qt4OpProgress()
self._progress_acquire = Qt4AcquireProgress()
self._progress_install = Qt4InstallProgress()
# If something goes wrong this flag is set to False and the process
# stops
self._continue = True
# Some defines to get the return result easily
self.Accepted = self._dialog.Accepted
self.Rejected = self._dialog.Rejected
# Connect signals
progress_op_signals = {
"statusChanged(PyQt_PyObject,PyQt_PyObject)":
self._on_status_changed,
"statusStarted()": self._on_status_started,
"statusFinished()": self._on_status_finished }
acquire_signals = {
"statusChanged(PyQt_PyObject,PyQt_PyObject)":
self._on_status_changed,
"statusError()": self._on_acquire_error,
"statusStarted()": self._on_acquire_started,
"statusFinished()": self._on_acquire_finished }
progress_install_signals = {
"statusChanged(PyQt_PyObject,PyQt_PyObject)":
self._on_status_changed,
"statusStarted()": self._on_status_started,
"statusFinished()": self._on_status_finished,
"statusTimeout()": self._on_status_timeout,
"statusError()": self._on_status_timeout,
"statusConffile()": self._on_status_timeout }
# Dialog signals
self._dialog.buttonOK.connect(self._dialog.buttonCancel,
QtCore.SIGNAL("clicked()"),
self.cancel_download)
self.connect(self, QtCore.SIGNAL("externalError(PyQt_PyObject)"),
self._externalError)
self._connect_signals(self._progress_open, progress_op_signals)
self._connect_signals(self._progress_acquire, acquire_signals)
self._connect_signals(self._progress_install, progress_install_signals)
def _on_acquire_error(self):
text = "Ocorreu um erro ao baixar o(s) pacote(s)."
self._externalError(text)
def _on_acquire_started(self):
self.dialog().setCancel(True)
self.dialog().setOk(False)
def _on_acquire_finished(self):
self.dialog().setCancel(False)
def _connect_signals(self, obj, signals):
""" Connect obj signals """
for signal, slot in signals.items():
obj.connect(obj,QtCore.SIGNAL(signal),slot)
def open(self):
"""Return the cache opening progress handler."""
return self._progress_open
def install(self):
"""Return the install progress handler."""
return self._progress_install
def acquire(self):
"""Return the acquire progress handler."""
return self._progress_acquire
def dialog(self):
return self._dialog
def error(self, text):
""" This method stops execution and print text as error message """
self.emit(QtCore.SIGNAL("externalError(PyQt_PyObject)"),text)
def _externalError(self, text):
""" This method stops execution and print text as error message """
self._continue = False
self._dialog.setPkgInstallingText(text)
self._dialog.pulse(100.0)
self._dialog.addText(text)
self._dialog.setStatusLabelText("ERRO!", "red")
self._dialog.finished()
def _on_status_started(self):
"""Called when something starts."""
self._on_status_changed("Iniciando...", 0)
def _on_status_changed(self, status, percent=0.0):
"""Called when the status changed."""
if self._continue:
self._dialog.setPkgInstallingText(status)
self._dialog.addText(status)
if percent is None or percent == -1:
pass
else:
self._dialog.pulse(percent)
def _on_status_timeout(self):
"""Called when timeout happens."""
#self._expander.set_expanded(True)
print "TIMEOUT"
pass
def _on_status_finished(self, progress=0):
"""Called when something finished."""
self._on_status_changed("Pronto.", 100)
self._dialog.finished()
def cancel_download(self):
"""Cancel a currently running download."""
print "cancelando"
if self._dialog.shouldCancel():
self.acquire().cancel()
self._dialog.hide()
self._dialog.showInfo(u"Operação Cancelada")
def show(self):
self._dialog.show()
def exec_(self):
return self._dialog.exec_()
class Qt4ProgressGui(QtGui.QDialog, Ui_mainWindow):
""" Opens a QDialog with a progress bar and a text area """
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
# Set up the user interface from Designer
self.setupUi(self)
self.setOk(False)
self.setCancel(True)
def setCancel(self, opt):
self.buttonCancel.setEnabled(opt)
def setStatusLabelText(self, text, color="red"):
self.statusLabel.setStyleSheet("QLabel { color : %s; }" % color)
self.statusLabel.setText(str(text))
def setOk(self, opt):
self.buttonOK.setEnabled(opt)
def showInfo(self, msg):
QtGui.QMessageBox.information(self, u"Edubar", msg)
def ask(self, msg, b1, b2):
if QtGui.QMessageBox.question(self, u"Edubar", msg, b1, b2) == 0:
return True
else:
return False
def shouldCancel(self):
msg = u"Deseja cancelar o processo de instalação?"
return self.ask(msg, u"Sim", u"Não")
def finished(self):
self.buttonOK.setEnabled(True)
self.buttonCancel.setEnabled(False)
def pulse(self, percent):
self.progressBar.setValue(int(percent))
def addText(self, text):
self.progressText.appendPlainText(str(text))
def setPkgInstallingText(self, pkgname):
self.pkgInstallingLabel.setText(str(pkgname))
#def done(self):
# """ Called when the user clicks on the OK button """
# self.addText("Pronto")
# self.setPkgInstallingText("Pronto")
C3SL - Centro de Computacao Cientifica e Software Livre
Adriano da Luz
Bruno Cesar Ribas
Carlos Carvalho
Cleide Luzia Bonfim Possamai
Danilo Kiyoshi Simizu Yorinori
Diego Giovane Pasqualin
Eduardo Todt
Erik Alexandre Pucci
Felipe Cys Laskoski
Guilherme Zasyeki Machado
Josiney de Souza
Juliana Bueno
Klismann Smoger Mottin
Laura Sanchez Garcia
Luis Carlos Erpen de Bona
Marcela Saragioto
Marcos Castilho
Pedro Eugenio Rocha
Renan Franca De Miranda
Ricardo Tavares De Oliveira
Rubens Massayuki Suguimoto
Thiago Henrique Dos Santos Picharski
Tiago Rodrigo Kepe
Victor Tarabola Cortiano
Vinicius Kwiecien Ruoso
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment