From f31dee90905376aab029fb6f73b8f5cba30deaca Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Mon, 11 Mar 2013 13:39:10 +0100 Subject: [PATCH] new application qcineoob --- scripts/qcineoob | 27 +++ weboob/applications/qcineoob/__init__.py | 3 + weboob/applications/qcineoob/main_window.py | 184 +++++++++++++++++ weboob/applications/qcineoob/minimovie.py | 63 ++++++ weboob/applications/qcineoob/miniperson.py | 64 ++++++ weboob/applications/qcineoob/movie.py | 36 ++++ weboob/applications/qcineoob/person.py | 36 ++++ weboob/applications/qcineoob/qcineoob.py | 46 +++++ weboob/applications/qcineoob/ui/Makefile | 13 ++ weboob/applications/qcineoob/ui/__init__.py | 0 .../applications/qcineoob/ui/main_window.ui | 183 +++++++++++++++++ weboob/applications/qcineoob/ui/minimovie.ui | 189 ++++++++++++++++++ weboob/applications/qcineoob/ui/miniperson.ui | 189 ++++++++++++++++++ weboob/applications/qcineoob/ui/movie.ui | 79 ++++++++ weboob/applications/qcineoob/ui/person.ui | 79 ++++++++ 15 files changed, 1191 insertions(+) create mode 100755 scripts/qcineoob create mode 100644 weboob/applications/qcineoob/__init__.py create mode 100644 weboob/applications/qcineoob/main_window.py create mode 100644 weboob/applications/qcineoob/minimovie.py create mode 100644 weboob/applications/qcineoob/miniperson.py create mode 100644 weboob/applications/qcineoob/movie.py create mode 100644 weboob/applications/qcineoob/person.py create mode 100644 weboob/applications/qcineoob/qcineoob.py create mode 100644 weboob/applications/qcineoob/ui/Makefile create mode 100644 weboob/applications/qcineoob/ui/__init__.py create mode 100644 weboob/applications/qcineoob/ui/main_window.ui create mode 100644 weboob/applications/qcineoob/ui/minimovie.ui create mode 100644 weboob/applications/qcineoob/ui/miniperson.ui create mode 100644 weboob/applications/qcineoob/ui/movie.ui create mode 100644 weboob/applications/qcineoob/ui/person.ui diff --git a/scripts/qcineoob b/scripts/qcineoob new file mode 100755 index 0000000000..b4f7b0d471 --- /dev/null +++ b/scripts/qcineoob @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# vim: ft=python et softtabstop=4 cinoptions=4 shiftwidth=4 ts=4 ai + +# Copyright(C) 2010-2011 Romain Bignon +# +# This file is part of weboob. +# +# weboob 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. +# +# weboob 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 weboob. If not, see . + + +from weboob.applications.qcineoob import QCineoob + + +if __name__ == '__main__': + QCineoob.run() diff --git a/weboob/applications/qcineoob/__init__.py b/weboob/applications/qcineoob/__init__.py new file mode 100644 index 0000000000..5767c8c210 --- /dev/null +++ b/weboob/applications/qcineoob/__init__.py @@ -0,0 +1,3 @@ +from .qcineoob import QCineoob + +__all__ = ['QCineoob'] diff --git a/weboob/applications/qcineoob/main_window.py b/weboob/applications/qcineoob/main_window.py new file mode 100644 index 0000000000..1b15488580 --- /dev/null +++ b/weboob/applications/qcineoob/main_window.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Romain Bignon +# +# This file is part of weboob. +# +# weboob 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. +# +# weboob 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 weboob. If not, see . + + +from PyQt4.QtCore import SIGNAL + +from weboob.capabilities.cinema import ICapCinema +from weboob.tools.application.qt import QtMainWindow, QtDo +from weboob.tools.application.qt.backendcfg import BackendCfg + +from weboob.applications.qcineoob.ui.main_window_ui import Ui_MainWindow + +from .minimovie import MiniMovie +from .miniperson import MiniPerson +from .movie import Movie +from .person import Person + +class MainWindow(QtMainWindow): + def __init__(self, config, weboob, parent=None): + QtMainWindow.__init__(self, parent) + self.ui = Ui_MainWindow() + self.ui.setupUi(self) + + self.config = config + self.weboob = weboob + self.minimovies = [] + self.minipersons = [] + self.current_movie_widget = None + self.current_person_widget = None + + self.history = {'last_action':None,'action_list':[]} + self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack) + self.ui.backButton.setDisabled(True) + + self.connect(self.ui.searchEdit, SIGNAL("returnPressed()"), self.search) + + self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig) + + self.loadBackendsList() + + if self.ui.backendEdit.count() == 0: + self.backendsConfig() + + def backendsConfig(self): + bckndcfg = BackendCfg(self.weboob, (ICapCinema,), self) + if bckndcfg.run(): + self.loadBackendsList() + + def loadBackendsList(self): + self.ui.backendEdit.clear() + for i, backend in enumerate(self.weboob.iter_backends()): + if i == 0: + self.ui.backendEdit.addItem('All backends', '') + self.ui.backendEdit.addItem(backend.name, backend.name) + if backend.name == self.config.get('settings', 'backend'): + self.ui.backendEdit.setCurrentIndex(i+1) + + if self.ui.backendEdit.count() == 0: + self.ui.searchEdit.setEnabled(False) + else: + self.ui.searchEdit.setEnabled(True) + + def doAction(self, fun, args): + if self.history['last_action'] != None: + self.history['action_list'].append(self.history['last_action']) + self.ui.backButton.setDisabled(False) + self.history['last_action'] = {'function':fun,'args':args} + return fun(*args) + + def doBack(self): + if len(self.history['action_list']) > 0: + todo = self.history['action_list'].pop() + self.history['last_action'] = todo + if len(self.history['action_list']) == 0: + self.ui.backButton.setDisabled(True) + return todo['function'](*todo['args']) + + def search(self): + tosearch = self.ui.typeCombo.currentText() + if tosearch == 'person': + self.searchPerson() + elif tosearch == 'movie': + self.searchMovie() + + def searchMovie(self): + pattern = unicode(self.ui.searchEdit.text()) + if not pattern: + return + self.doAction(self.searchMovieAction,[pattern]) + + def searchMovieAction(self,pattern): + self.ui.stackedWidget.setCurrentWidget(self.ui.movie_list_page) + for minimovie in self.minimovies: + self.ui.movie_list_page.layout().removeWidget(minimovie) + minimovie.hide() + minimovie.deleteLater() + + self.minimovies = [] + self.ui.searchEdit.setEnabled(False) + + backend_name = str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString()) + + self.process = QtDo(self.weboob, self.addMovie) + self.process.do('iter_movies', pattern, backends=backend_name) + + def addMovie(self, backend, movie): + if not backend: + self.ui.searchEdit.setEnabled(True) + self.process = None + return + minimovie = MiniMovie(self.weboob, backend, movie, self) + self.ui.scrollAreaContent.layout().addWidget(minimovie) + self.minimovies.append(minimovie) + + def displayMovie(self, movie): + self.ui.stackedWidget.setCurrentWidget(self.ui.movie_info_page) + if self.current_movie_widget != None: + self.ui.movie_info_page.layout().removeWidget(self.current_movie_widget) + self.current_movie_widget.hide() + self.current_movie_widget.deleteLater() + wmovie = Movie(movie,self) + self.ui.movie_info_page.layout().addWidget(wmovie) + self.current_movie_widget = wmovie + + def searchPerson(self): + pattern = unicode(self.ui.searchEdit.text()) + if not pattern: + return + self.doAction(self.searchPersonAction,[pattern]) + + def searchPersonAction(self,pattern): + self.ui.stackedWidget.setCurrentWidget(self.ui.person_list_page) + for miniperson in self.minipersons: + self.ui.person_list_page.layout().removeWidget(miniperson) + miniperson.hide() + miniperson.deleteLater() + + self.minipersons = [] + self.ui.searchEdit.setEnabled(False) + + backend_name = str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString()) + + self.process = QtDo(self.weboob, self.addPerson) + self.process.do('iter_persons', pattern, backends=backend_name) + + def addPerson(self, backend, person): + if not backend: + self.ui.searchEdit.setEnabled(True) + self.process = None + return + miniperson = MiniPerson(self.weboob, backend, person, self) + self.ui.scrollAreaContent_2.layout().addWidget(miniperson) + self.minipersons.append(miniperson) + + def displayPerson(self, person): + self.ui.stackedWidget.setCurrentWidget(self.ui.person_info_page) + if self.current_person_widget != None: + self.ui.person_info_page.layout().removeWidget(self.current_person_widget) + self.current_person_widget.hide() + self.current_person_widget.deleteLater() + wperson = Person(person,self) + self.ui.person_info_page.layout().addWidget(wperson) + self.current_person_widget = wperson + + def closeEvent(self, ev): + self.config.set('settings', 'backend', str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString())) + self.config.save() + ev.accept() diff --git a/weboob/applications/qcineoob/minimovie.py b/weboob/applications/qcineoob/minimovie.py new file mode 100644 index 0000000000..57d7f44117 --- /dev/null +++ b/weboob/applications/qcineoob/minimovie.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Romain Bignon +# +# This file is part of weboob. +# +# weboob 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. +# +# weboob 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 weboob. If not, see . + + +from PyQt4.QtGui import QFrame, QImage, QPixmap + +from weboob.tools.application.qt import QtDo +from weboob.applications.qcineoob.ui.minimovie_ui import Ui_MiniMovie + +class MiniMovie(QFrame): + def __init__(self, weboob, backend, movie, parent=None): + QFrame.__init__(self, parent) + self.parent = parent + self.ui = Ui_MiniMovie() + self.ui.setupUi(self) + + self.weboob = weboob + self.backend = backend + self.movie = movie + self.ui.titleLabel.setText(movie.original_title) + self.ui.backendLabel.setText(backend.name) + + #self.process_thumbnail = QtDo(self.weboob, self.gotThumbnail) + #self.process_thumbnail.do('fillobj', self.movie, ['thumbnail_url'], backends=backend) + + def gotThumbnail(self, backend, movie): + if not backend: + return + + if movie.thumbnail_url: + img = QImage.fromData(movie.thumbnail.data) + self.ui.imageLabel.setPixmap(QPixmap.fromImage(img)) + + def enterEvent(self, event): + self.setFrameShadow(self.Sunken) + QFrame.enterEvent(self, event) + + def leaveEvent(self, event): + self.setFrameShadow(self.Raised) + QFrame.leaveEvent(self, event) + + def mousePressEvent(self, event): + QFrame.mousePressEvent(self, event) + + movie = self.backend.get_movie(self.movie.id) + if movie: + self.parent.doAction(self.parent.displayMovie,[movie]) diff --git a/weboob/applications/qcineoob/miniperson.py b/weboob/applications/qcineoob/miniperson.py new file mode 100644 index 0000000000..f268dda085 --- /dev/null +++ b/weboob/applications/qcineoob/miniperson.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Romain Bignon +# +# This file is part of weboob. +# +# weboob 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. +# +# weboob 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 weboob. If not, see . + + +from PyQt4.QtGui import QFrame, QImage, QPixmap + +from weboob.tools.application.qt import QtDo +from weboob.applications.qcineoob.ui.miniperson_ui import Ui_MiniPerson + +class MiniPerson(QFrame): + def __init__(self, weboob, backend, person, parent=None): + QFrame.__init__(self, parent) + self.parent = parent + self.ui = Ui_MiniPerson() + self.ui.setupUi(self) + + self.weboob = weboob + self.backend = backend + self.person = person + self.ui.nameLabel.setText(person.name) + #self.ui.birthdateLabel.setText(person.birth_date) + self.ui.backendLabel.setText(backend.name) + + #self.process_thumbnail = QtDo(self.weboob, self.gotThumbnail) + #self.process_thumbnail.do('fillobj', self.person, ['thumbnail_url'], backends=backend) + + def gotThumbnail(self, backend, person): + if not backend: + return + + if person.thumbnail_url: + img = QImage.fromData(person.thumbnail.data) + self.ui.imageLabel.setPixmap(QPixmap.fromImage(img)) + + def enterEvent(self, event): + self.setFrameShadow(self.Sunken) + QFrame.enterEvent(self, event) + + def leaveEvent(self, event): + self.setFrameShadow(self.Raised) + QFrame.leaveEvent(self, event) + + def mousePressEvent(self, event): + QFrame.mousePressEvent(self, event) + + person = self.backend.get_person(self.person.id) + if person: + self.parent.doAction(self.parent.displayPerson,[person]) diff --git a/weboob/applications/qcineoob/movie.py b/weboob/applications/qcineoob/movie.py new file mode 100644 index 0000000000..806cb8809e --- /dev/null +++ b/weboob/applications/qcineoob/movie.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Romain Bignon +# +# This file is part of weboob. +# +# weboob 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. +# +# weboob 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 weboob. If not, see . + + +from PyQt4.QtCore import QUrl +from PyQt4.QtGui import QFrame +from PyQt4.phonon import Phonon + +from weboob.applications.qcineoob.ui.movie_ui import Ui_Movie + +class Movie(QFrame): + def __init__(self, movie, parent=None): + QFrame.__init__(self, parent) + self.parent = parent + self.ui = Ui_Movie() + self.ui.setupUi(self) + + self.movie = movie + self.ui.titleLabel.setText(movie.original_title) + self.ui.durationLabel.setText(unicode(movie.duration)) diff --git a/weboob/applications/qcineoob/person.py b/weboob/applications/qcineoob/person.py new file mode 100644 index 0000000000..3a03b5f577 --- /dev/null +++ b/weboob/applications/qcineoob/person.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Romain Bignon +# +# This file is part of weboob. +# +# weboob 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. +# +# weboob 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 weboob. If not, see . + + +from PyQt4.QtCore import QUrl +from PyQt4.QtGui import QFrame +from PyQt4.phonon import Phonon + +from weboob.applications.qcineoob.ui.person_ui import Ui_Person + +class Person(QFrame): + def __init__(self, person, parent=None): + QFrame.__init__(self, parent) + self.parent = parent + self.ui = Ui_Person() + self.ui.setupUi(self) + + self.person = person + self.ui.nameLabel.setText(person.name) + self.ui.birthdateLabel.setText(person.birth_date.isoformat()) diff --git a/weboob/applications/qcineoob/qcineoob.py b/weboob/applications/qcineoob/qcineoob.py new file mode 100644 index 0000000000..1c540f0cc4 --- /dev/null +++ b/weboob/applications/qcineoob/qcineoob.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Romain Bignon +# +# This file is part of weboob. +# +# weboob 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. +# +# weboob 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 weboob. If not, see . + + +from weboob.capabilities.cinema import ICapCinema +from weboob.tools.application.qt import QtApplication + +from .main_window import MainWindow + + +class QCineoob(QtApplication): + APPNAME = 'qcineoob' + VERSION = '0.f' + COPYRIGHT = 'Copyright(C) 2010-2011 Romain Bignon' + DESCRIPTION = "Qt application allowing to search movies etc..." + SHORT_DESCRIPTION = "search movies" + CAPS = ICapCinema + CONFIG = {'settings': {'nsfw': 1, + 'sfw': 1, + 'sortby': 0, + 'backend': '' + } + } + def main(self, argv): + self.load_backends(ICapCinema) + self.load_config() + + self.main_window = MainWindow(self.config, self.weboob) + self.main_window.show() + return self.weboob.loop() diff --git a/weboob/applications/qcineoob/ui/Makefile b/weboob/applications/qcineoob/ui/Makefile new file mode 100644 index 0000000000..f0db5154cf --- /dev/null +++ b/weboob/applications/qcineoob/ui/Makefile @@ -0,0 +1,13 @@ +UI_FILES = $(wildcard *.ui) +UI_PY_FILES = $(UI_FILES:%.ui=%_ui.py) +PYUIC = pyuic4 + +all: $(UI_PY_FILES) + +%_ui.py: %.ui + $(PYUIC) -o $@ $^ + +clean: + rm -f *.pyc + rm -f $(UI_PY_FILES) + diff --git a/weboob/applications/qcineoob/ui/__init__.py b/weboob/applications/qcineoob/ui/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/weboob/applications/qcineoob/ui/main_window.ui b/weboob/applications/qcineoob/ui/main_window.ui new file mode 100644 index 0000000000..284942a3bb --- /dev/null +++ b/weboob/applications/qcineoob/ui/main_window.ui @@ -0,0 +1,183 @@ + + + MainWindow + + + + 0 + 0 + 582 + 463 + + + + QCineoob + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + Search: + + + + + + + + + + + movie + + + + + person + + + + + + + + + + + + 40 + 16777215 + + + + back + + + + + + + + + + + + + + + + + true + + + + + 0 + 0 + 542 + 313 + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + true + + + + + 0 + 0 + 78 + 16 + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + 0 + 0 + 582 + 23 + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + Backends + + + + + + diff --git a/weboob/applications/qcineoob/ui/minimovie.ui b/weboob/applications/qcineoob/ui/minimovie.ui new file mode 100644 index 0000000000..24dfb9b213 --- /dev/null +++ b/weboob/applications/qcineoob/ui/minimovie.ui @@ -0,0 +1,189 @@ + + + MiniMovie + + + + 0 + 0 + 464 + 132 + + + + Form + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 9 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + + 75 + true + + + + Title + + + + + + + + 0 + 0 + + + + + 50 + true + false + + + + TextLabel + + + + + + + + 75 + true + + + + Duration + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Author + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Date + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Rating + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Where + + + + + + + TextLabel + + + + + + + + + + diff --git a/weboob/applications/qcineoob/ui/miniperson.ui b/weboob/applications/qcineoob/ui/miniperson.ui new file mode 100644 index 0000000000..5a3f4c51b5 --- /dev/null +++ b/weboob/applications/qcineoob/ui/miniperson.ui @@ -0,0 +1,189 @@ + + + MiniPerson + + + + 0 + 0 + 464 + 136 + + + + Form + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 9 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + + 75 + true + + + + Name + + + + + + + + 0 + 0 + + + + + 50 + true + false + + + + TextLabel + + + + + + + + 75 + true + + + + Duration + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Author + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Date + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Rating + + + + + + + TextLabel + + + + + + + + 75 + true + + + + Where + + + + + + + TextLabel + + + + + + + + + + diff --git a/weboob/applications/qcineoob/ui/movie.ui b/weboob/applications/qcineoob/ui/movie.ui new file mode 100644 index 0000000000..066f792bd5 --- /dev/null +++ b/weboob/applications/qcineoob/ui/movie.ui @@ -0,0 +1,79 @@ + + + Movie + + + + 0 + 0 + 857 + 629 + + + + Frame + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Title: + + + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Duration: + + + + + + + + + + + + + + + + + + diff --git a/weboob/applications/qcineoob/ui/person.ui b/weboob/applications/qcineoob/ui/person.ui new file mode 100644 index 0000000000..7527262885 --- /dev/null +++ b/weboob/applications/qcineoob/ui/person.ui @@ -0,0 +1,79 @@ + + + Person + + + + 0 + 0 + 857 + 629 + + + + Frame + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + name: + + + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Birth date: + + + + + + + + + + + + + + + + + + -- GitLab