From 397675fb884e5419ac23222df42c83ae9e54cd0d Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 3 Oct 2017 14:58:25 +0100 Subject: [PATCH 01/66] Import new paths now allows for txt files with auto frame numbering --- pyforms/gui/dialogs/generic_csv_parser.py | 185 +++++++++++++--------- 1 file changed, 107 insertions(+), 78 deletions(-) diff --git a/pyforms/gui/dialogs/generic_csv_parser.py b/pyforms/gui/dialogs/generic_csv_parser.py index 5cf9c73..418cc19 100644 --- a/pyforms/gui/dialogs/generic_csv_parser.py +++ b/pyforms/gui/dialogs/generic_csv_parser.py @@ -8,83 +8,111 @@ class GenericCsvParserDialog(BaseWidget): + def __init__(self, columns, parent=None): + super(GenericCsvParserDialog, self).__init__('CSV Choose the columns', parent_win=parent) + + self._filename = None + self._columns = columns + self._columns_indexes = [] + self._rownum = 0 + + # Definition of the forms fields + self._filename = ControlFile('CSV File') + self._separator = ControlText('Separator', 'auto') + self._startingrow = ControlNumber('Starting row', 0) + + for index, column in enumerate(columns): + setattr(self, '_col_{0}'.format(index), ControlNumber(column, index, -1, 1000)) + + self._filePreview = ControlList('Preview') + self._loadButton = ControlButton('Load') + + form_row = ['_separator'] + ['_col_{0}'.format(index) for index, column in enumerate(columns)] + ['_loadButton'] + + self._formset = [ + ('_filename', '_startingrow'), + tuple(form_row), + '_filePreview' + ] + self._separator.changed_event = self.__refreshPreview + self._filename.changed_event = self.__refreshPreview + self._startingrow.changed_event = self.__refreshPreview + self._loadButton.value = self.load + + self._load_event = None + + @property + def load_file_event(self): + return self._load_event + + @load_file_event.setter + def load_file_event(self, value): + self._load_event = value + + def __iter__(self): + + if self._filename.value != None and self._filename.value != '': + csvfile = open(self._filename.value, 'U') + if self._separator.value in ['auto']: + dialect = csv.Sniffer().sniff(csvfile.read(1024)) + csvfile.seek(0) + self._spamreader = csv.reader(csvfile, dialect) + else: + self._spamreader = csv.reader(csvfile, delimiter=self._separator.value) + for i in range(int(self._startingrow.value)): next(self._spamreader, None) # skip the headers + else: + self._spamreader = None + + return self + + # For compatibility with python 3 + def __next__(self): + return self.next() + + def next(self): + if self._spamreader != None: + row = next(self._spamreader) + res = [] + for col in self._columns_indexes: + if col == -1: + res.append(self._rownum) + else: + if row[col].lower() == 'nan': + res.append('None') + else: + res.append(row[col]) + + self._rownum +=1 + + return res + else: + raise StopIteration() + + def __refreshPreview(self): + if self._filename.value != None and self._filename.value != '': + with open(self._filename.value, 'U') as csvfile: + if self._separator.value in ['auto']: + dialect = csv.Sniffer().sniff(csvfile.read(1024)) + csvfile.seek(0) + spamreader = csv.reader(csvfile, dialect) + else: + spamreader = csv.reader(csvfile, delimiter=self._separator.value) + + for i in range(int(self._startingrow.value)): next(spamreader, None) # skip the headers + self._filePreview.value = [] + self._filePreview.horizontalHeaders = map(str, range(1000)) + for i, row in enumerate(spamreader): + self._filePreview += row + if i >= 10: + break + + def load(self): + self.__refreshPreview() + self._columns_indexes = [] + for index, column in enumerate(self._columns): + self._columns_indexes.append(int(getattr(self, '_col_{0}'.format(index)).value)) + if self._load_event is not None: self._load_event() - def __init__(self, columns, parent=None): - super(GenericCsvParserDialog, self).__init__('CSV Choose the columns', parent_win = parent) - - self._filename = None - self._columns = columns - self._columns_indexes = [] - - # Definition of the forms fields - self._filename = ControlFile('CSV File') - self._separator = ControlText('Separator', ';') - self._startingrow = ControlNumber('Starting row', 0) - - for index, column in enumerate(columns): - setattr(self, '_col_{0}'.format(index), ControlNumber(column, index, 0, 1000) ) - - self._filePreview = ControlList('Preview') - self._loadButton = ControlButton('Load') - - form_row = ['_separator'] + ['_col_{0}'.format(index) for index, column in enumerate(columns)] + ['_loadButton'] - - self._formset = [ - ('_filename','_startingrow'), - tuple(form_row), - '_filePreview' - ] - self._separator.changed_event = self.__refreshPreview - self._filename.changed_event = self.__refreshPreview - self._startingrow.changed_event = self.__refreshPreview - self._loadButton.value = self.load - - self._load_event = None - - @property - def load_file_event(self): return self._load_event - @load_file_event.setter - def load_file_event(self, value): self._load_event = value - - - def __iter__(self): - if self._filename.value != None and self._filename.value != '': - csvfile = open(self._filename.value, 'U') - self._spamreader = csv.reader(csvfile, delimiter=self._separator.value) - for i in range(int(self._startingrow.value)): next(self._spamreader, None) # skip the headers - else: - self._spamreader = None - return self - - # For compatibility with python 3 - def __next__(self): return self.next() - - def next(self): - if self._spamreader != None: - row = next(self._spamreader) - return [row[col] for col in self._columns_indexes] - else: - raise StopIteration() - - def __refreshPreview(self): - if self._filename.value != None and self._filename.value != '': - with open(self._filename.value, 'U') as csvfile: - spamreader = csv.reader(csvfile, delimiter=self._separator.value) - for i in range(int(self._startingrow.value)): next(spamreader, None) # skip the headers - self._filePreview.value = [] - self._filePreview.horizontalHeaders = map(str, range(1000)) - for i, row in enumerate(spamreader): - self._filePreview += row - if i >= 10: - break - - def load(self): - self.__refreshPreview() - self._columns_indexes = [] - for index, column in enumerate(self._columns): - self._columns_indexes.append( int(getattr(self, '_col_{0}'.format(index) ).value) ) - if self._load_event is not None: self._load_event() - ################################################################################################################## ################################################################################################################## @@ -92,5 +120,6 @@ def load(self): # Execute the application if __name__ == "__main__": - import pyforms - pyforms.start_app(GenericCsvParserDialog, geometry=(0, 0, 600, 400)) + import pyforms + + pyforms.start_app(GenericCsvParserDialog, geometry=(0, 0, 600, 400)) \ No newline at end of file From 5131db25fbc708e1e43083b979c919c42a32eaba Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 6 Oct 2017 18:12:22 +0100 Subject: [PATCH 02/66] Add autoscroll to ControlTextArea and ControlList --- docs/api-documentation/controls.md | 9 +++ pyforms/gui/Controls/ControlList.py | 22 ++++++- pyforms/gui/Controls/ControlTextArea.py | 78 +++++++++++++++---------- 3 files changed, 75 insertions(+), 34 deletions(-) diff --git a/docs/api-documentation/controls.md b/docs/api-documentation/controls.md index 477fc12..bbc6b20 100644 --- a/docs/api-documentation/controls.md +++ b/docs/api-documentation/controls.md @@ -775,6 +775,10 @@ Called on item item double click. ### **Properties** *************************** +#### autoscroll + +Returns and sets the autoscroll flag. If True the ControlList will position the scroll automatically to a position where the new new added item will be visible. + #### horizontal_headers Get and set the horizontal headers in the table list. @@ -1210,6 +1214,11 @@ Append text to the bottom. Returns and sets the readonly flag for the control. +#### autoscroll + +Returns and sets the autoscroll flag. If True the ControlTextArea will scroll always the text to the bottom everytime a new text is added. + + ## ControlToolBox *************************** diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/Controls/ControlList.py index c6c59bd..f8ccd28 100755 --- a/pyforms/gui/Controls/ControlList.py +++ b/pyforms/gui/Controls/ControlList.py @@ -48,6 +48,9 @@ def __init__(self, label="", default="", add_function=None, self._minusFunction = remove_function ControlBase.__init__(self, label, default) + self.autoscroll = False + + ########################################################################## ############ FUNCTIONS ################################################### ########################################################################## @@ -133,16 +136,23 @@ def load_form(self, data, path=None): self.value = data['value'] def __add__(self, other): + row_index = self.tableWidget.rowCount() - row = self.tableWidget.rowCount() + self.tableWidget.insertRow(row_index) - self.tableWidget.insertRow(row) + #increase the number of columns if necessary #### if self.tableWidget.currentColumn() < len(other): self.tableWidget.setColumnCount(len(other)) + ################################################# - for column, e in enumerate(other): self.set_value(column, row, e) + for column, e in enumerate(other): self.set_value(column, row_index, e) self.tableWidget.resizeColumnsToContents() + + # auto scroll the list to the new inserted item ################## + if self.autoscroll: + self.tableWidget.scrollToItem( self.get_cell(0,row_index) ) + ################################################################## return self def __sub__(self, other): @@ -344,6 +354,12 @@ def icon_size(self, value): else: self.tableWidget.setIconSize(QtCore.QSize(value, value)) + @property + def autoscroll(self): return self._autoscroll + @autoscroll.setter + def autoscroll(self, value): self._autoscroll = value + + ########################################################################## ############ PRIVATE FUNCTIONS ########################################### ########################################################################## diff --git a/pyforms/gui/Controls/ControlTextArea.py b/pyforms/gui/Controls/ControlTextArea.py index 0af7adc..b1f670d 100755 --- a/pyforms/gui/Controls/ControlTextArea.py +++ b/pyforms/gui/Controls/ControlTextArea.py @@ -4,9 +4,9 @@ import pyforms.utils.tools as tools from pysettings import conf if conf.PYFORMS_USE_QT5: - from PyQt5 import uic + from PyQt5 import uic, QtGui else: - from PyQt4 import uic + from PyQt4 import uic, QtGui from pyforms.gui.Controls.ControlBase import ControlBase __author__ = "Ricardo Ribeiro" @@ -20,40 +20,56 @@ class ControlTextArea(ControlBase): - def init_form(self): - control_path = tools.getFileInSameDirectory(__file__, "textArea.ui") - self._form = uic.loadUi(control_path) - self._form.label.setText(self._label) - if self._value: - self._form.plainTextEdit.setPlainText(str(self._value)) + def __init__(self, label='', default=None, helptext=None): + ControlBase.__init__(self, label, default, helptext) + self.autoscroll = False + - if not self._label or len(self._label)==0: - self.form.label.hide() + def init_form(self): + control_path = tools.getFileInSameDirectory(__file__, "textArea.ui") + self._form = uic.loadUi(control_path) + self._form.label.setText(self._label) + if self._value: + self._form.plainTextEdit.setPlainText(str(self._value)) - super(ControlTextArea, self).init_form() - self.form.plainTextEdit.textChanged.connect(self.finishEditing) + if not self._label or len(self._label)==0: + self.form.label.hide() - def __add__(self, other): - self._form.plainTextEdit.appendPlainText(str(other)) - return self + super(ControlTextArea, self).init_form() + self.form.plainTextEdit.textChanged.connect(self.finishEditing) - def finishEditing(self): - """Function called when the lineEdit widget is edited""" - self.changed_event() - + def __add__(self, other): + self._form.plainTextEdit.appendPlainText(str(other)) - @property - def value(self): - return self._form.plainTextEdit.toPlainText() + # if activated the text field is autoscrolled to the bottom + if self.autoscroll: + self._form.plainTextEdit.moveCursor(QtGui.QTextCursor.End) - @value.setter - def value(self, value): - self._form.plainTextEdit.setPlainText(str(value)) + return self - @property - def readonly(self): - return self._form.plainTextEdit.isReadOnly() + def finishEditing(self): + """Function called when the lineEdit widget is edited""" + self.changed_event() + - @readonly.setter - def readonly(self, value): - self._form.plainTextEdit.setReadOnly(value) + @property + def value(self): + return self._form.plainTextEdit.toPlainText() + + @value.setter + def value(self, value): + self._form.plainTextEdit.setPlainText(str(value)) + + @property + def readonly(self): + return self._form.plainTextEdit.isReadOnly() + + @readonly.setter + def readonly(self, value): + self._form.plainTextEdit.setReadOnly(value) + + + @property + def autoscroll(self): return self._autoscroll + @autoscroll.setter + def autoscroll(self, value): self._autoscroll = value From 13f1e1e8bd41989494c1510c922c78a2e19b7d28 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 17 Oct 2017 15:55:38 +0100 Subject: [PATCH 03/66] Autocomplete added to ControlCodeEditor --- docs/api-documentation/basewidget.md | 6 +++--- pyforms/__init__.py | 2 +- pyforms/gui/Controls/ControlCodeEditor.py | 16 ++++++++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/api-documentation/basewidget.md b/docs/api-documentation/basewidget.md index 40918b1..a7ccf34 100644 --- a/docs/api-documentation/basewidget.md +++ b/docs/api-documentation/basewidget.md @@ -37,9 +37,9 @@ class SimpleExample(BaseWidget): ### \_\_init\_\_(title='Untitled', parent_win=None, win_flag=None) -**title** - Title of the window. -**parent_win** - Parent widget. If the win_flag is None and the parent parameters is set, then the flag_win will be QtCore.Qt.Dialog. -**win_flag** - Window type flag. Type of Qt.WindowType. +**title** - Title of the window. +**parent_win** - Parent widget. If the win_flag is None and the parent parameters is set, then the flag_win will be QtCore.Qt.Dialog. +**win_flag** - Window type flag. Type of Qt.WindowType. ## **Functions** *************************** diff --git a/pyforms/__init__.py b/pyforms/__init__.py index 0c4aa63..a10a0e9 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -9,7 +9,7 @@ __author__ = "Ricardo Ribeiro" __credits__ = ["Ricardo Ribeiro"] __license__ = "MIT" -__version__ = '2.0.5' +__version__ = '2.0.6' __maintainer__ = ["Ricardo Ribeiro", "Carlos Mão de Ferro"] __email__ = ["ricardojvr@gmail.com", "cajomferro@gmail.com"] __status__ = "Production" diff --git a/pyforms/gui/Controls/ControlCodeEditor.py b/pyforms/gui/Controls/ControlCodeEditor.py index 1a2c2a1..aadcf8a 100755 --- a/pyforms/gui/Controls/ControlCodeEditor.py +++ b/pyforms/gui/Controls/ControlCodeEditor.py @@ -11,12 +11,12 @@ if conf.PYFORMS_USE_QT5: from PyQt5.QtWidgets import QApplication from PyQt5.QtGui import QFontMetrics, QColor, QIcon, QFont - from PyQt5.Qsci import QsciScintilla, QsciLexerPython + from PyQt5.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs from PyQt5 import uic from PyQt5 import QtCore else: from PyQt4.QtGui import QApplication, QFontMetrics, QColor, QIcon, QFont - from PyQt4.Qsci import QsciScintilla, QsciLexerPython + from PyQt4.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs from PyQt4 import uic from PyQt4 import QtCore @@ -141,6 +141,18 @@ def _load_code_editor_settings(self): # Don't want to see the horizontal scrollbar at all # Use raw message to Scintilla here (all messages are documented here: http://www.scintilla.org/ScintillaDoc.html) self._code_editor.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) + + self._lexer_obj = lexer + self.qsci_api = QsciAPIs(self._lexer_obj) + ## Add autocompletion strings + self.qsci_api.add("aLongString") + self.qsci_api.add("aLongerString") + self.qsci_api.add("aDifferentString") + self.qsci_api.add("sOmethingElse") + ## Compile the api for use in the lexer + self.qsci_api.prepare() + self._code_editor.setAutoCompletionThreshold(1) + self._code_editor.setAutoCompletionSource(QsciScintilla.AcsAll) # not too small # self._code_editor.setMinimumSize(600, 450) From 460c069bb7748d656881515bc440c668edff467a Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 26 Oct 2017 23:25:09 +0100 Subject: [PATCH 04/66] Update code to AnyQt --- pyforms/__init__.py | 2 +- pyforms/gui/Controls/ControlBase.py | 21 ++++------------ pyforms/gui/Controls/ControlBoundingSlider.py | 24 +++---------------- pyforms/gui/Controls/ControlButton.py | 13 +++------- pyforms/gui/Controls/ControlCheckBox.py | 10 ++------ pyforms/gui/Controls/ControlCheckBoxList.py | 11 ++------- pyforms/gui/Controls/ControlCodeEditor.py | 21 ++++++++-------- pyforms/gui/Controls/ControlCombo.py | 5 +--- pyforms/gui/Controls/ControlDir.py | 8 ++----- pyforms/gui/Controls/ControlEmptyWidget.py | 7 +----- pyforms/gui/Controls/ControlFile.py | 8 ++----- pyforms/gui/Controls/ControlFilesTree.py | 12 ++-------- pyforms/gui/Controls/ControlImage.py | 19 +++++++-------- pyforms/gui/Controls/ControlLabel.py | 5 +--- pyforms/gui/Controls/ControlList.py | 22 ++++------------- pyforms/gui/Controls/ControlMatplotlib.py | 6 +---- pyforms/gui/Controls/ControlMdiArea.py | 8 +------ pyforms/gui/Controls/ControlNumber.py | 6 +---- pyforms/gui/Controls/ControlOpenGL.py | 24 ++++++++++++------- 19 files changed, 66 insertions(+), 166 deletions(-) diff --git a/pyforms/__init__.py b/pyforms/__init__.py index a10a0e9..35fbb35 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -9,7 +9,7 @@ __author__ = "Ricardo Ribeiro" __credits__ = ["Ricardo Ribeiro"] __license__ = "MIT" -__version__ = '2.0.6' +__version__ = '2.1.0' __maintainer__ = ["Ricardo Ribeiro", "Carlos Mão de Ferro"] __email__ = ["ricardojvr@gmail.com", "cajomferro@gmail.com"] __status__ = "Production" diff --git a/pyforms/gui/Controls/ControlBase.py b/pyforms/gui/Controls/ControlBase.py index 413da38..036df10 100755 --- a/pyforms/gui/Controls/ControlBase.py +++ b/pyforms/gui/Controls/ControlBase.py @@ -1,24 +1,11 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QMenu - from PyQt5.QtWidgets import QAction - from PyQt5.QtGui import QIcon - from PyQt5.QtGui import QKeySequence - from PyQt5 import QtCore - from PyQt5 import uic -else: - from PyQt4.QtGui import Qmenu - from PyQt4.QtGui import QAction - from PyQt4.QtGui import QIcon - from PyQt4.QtGui import QKeySequence - from PyQt4 import QtCore - from PyQt4 import uic - +from pysettings import conf +from AnyQt import QtCore, uic +from AnyQt.QtWidgets import QMenu, QAction +from AnyQt.QtGui import QIcon, QKeySequence class ControlBase(object): """ diff --git a/pyforms/gui/Controls/ControlBoundingSlider.py b/pyforms/gui/Controls/ControlBoundingSlider.py index fdd6749..4868658 100755 --- a/pyforms/gui/Controls/ControlBoundingSlider.py +++ b/pyforms/gui/Controls/ControlBoundingSlider.py @@ -3,27 +3,9 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget - from PyQt5.QtWidgets import QVBoxLayout - from PyQt5.QtWidgets import QHBoxLayout - from PyQt5.QtWidgets import QSpinBox - from PyQt5.QtGui import QPainter - from PyQt5.QtGui import QFont - from PyQt5.QtGui import QColor - from PyQt5.QtGui import QCursor - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QWidget - from PyQt4.QtGui import QVBoxLayout - from PyQt4.QtGui import QHBoxLayout - from PyQt4.QtGui import QPainter - from PyQt4.QtGui import QFont - from PyQt4.QtGui import QColor - from PyQt4.QtGui import QCursor - from PyQt4.QtGui import QSpinBox - from PyQt4 import QtCore +from AnyQt import QtCore +from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QSpinBox +from AnyQt.QtGui import QFont, QColor, QCursor, QPainter from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlButton.py b/pyforms/gui/Controls/ControlButton.py index 29aa486..7769cd9 100755 --- a/pyforms/gui/Controls/ControlButton.py +++ b/pyforms/gui/Controls/ControlButton.py @@ -5,16 +5,9 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QPushButton - from PyQt5.QtWidgets import QSizePolicy - from PyQt5.QtGui import QIcon - from PyQt5 import uic -else: - from PyQt4.QtGui import QPushButton - from PyQt4.QtGui import QSizePolicy - from PyQt4.QtGui import QIcon - from PyQt4 import uic +from AnyQt import uic +from AnyQt.QtWidgets import QPushButton, QSizePolicy +from AnyQt.QtGui import QIcon from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlCheckBox.py b/pyforms/gui/Controls/ControlCheckBox.py index 8568b16..f3e7f6e 100755 --- a/pyforms/gui/Controls/ControlCheckBox.py +++ b/pyforms/gui/Controls/ControlCheckBox.py @@ -3,16 +3,10 @@ from pysettings import conf -import pyforms.utils.tools as tools - -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic - from PyQt5 import QtCore +from AnyQt import uic, QtCore -else: - from PyQt4 import uic - from PyQt4 import QtCore +import pyforms.utils.tools as tools from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlCheckBoxList.py b/pyforms/gui/Controls/ControlCheckBoxList.py index 127b833..4011ecd 100755 --- a/pyforms/gui/Controls/ControlCheckBoxList.py +++ b/pyforms/gui/Controls/ControlCheckBoxList.py @@ -5,15 +5,8 @@ import pyforms.utils.tools as tools -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QListWidgetItem - from PyQt5 import uic - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QListWidgetItem - from PyQt4 import uic - from PyQt4 import QtCore +from AnyQt import uic, QtCore +from AnyQt.QtWidgets import QListWidgetItem from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlCodeEditor.py b/pyforms/gui/Controls/ControlCodeEditor.py index aadcf8a..fd8c54d 100755 --- a/pyforms/gui/Controls/ControlCodeEditor.py +++ b/pyforms/gui/Controls/ControlCodeEditor.py @@ -3,22 +3,21 @@ import logging +from AnyQt import _api from pysettings import conf from pyforms.gui.Controls.ControlBase import ControlBase import pyforms.utils.tools as tools -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QApplication - from PyQt5.QtGui import QFontMetrics, QColor, QIcon, QFont - from PyQt5.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs - from PyQt5 import uic - from PyQt5 import QtCore -else: - from PyQt4.QtGui import QApplication, QFontMetrics, QColor, QIcon, QFont - from PyQt4.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs - from PyQt4 import uic - from PyQt4 import QtCore +from AnyQt import QtCore, uic +from AnyQt.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QSpinBox +from AnyQt.QtGui import QFontMetrics, QColor, QIcon, QFont + +if _api.USED_API == _api.QT_API_PYQT5: + from PyQt5.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs +elif _api.USED_API == _api.QT_API_PYQT4: + from PyQt4.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs + logger = logging.getLogger(__name__) diff --git a/pyforms/gui/Controls/ControlCombo.py b/pyforms/gui/Controls/ControlCombo.py index df9860a..b1d4542 100755 --- a/pyforms/gui/Controls/ControlCombo.py +++ b/pyforms/gui/Controls/ControlCombo.py @@ -6,10 +6,7 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic -else: - from PyQt4 import uic +from AnyQt import uic from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlDir.py b/pyforms/gui/Controls/ControlDir.py index a4df416..b8d1ecd 100755 --- a/pyforms/gui/Controls/ControlDir.py +++ b/pyforms/gui/Controls/ControlDir.py @@ -7,13 +7,9 @@ import pyforms.utils.tools as tools -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QFileDialog - from PyQt5 import uic -else: - from PyQt4.QtGui import QFileDialog - from PyQt4 import uic +from AnyQt import uic +from AnyQt.QtWidgets import QFileDialog class ControlDir(ControlText): diff --git a/pyforms/gui/Controls/ControlEmptyWidget.py b/pyforms/gui/Controls/ControlEmptyWidget.py index a144a5a..c7e3821 100755 --- a/pyforms/gui/Controls/ControlEmptyWidget.py +++ b/pyforms/gui/Controls/ControlEmptyWidget.py @@ -3,12 +3,7 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget - from PyQt5.QtWidgets import QVBoxLayout -else: - from PyQt4.QtGui import QWidget - from PyQt4.QtGui import QVBoxLayout +from AnyQt.QtWidgets import QWidget, QVBoxLayout from pyforms.gui.Controls.ControlBase import ControlBase from pyforms.gui.BaseWidget import BaseWidget diff --git a/pyforms/gui/Controls/ControlFile.py b/pyforms/gui/Controls/ControlFile.py index 31039d2..5c56d77 100755 --- a/pyforms/gui/Controls/ControlFile.py +++ b/pyforms/gui/Controls/ControlFile.py @@ -7,13 +7,9 @@ import pyforms.utils.tools as tools -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QFileDialog - from PyQt5 import uic -else: - from PyQt4.QtGui import QFileDialog - from PyQt4 import uic +from AnyQt import uic +from AnyQt.QtWidgets import QFileDialog class ControlFile(ControlText): diff --git a/pyforms/gui/Controls/ControlFilesTree.py b/pyforms/gui/Controls/ControlFilesTree.py index 3f5f899..fe25201 100755 --- a/pyforms/gui/Controls/ControlFilesTree.py +++ b/pyforms/gui/Controls/ControlFilesTree.py @@ -6,16 +6,8 @@ from pyforms.gui.Controls.ControlBase import ControlBase -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QTreeView - from PyQt5.QtWidgets import QFileSystemModel - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QTreeView - from PyQt4.QtGui import QFileSystemModel - from PyQt4 import QtCore - +from AnyQt import QtCore +from AnyQt.QtWidgets import QTreeView, QFileSystemModel class ControlFilesTree(ControlBase): def init_form(self): diff --git a/pyforms/gui/Controls/ControlImage.py b/pyforms/gui/Controls/ControlImage.py index a7a93da..a1f14dc 100755 --- a/pyforms/gui/Controls/ControlImage.py +++ b/pyforms/gui/Controls/ControlImage.py @@ -15,29 +15,28 @@ except: logger.debug("OpenCV not available") -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic +import OpenGL.GL as GL +import OpenGL.GLU as GLU + +from AnyQt import QtCore, QtOpenGL, uic +from AnyQt.QtWidgets import QWidget +from AnyQt import _api + +if _api.USED_API == _api.QT_API_PYQT5: try: - import OpenGL.GL as GL - import OpenGL.GLU as GLU from PyQt5.QtOpenGL import QGLWidget except: logger.debug("No OpenGL library available") import platform - if platform.system() == 'Darwin': from pyforms.gui.Controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget else: from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget -else: - from PyQt4 import uic - +elif _api.USED_API == _api.QT_API_PYQT4: try: - import OpenGL.GL as GL - import OpenGL.GLU as GLU from PyQt4.QtOpenGL import QGLWidget except: logger.debug("No OpenGL library available") diff --git a/pyforms/gui/Controls/ControlLabel.py b/pyforms/gui/Controls/ControlLabel.py index 3d30273..817de4b 100755 --- a/pyforms/gui/Controls/ControlLabel.py +++ b/pyforms/gui/Controls/ControlLabel.py @@ -5,11 +5,8 @@ import pyforms.utils.tools as tools from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic -else: - from PyQt4 import uic +from AnyQt import uic from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/Controls/ControlList.py index f8ccd28..ade9230 100755 --- a/pyforms/gui/Controls/ControlList.py +++ b/pyforms/gui/Controls/ControlList.py @@ -9,23 +9,9 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget - from PyQt5.QtWidgets import QTableWidgetItem - from PyQt5.QtWidgets import QAbstractItemView - from PyQt5.QtGui import QIcon - from PyQt5 import uic - from PyQt5 import QtCore - from PyQt5.QtCore import Qt - -else: - from PyQt4.QtGui import QWidget - from PyQt4.QtGui import QTableWidgetItem - from PyQt4.QtGui import QAbstractItemView - from PyQt4.QtGui import QIcon - from PyQt4 import uic - from PyQt4 import QtCore - from PyQt4.QtCore import Qt +from AnyQt import QtCore, uic +from AnyQt.QtWidgets import QTableWidgetItem, QWidget, QAbstractItemView +from AnyQt.QtGui import QIcon from pyforms.gui.BaseWidget import BaseWidget from pyforms.gui.Controls.ControlBase import ControlBase @@ -174,7 +160,7 @@ def set_value(self, column, row, value): else: args = [value] if not hasattr(value, 'icon') else [QIcon(value.icon), value] item = QTableWidgetItem() - item.setData(Qt.EditRole, *args) + item.setData(QtCore.Qt.EditRole, *args) self.tableWidget.setItem(row, column, item) def get_value(self, column, row): diff --git a/pyforms/gui/Controls/ControlMatplotlib.py b/pyforms/gui/Controls/ControlMatplotlib.py index f83d8d5..09e1fdc 100644 --- a/pyforms/gui/Controls/ControlMatplotlib.py +++ b/pyforms/gui/Controls/ControlMatplotlib.py @@ -12,11 +12,7 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget, QVBoxLayout -else: - from PyQt4.QtGui import QWidget, QVBoxLayout - +from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayo from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlMdiArea.py b/pyforms/gui/Controls/ControlMdiArea.py index 6011c5e..28a4411 100644 --- a/pyforms/gui/Controls/ControlMdiArea.py +++ b/pyforms/gui/Controls/ControlMdiArea.py @@ -5,13 +5,7 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QMdiArea - from PyQt5.QtWidgets import QMdiSubWindow - -else: - from PyQt4.QtGui import QMdiArea - from PyQt4.QtGui import QMdiSubWindow +from AnyQt.QtWidgets import QMdiArea, QMdiSubWindow from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlNumber.py b/pyforms/gui/Controls/ControlNumber.py index 3d9e6f2..e3b5b1b 100644 --- a/pyforms/gui/Controls/ControlNumber.py +++ b/pyforms/gui/Controls/ControlNumber.py @@ -6,11 +6,7 @@ import pyforms.utils.tools as tools -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic - -else: - from PyQt4 import uic +from AnyQt import uic from pyforms.gui.Controls.ControlBase import ControlBase diff --git a/pyforms/gui/Controls/ControlOpenGL.py b/pyforms/gui/Controls/ControlOpenGL.py index c12b840..826b307 100644 --- a/pyforms/gui/Controls/ControlOpenGL.py +++ b/pyforms/gui/Controls/ControlOpenGL.py @@ -9,26 +9,34 @@ from pyforms.gui.Controls.ControlBase import ControlBase -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QSizePolicy +from AnyQt.QtWidgets import QSizePolicy +from AnyQt import _api + +from OpenGL.GL import * +from OpenGL.GLU import * + +from AnyQt import _api +if _api.USED_API == _api.QT_API_PYQT5: try: - from OpenGL.GL import * - from OpenGL.GLU import * from PyQt5.QtOpenGL import QGLWidget except: logger.debug("No OpenGL library available") -else: - from PyQt4.QtGui import QSizePolicy + import platform + if platform.system() == 'Darwin': + from pyforms.gui.Controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + else: + from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget +elif _api.USED_API == _api.QT_API_PYQT4: try: - from OpenGL.GL import * - from OpenGL.GLU import * from PyQt4.QtOpenGL import QGLWidget except: logger.debug("No OpenGL library available") + from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget + class OpenglGLWidget(QGLWidget): def __init__(self, parent=None): From 6d5f44ad5d66519e79ea0f61a8dcf4c852600d2e Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Mon, 30 Oct 2017 14:35:40 +0000 Subject: [PATCH 05/66] Add anyqt to requirements --- setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index b4bb60b..6ea86f8 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ version = '' with open('pyforms/__init__.py', 'r') as fd: version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', - fd.read(), re.MULTILINE).group(1) + fd.read(), re.MULTILINE).group(1) if not version: raise RuntimeError('Cannot find version information') @@ -19,7 +19,9 @@ author_email='ricardojvr@gmail.com', license='MIT', url='https://github.com/UmSenhorQualquer/pyforms', - + install_requires=[ + "anyqt", + ], packages=[ 'pyforms', 'pyforms.utils', From 9c1ab998d969b5a155f8dd17b8c7d3884530242f Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Mon, 30 Oct 2017 14:38:49 +0000 Subject: [PATCH 06/66] Fix errors on ControlMatplotlib --- pyforms/gui/Controls/ControlMatplotlib.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyforms/gui/Controls/ControlMatplotlib.py b/pyforms/gui/Controls/ControlMatplotlib.py index 09e1fdc..76844dc 100644 --- a/pyforms/gui/Controls/ControlMatplotlib.py +++ b/pyforms/gui/Controls/ControlMatplotlib.py @@ -12,15 +12,17 @@ from pysettings import conf -from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayo +from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout from pyforms.gui.Controls.ControlBase import ControlBase -if conf.PYFORMS_USE_QT5: +from AnyQt import _api + +if _api.USED_API == _api.QT_API_PYQT5: from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar -else: +elif _api.USED_API == _api.QT_API_PYQT4: from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar From e548f1745441d9e59b2e7b44ae4b457900a705ee Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Sat, 4 Nov 2017 00:24:33 +0000 Subject: [PATCH 07/66] . --- docs/api-documentation/controls.md | 2 +- pyforms/gui/Controls/ControlCombo.py | 95 ++++++++++++++----- pyforms/gui/Controls/ControlList.py | 4 + .../ControlPlayer/AbstractGLWidget.py | 19 ++-- .../Controls/ControlPlayer/ControlPlayer.py | 2 - pyforms/gui/Controls/comboInput.ui | 53 ----------- pyforms/utils/make_lambda.py | 5 + 7 files changed, 90 insertions(+), 90 deletions(-) delete mode 100755 pyforms/gui/Controls/comboInput.ui create mode 100644 pyforms/utils/make_lambda.py diff --git a/docs/api-documentation/controls.md b/docs/api-documentation/controls.md index bbc6b20..0b025cd 100644 --- a/docs/api-documentation/controls.md +++ b/docs/api-documentation/controls.md @@ -754,7 +754,7 @@ Returns the a specific cell from the QTableWidget. #### data_changed_event(row, col, item) -Called when any of list the content is updated. +Called when any of content of the list is updated. #### item_selection_changed_event() diff --git a/pyforms/gui/Controls/ControlCombo.py b/pyforms/gui/Controls/ControlCombo.py index b1d4542..9201a94 100755 --- a/pyforms/gui/Controls/ControlCombo.py +++ b/pyforms/gui/Controls/ControlCombo.py @@ -6,46 +6,69 @@ from pysettings import conf -from AnyQt import uic +from AnyQt.QtWidgets import QLabel, QWidget, QComboBox, QHBoxLayout, QSizePolicy from pyforms.gui.Controls.ControlBase import ControlBase -class ControlCombo(ControlBase): +class ControlCombo(ControlBase, QWidget): """This class represents a wrapper to the combo box""" + def __init__(self, label='', default=None, helptext=None): + QWidget.__init__(self) + ControlBase.__init__(self, label, default, helptext) + ########################################################################## ############ Functions ################################################### ########################################################################## def init_form(self): - control_path = tools.getFileInSameDirectory(__file__, "comboInput.ui") - self._form = uic.loadUi(control_path) - - self._form.comboLabel.setAccessibleName('ControlCombo-label') - self._form.comboBox.currentIndexChanged.connect(self._currentIndexChanged) - self._form.comboBox.activated.connect(self._activated) - self._form.comboBox.highlighted.connect(self._highlighted) - self._form.comboBox.editTextChanged.connect(self._editTextChanged) + self._layout = QHBoxLayout() + self._combo = QComboBox(self.form) + + if self._label is not None: + self._combolabel = QLabel(self.form) + self._layout.addWidget( self._combolabel ) + self._combolabel.setAccessibleName('ControlCombo-label') + self.label = self._label + else: + self._combolabel = None + + self._layout.addWidget( self._combo ) + self.form.setLayout( self._layout ) + + + self._combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self._layout.setContentsMargins(0,0,0,0) + self.form.setContentsMargins(0,0,0,0) + self.form.setMinimumHeight(38) + self.form.setMaximumHeight(38) + self.form.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + + self._combo.currentIndexChanged.connect(self._currentIndexChanged) + self._combo.activated.connect(self._activated) + self._combo.highlighted.connect(self._highlighted) + self._combo.editTextChanged.connect(self._editTextChanged) + self._items = {} self._addingItem = False - self.label = self._label + def clear(self): self._items = {} self._value = None - self._form.comboBox.clear() + self._combo.clear() def add_item(self, label, value=None): self._addingItem = True if value is not None: if not (value in self._items.values()): - self._form.comboBox.addItem(label) + self._combo.addItem(label) else: if not (label in self._items.keys()): - self._form.comboBox.addItem(label) + self._combo.addItem(label) firstValue = False if self._items == {}: @@ -74,10 +97,23 @@ def get_item_index_by_name(self, item_name): :param item_name: item name in combo box :type item_name: string """ - return self._form.comboBox.findText(item_name) + return self._combo.findText(item_name) def count(self): - return self._form.comboBox.count() + return self._combo.count() + + def show(self): + """ + Show the control + """ + QWidget.show(self) + + def hide(self): + """ + Hide the control + """ + QWidget.hide(self) + ########################################################################## ############ Events ###################################################### @@ -107,13 +143,17 @@ def edittext_changed_event(self, text): ############ PROPERTIES ################################################## ########################################################################## + @property + def form(self): + return self + @property def current_index(self): - return self._form.comboBox.currentIndex() + return self._combo.currentIndex() @current_index.setter def current_index(self, value): - self._form.comboBox.setCurrentIndex(value) + self._combo.setCurrentIndex(value) @property def items(self): @@ -127,15 +167,15 @@ def value(self): def value(self, value): for key, val in self.items: if value == val: - index = self._form.comboBox.findText(key) - self._form.comboBox.setCurrentIndex(index) + index = self._combo.findText(key) + self._combo.setCurrentIndex(index) if self._value != value: self.changed_event() self._value = val @property def text(self): - return str(self._form.comboBox.currentText()) + return str(self._combo.currentText()) @text.setter def text(self, value): @@ -146,7 +186,10 @@ def text(self, value): @property def label(self): - return self._form.comboLabel.text() + if self._combolabel: + return self._combolabel.text() + else: + return None @label.setter def label(self, value): @@ -154,7 +197,9 @@ def label(self, value): Label of the control, if applies @type value: string """ - self._form.comboLabel.setText(value) + if self._combolabel: + self._combolabel.setText(value) + ########################################################################## ############ Private functions ########################################### @@ -162,7 +207,7 @@ def label(self, value): def _activated(self, index): if not self._addingItem: - item = self._form.comboBox.currentText() + item = self._combo.currentText() if len(item) >= 1: ControlBase.value.fset(self, self._items[str(item)]) self.activated_event(index) @@ -179,7 +224,7 @@ def _editTextChanged(self, text): def _currentIndexChanged(self, index): if not self._addingItem: - item = self._form.comboBox.currentText() + item = self._combo.currentText() if len(item) >= 1: ControlBase.value.fset(self, self._items[str(item)]) self.current_index_changed_event(index) diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/Controls/ControlList.py index ade9230..ab28db4 100755 --- a/pyforms/gui/Controls/ControlList.py +++ b/pyforms/gui/Controls/ControlList.py @@ -157,6 +157,10 @@ def set_value(self, column, row, value): self.tableWidget.setCellWidget(row, column, value) value.show() self.tableWidget.setRowHeight(row, value.height()) + elif isinstance(value, ControlBase): + self.tableWidget.setCellWidget(row, column, value.form) + value.show() + self.tableWidget.setRowHeight(row, value.form.height()) else: args = [value] if not hasattr(value, 'icon') else [QIcon(value.icon), value] item = QTableWidgetItem() diff --git a/pyforms/gui/Controls/ControlPlayer/AbstractGLWidget.py b/pyforms/gui/Controls/ControlPlayer/AbstractGLWidget.py index 493509b..bdb8d14 100644 --- a/pyforms/gui/Controls/ControlPlayer/AbstractGLWidget.py +++ b/pyforms/gui/Controls/ControlPlayer/AbstractGLWidget.py @@ -40,6 +40,7 @@ def __init__(self, event): self.x = event.x() self.y = event.y() self.button = event.button() + self.event = event class AbstractGLWidget(object): @@ -455,39 +456,39 @@ def keyReleaseEvent(self, event): if event.key() == QtCore.Qt.Key_M: self._move_img = False if event.key() == QtCore.Qt.Key_1: - self._control.speed = 1 + self._control.next_frame_step = 1 self.show_tmp_msg('Speed: 1x') if event.key() == QtCore.Qt.Key_2: - self._control.speed = 2 + self._control.next_frame_step = 2 self.show_tmp_msg('Speed: 2x') if event.key() == QtCore.Qt.Key_3: - self._control.speed = 3 + self._control.next_frame_step = 3 self.show_tmp_msg('Speed: 3x') if event.key() == QtCore.Qt.Key_4: - self._control.speed = 4 + self._control.next_frame_step = 4 self.show_tmp_msg('Speed: 4x') if event.key() == QtCore.Qt.Key_5: - self._control.speed = 5 + self._control.next_frame_step = 5 self.show_tmp_msg('Speed: 5x') if event.key() == QtCore.Qt.Key_6: - self._control.speed = 6 + self._control.next_frame_step = 6 self.show_tmp_msg('Speed: 6x') if event.key() == QtCore.Qt.Key_7: - self._control.speed = 7 + self._control.next_frame_step = 7 self.show_tmp_msg('Speed: 7x') if event.key() == QtCore.Qt.Key_8: - self._control.speed = 8 + self._control.next_frame_step = 8 self.show_tmp_msg('Speed: 8x') if event.key() == QtCore.Qt.Key_9: - self._control.speed = 9 + self._control.next_frame_step = 9 self.show_tmp_msg('Speed: 9x') diff --git a/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py b/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py index 466d76f..ee0a3cb 100755 --- a/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py +++ b/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py @@ -78,8 +78,6 @@ def init_form(self): self.videoPlay.setIcon(conf.PYFORMS_ICON_VIDEOPLAYER_PAUSE_PLAY) - - self._videoWidget = VideoGLWidget() self._videoWidget._control = self self.videoLayout.addWidget(self._videoWidget) diff --git a/pyforms/gui/Controls/comboInput.ui b/pyforms/gui/Controls/comboInput.ui deleted file mode 100755 index 7c06100..0000000 --- a/pyforms/gui/Controls/comboInput.ui +++ /dev/null @@ -1,53 +0,0 @@ - - - Form - - - - 0 - 0 - 169 - 38 - - - - - 0 - 38 - - - - - 16777215 - 38 - - - - Form - - - - 0 - - - - - TextLabel - - - - - - - - 0 - 0 - - - - - - - - - diff --git a/pyforms/utils/make_lambda.py b/pyforms/utils/make_lambda.py new file mode 100644 index 0000000..fab247b --- /dev/null +++ b/pyforms/utils/make_lambda.py @@ -0,0 +1,5 @@ + + +def make_lambda_func(func, **kwargs): + """ Auxiliar function for passing parameters to functions """ + return lambda: func(**kwargs) \ No newline at end of file From 43389c0c76ebfa5ad369ff2eb9f55155faaa72b0 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 24 Nov 2017 11:20:58 +0000 Subject: [PATCH 08/66] Added clear function to ControlEventsGraph --- .../ControlEventsGraph/ControlEventsGraph.py | 260 +++++++++--------- 1 file changed, 132 insertions(+), 128 deletions(-) diff --git a/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py b/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py index 072503a..78bec36 100755 --- a/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py +++ b/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py @@ -9,148 +9,152 @@ from pyforms.gui.Controls.ControlEventsGraph.EventsWidget import EventsWidget if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog - from PyQt5 import QtCore + from PyQt5.QtWidgets import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog + from PyQt5 import QtCore else: - from PyQt4.QtGui import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog - from PyQt4 import QtCore + from PyQt4.QtGui import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog + from PyQt4 import QtCore class ControlEventsGraph(ControlBase, QWidget): - """ - Timeline events editor - """ - - def __init__(self, label="", default=0, min=0, max=100, **kwargs): - """ - - :param label: - :param default: - :param min: - :param max: - :param kwargs: - """ - QWidget.__init__(self) - ControlBase.__init__(self, label, default, **kwargs) - self.add_popup_menu_option('Export to CSV', self.__export) - - def init_form(self): - vlayout = QVBoxLayout() - - if conf.PYFORMS_USE_QT5: - vlayout.setContentsMargins(0,0,0,0) - else: - vlayout.setMargin(0) - - self.setLayout(vlayout) - - self._scroll = QScrollBar(QtCore.Qt.Horizontal) - - scrollarea = QScrollArea() - scrollarea.setMinimumHeight(140) - scrollarea.setWidgetResizable(True) - - self._events_widget = EventsWidget(scroll=self._scroll) - scrollarea.setWidget(self._events_widget) - - self._scroll.actionTriggered.connect(self.__scroll_changed) - - vlayout.addWidget(scrollarea) # The timeline widget - vlayout.addWidget(self._scroll) # Add scroll - - self._scroll.setMaximum(0) - self._scroll.setSliderPosition(0) - - ########################################################################## - #### HELPERS/PUBLIC FUNCTIONS ############################################ - ########################################################################## - - def add_track(self, title=None): - """ - - :param title: - """ - self._events_widget.add_track(title) - - def add_event(self, begin, end, title='', track=0, color='#FFFF00'): - """ - - :param begin: - :param end: - :param title: - :param track: - :param color: - :return: - """ - return self._events_widget.add_event(begin, end, title, track, color) - - ########################################################################## - #### EVENTS ############################################################## - ########################################################################## - - def __scroll_changed(self, change): self.repaint() - - def get_export_filename(self): return "untitled.csv" - - def __export(self): - """Export annotations to a file.""" - filename = QFileDialog.getSaveFileName(parent=self, - caption="Export annotations file", - directory=self.get_export_filename(), - filter="CSV Files (*.csv)", - options=QFileDialog.DontUseNativeDialog) - if filename != '': - self.export_csv(filename) - - def export_csv(self, filename): - """ - Export annotations to a file. - :param str filename: filename to open - """ - with open(filename, 'wb') as csvfile: - spamwriter = csv.writer(csvfile, dialect='excel') - self._events_widget.export_csv(spamwriter) - - def repaint(self): - """ - - """ - self._events_widget.repaint() - - ########################################################################## - #### PROPERTIES ########################################################## - ########################################################################## - """ + """ + Timeline events editor + """ + + def __init__(self, label="", default=0, min=0, max=100, **kwargs): + """ + + :param label: + :param default: + :param min: + :param max: + :param kwargs: + """ + QWidget.__init__(self) + ControlBase.__init__(self, label, default, **kwargs) + self.add_popup_menu_option('Export to CSV', self.__export) + + def init_form(self): + vlayout = QVBoxLayout() + + if conf.PYFORMS_USE_QT5: + vlayout.setContentsMargins(0, 0, 0, 0) + else: + vlayout.setMargin(0) + + self.setLayout(vlayout) + + self._scroll = QScrollBar(QtCore.Qt.Horizontal) + + scrollarea = QScrollArea() + scrollarea.setMinimumHeight(140) + scrollarea.setWidgetResizable(True) + + self._events_widget = EventsWidget(scroll=self._scroll) + scrollarea.setWidget(self._events_widget) + + self._scroll.actionTriggered.connect(self.__scroll_changed) + + vlayout.addWidget(scrollarea) # The timeline widget + vlayout.addWidget(self._scroll) # Add scroll + + self._scroll.setMaximum(0) + self._scroll.setSliderPosition(0) + + ########################################################################## + #### HELPERS/PUBLIC FUNCTIONS ############################################ + ########################################################################## + + def clear(self): + self._events_widget.clear() + + def add_track(self, title=None): + """ + + :param title: + """ + self._events_widget.add_track(title) + + def add_event(self, begin, end, title='', track=0, color='#FFFF00'): + """ + + :param begin: + :param end: + :param title: + :param track: + :param color: + :return: + """ + return self._events_widget.add_event(begin, end, title, track, color) + + ########################################################################## + #### EVENTS ############################################################## + ########################################################################## + + def __scroll_changed(self, change): self.repaint() + + def get_export_filename(self): return "untitled.csv" + + def __export(self): + """Export annotations to a file.""" + filename = QFileDialog.getSaveFileName(parent=self, + caption="Export annotations file", + directory=self.get_export_filename(), + filter="CSV Files (*.csv)", + options=QFileDialog.DontUseNativeDialog) + if filename != '': + self.export_csv(filename) + + def export_csv(self, filename): + """ + Export annotations to a file. + :param str filename: filename to open + """ + with open(filename, 'wb') as csvfile: + spamwriter = csv.writer(csvfile, dialect='excel') + self._events_widget.export_csv(spamwriter) + + def repaint(self): + """ + + """ + self._events_widget.repaint() + + ########################################################################## + #### PROPERTIES ########################################################## + ########################################################################## + """ Overwrite the changed event from the ControlBase """ - @property - def changed_event(self): return self._events_widget._pointer.moveEvent + @property + def changed_event(self): return self._events_widget._pointer.moveEvent - @changed_event.setter - def changed_event(self, value): self._events_widget._pointer.moveEvent = value + @changed_event.setter + def changed_event( + self, value): self._events_widget._pointer.moveEvent = value - @property - def value(self): return self._events_widget.position + @property + def value(self): return self._events_widget.position - @value.setter - def value(self, value): self._events_widget.position = value + @value.setter + def value(self, value): self._events_widget.position = value - @property - def form(self): return self + @property + def form(self): return self - @property - def tracks(self): return self._events_widget.tracks + @property + def tracks(self): return self._events_widget.tracks - @property - def tracks_height(self): return self._events_widget.tracks_height + @property + def tracks_height(self): return self._events_widget.tracks_height - @tracks_height.setter - def tracks_height(self, value): self._events_widget.tracks_height = value + @tracks_height.setter + def tracks_height(self, value): self._events_widget.tracks_height = value - @property - def scale(self): return self._events_widget.scale + @property + def scale(self): return self._events_widget.scale - @scale.setter - def scale(self, value): self._events_widget.scale = value + @scale.setter + def scale(self, value): self._events_widget.scale = value From 5bc44a14450c055037b1c404d112c70652f47b72 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 24 Nov 2017 16:46:12 +0000 Subject: [PATCH 09/66] Modify function clean to clear on ControlEventsGraph.EventsWidget --- pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py b/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py index f5d82f4..0be5efa 100755 --- a/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py +++ b/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py @@ -53,7 +53,7 @@ def __init__(self, scroll): #### HELPERS/FUNCTIONS ################################################### ########################################################################## - def clean(self): + def clear(self): """ Clean all events """ From 14dd84be99041e1670e5475089bd29f6b10f6882 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 28 Nov 2017 16:51:43 +0000 Subject: [PATCH 10/66] Add a save flag to the ControlFile --- docs/api-documentation/controls.md | 7 +++++++ pyforms/gui/Controls/ControlFile.py | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/api-documentation/controls.md b/docs/api-documentation/controls.md index 0b025cd..cdd5bbe 100644 --- a/docs/api-documentation/controls.md +++ b/docs/api-documentation/controls.md @@ -613,6 +613,13 @@ Returns a list of graphs objects. The control may be used to select a file. +### **Constructer** +*************************** + +#### \_\_init\_\_(label='', default='', helptext='', use_save_dialog=False) + +**use_save_dialog** - By default the control will select a file to be opened. If this flab is True The control will open a file to be created or updated. + ### **Functions** *************************** diff --git a/pyforms/gui/Controls/ControlFile.py b/pyforms/gui/Controls/ControlFile.py index 5c56d77..ce6f509 100755 --- a/pyforms/gui/Controls/ControlFile.py +++ b/pyforms/gui/Controls/ControlFile.py @@ -13,6 +13,11 @@ class ControlFile(ControlText): + + def __init__(self, label='', default=None, helptext=None, use_save_dialog=False): + super(ControlFile, self).__init__(label, default, helptext) + self.use_save_dialog = use_save_dialog + def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "fileInput.ui") self._form = uic.loadUi(control_path) @@ -26,7 +31,12 @@ def finishEditing(self): self.changed_event() def click(self): - value = QFileDialog.getOpenFileName(self.parent, self._label, self.value) + + if self.use_save_dialog: + value = QFileDialog.getSaveFileName(self.parent, self._label, self.value) + else: + value = QFileDialog.getOpenFileName(self.parent, self._label, self.value) + if conf.PYFORMS_USE_QT5: value = value[0] From e85dc6294cb44fedd06263a5ea13a1dc8e6be72f Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 14 Dec 2017 16:02:42 +0000 Subject: [PATCH 11/66] . --- pyforms/gui/BaseWidget.py | 930 ++++++++++++++-------------- pyforms/gui/Controls/ControlBase.py | 476 +++++++------- 2 files changed, 709 insertions(+), 697 deletions(-) diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/BaseWidget.py index 49678a1..a60b88c 100644 --- a/pyforms/gui/BaseWidget.py +++ b/pyforms/gui/BaseWidget.py @@ -10,483 +10,465 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QFrame - from PyQt5.QtWidgets import QVBoxLayout - from PyQt5.QtWidgets import QTabWidget - from PyQt5.QtWidgets import QSplitter - from PyQt5.QtWidgets import QHBoxLayout - from PyQt5.QtWidgets import QSpacerItem - from PyQt5.QtWidgets import QSizePolicy - from PyQt5.QtWidgets import QLabel - from PyQt5.QtGui import QFont - from PyQt5.QtWidgets import QFileDialog - from PyQt5.QtWidgets import QApplication - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QFrame - from PyQt4.QtGui import QVBoxLayout - from PyQt4.QtGui import QTabWidget - from PyQt4.QtGui import QSplitter - from PyQt4.QtGui import QHBoxLayout - from PyQt4.QtGui import QSpacerItem - from PyQt4.QtGui import QSizePolicy - from PyQt4.QtGui import QLabel - from PyQt4.QtGui import QFont - from PyQt4.QtGui import QFileDialog - from PyQt4.QtGui import QApplication - from PyQt4 import QtCore +from AnyQt.QtWidgets import QFrame +from AnyQt.QtWidgets import QVBoxLayout +from AnyQt.QtWidgets import QTabWidget +from AnyQt.QtWidgets import QSplitter +from AnyQt.QtWidgets import QHBoxLayout +from AnyQt.QtWidgets import QSpacerItem +from AnyQt.QtWidgets import QSizePolicy +from AnyQt.QtWidgets import QLabel +from AnyQt.QtWidgets import QFileDialog +from AnyQt.QtWidgets import QApplication +from AnyQt.QtGui import QFont +from AnyQt import QtCore +import AnyQt from pyforms.gui.Controls.ControlBase import ControlBase from pyforms.gui.Controls.ControlProgress import ControlProgress class BaseWidget(QFrame): - """ - The class implements the most basic widget or window. - """ - - def __init__(self, title='Untitled', parent_win=None, win_flag=None): - if parent_win is not None and win_flag is None: win_flag = QtCore.Qt.Dialog - - QFrame.__init__(self) if parent_win is None else QFrame.__init__(self, parent_win, win_flag) - - # self.setObjectName(self.__class__.__name__) - - - layout = QVBoxLayout() - self.setLayout(layout) - - if conf.PYFORMS_USE_QT5: - layout.setContentsMargins(0,0,0,0) - else: - layout.setMargin(0) - - self.title = title - self.has_progress = False - - self._mainmenu = [] - self._splitters = [] - self._tabs = [] - self._formset = None - self._formLoaded = False - self.uid = id(self) - - self.setAccessibleName('BaseWidget') - - ########################################################################## - ############ FUNCTIONS ################################################## - ########################################################################## - - - def init_form(self): - """ - Generate the module Form - """ - if not self._formLoaded: - - if self.has_progress: - self._progress = ControlProgress("Progress", 0, 100) - self._progress.hide() - if self._formset != None: - self._formset += ['_progress'] - - if self._formset is not None: - control = self.generate_panel(self._formset) - self.layout().addWidget(control) - else: - allparams = self.controls - for key, param in allparams.items(): - param.parent = self - param.name = key - self.layout().addWidget(param.form) - self._formLoaded = True - - def set_margin(self, margin): - if conf.PYFORMS_USE_QT5: - self.layout().setContentsMargins(margin,margin,margin,margin) - else: - self.layout().setMargin(margin) - - - def generate_tabs(self, formsetdict): - """ - Generate QTabWidget for the module form - @param formset: Tab form configuration - @type formset: dict - """ - tabs = QTabWidget(self) - for key, item in sorted(formsetdict.items()): - ctrl = self.generate_panel(item) - tabs.addTab(ctrl, key[key.find(':') + 1:]) - return tabs - - def generate_panel(self, formset): - """ - Generate a panel for the module form with all the controls - formset format example: [('_video', '_arenas', '_run'), {"Player":['_threshold', "_player", "=", "_results", "_query"], "Background image":[(' ', '_selectBackground', '_paintBackground'), '_image']}, "_progress"] - tuple: will display the controls in the same horizontal line - list: will display the controls in the same vertical line - dict: will display the controls in a tab widget - '||': will plit the controls in a horizontal line - '=': will plit the controls in a vertical line - @param formset: Form configuration - @type formset: list - """ - control = None - if '=' in formset: - control = QSplitter(QtCore.Qt.Vertical) - tmp = list(formset) - index = tmp.index('=') - firstPanel = self.generate_panel(formset[0:index]) - secondPanel = self.generate_panel(formset[index + 1:]) - control.addWidget(firstPanel) - control.addWidget(secondPanel) - self._splitters.append(control) - return control - elif '||' in formset: - control = QSplitter(QtCore.Qt.Horizontal) - tmp = list(formset) - rindex = lindex = index = tmp.index('||') - rindex -= 1 - rindex += 2 - if isinstance(formset[lindex - 1], int): - lindex = lindex - 1 - if len(formset) > rindex and isinstance(formset[index + 1], int): - rindex += 1 - firstPanel = self.generate_panel(formset[0:lindex]) - secondPanel = self.generate_panel(formset[rindex:]) - if isinstance(formset[index - 1], int): - firstPanel.setMaximumWidth(formset[index - 1]) - if isinstance(formset[index + 1], int): - secondPanel.setMaximumWidth(formset[index + 1]) - control.addWidget(firstPanel) - control.addWidget(secondPanel) - self._splitters.append(control) - return control - control = QFrame(self) - layout = None - if type(formset) is tuple: - layout = QHBoxLayout() - for row in formset: - if isinstance(row, (list, tuple)): - panel = self.generate_panel(row) - layout.addWidget(panel) - elif row == " ": - spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) - layout.addItem(spacer) - elif type(row) is dict: - c = self.generate_tabs(row) - layout.addWidget(c) - self._tabs.append(c) - else: - param = self.controls.get(row, None) - if param is None: - label = QLabel() - label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) - # layout.addWidget( label ) - - if row.startswith('info:'): - label.setText(row[5:]) - font = QFont() - font.setPointSize(10) - label.setFont(font) - label.setAccessibleName('info') - elif row.startswith('h1:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(17) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h1') - elif row.startswith('h2:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(16) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h2') - elif row.startswith('h3:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(15) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h3') - elif row.startswith('h4:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(14) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h4') - elif row.startswith('h5:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(12) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h5') - else: - label.setText(row) - font = QFont() - font.setPointSize(10) - label.setFont(font) - label.setAccessibleName('msg') - label.setToolTip(label.text()) - layout.addWidget(label) - else: - param.parent = self - param.name = row - layout.addWidget(param.form) - elif type(formset) is list: - layout = QVBoxLayout() - for row in formset: - if isinstance(row, (list, tuple)): - panel = self.generate_panel(row) - layout.addWidget(panel) - elif row == " ": - spacer = QSpacerItem( - 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) - layout.addItem(spacer) - elif type(row) is dict: - c = self.generate_tabs(row) - layout.addWidget(c) - self._tabs.append(c) - else: - param = self.controls.get(row, None) - if param is None: - label = QLabel() - label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) - label.resize(30, 30) - # layout.addWidget( label ) - - if row.startswith('info:'): - label.setText(row[5:]) - font = QFont() - font.setPointSize(10) - label.setFont(font) - label.setAccessibleName('info') - elif row.startswith('h1:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(17) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h1') - elif row.startswith('h2:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(16) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h2') - elif row.startswith('h3:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(15) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h3') - elif row.startswith('h4:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(14) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h4') - elif row.startswith('h5:'): - label.setText(row[3:]) - font = QFont() - font.setPointSize(12) - font.setBold(True) - label.setFont(font) - label.setAccessibleName('h5') - else: - label.setText(row) - font = QFont() - font.setPointSize(10) - label.setFont(font) - label.setAccessibleName('msg') - - label.setToolTip(label.text()) - - layout.addWidget(label) - else: - param.parent = self - param.name = row - layout.addWidget(param.form) - - if conf.PYFORMS_USE_QT5: - layout.setContentsMargins(0,0,0,0) - else: - layout.setMargin(0) - - control.setLayout(layout) - return control - - def show(self): - """ - It shows the - """ - self.init_form() - super(BaseWidget, self).show() - - def save_form(self, data={}, path=None): - allparams = self.controls - - if hasattr(self, 'load_order'): - for name in self.load_order: - param = allparams[name] - data[name] = {} - param.save_form(data[name]) - else: - for name, param in allparams.items(): - data[name] = {} - param.save_form(data[name]) - return data - - def load_form(self, data, path=None): - allparams = self.controls - - if hasattr(self, 'load_order'): - for name in self.load_order: - param = allparams[name] - if name in data: - param.load_form(data[name]) - else: - for name, param in allparams.items(): - if name in data: - param.load_form(data[name]) - # self.init_form() - - def save_window(self): - allparams = self.controls - data = {} - self.save_form(data) - - filename = QFileDialog.getSaveFileName(self, 'Select file') - with open(filename, 'w') as output_file: json.dump(data, output_file) - - def load_form_filename(self, filename): - with open(filename, 'r') as pkl_file: - project_data = json.load(pkl_file) - data = dict(project_data) - self.load_form(data) - - def load_window(self): - filename = QFileDialog.getOpenFileNames(self, 'Select file') - self.load_form_filename(str(filename[0])) - - ########################################################################## - ############ EVENTS ###################################################### - ########################################################################## - - def before_close_event(self): - """ - Do something before closing widget - Note that the window will be closed anyway - """ - pass - - ########################################################################## - ############ Properties ################################################## - ########################################################################## - - @property - def form_has_loaded(self): - return self._formLoaded - - @property - def controls(self): - """ - Return all the form controls from the the module - """ - result = {} - for name, var in vars(self).items(): - try: - if isinstance(var, ControlBase): - result[name] = var - except: - pass - return result - - @property - def form(self): - return self - - @property - def title(self): - return self.windowTitle() - - @title.setter - def title(self, value): - self.setWindowTitle(value) - - @property - def mainmenu(self): - return self._mainmenu - - @mainmenu.setter - def mainmenu(self, value): - self._mainmenu = value - - @property - def formset(self): - return self._formset - - @formset.setter - def formset(self, value): - self._formset = value - - @property - def uid(self): - return self._uid - - @uid.setter - def uid(self, value): - self._uid = value - - @property - def max_progress(self): - return self._progress.max - - @max_progress.setter - def max_progress(self, value): - self._progress.max = value - - @property - def min_progress(self): - return self._progress.min - - @min_progress.setter - def min_progress(self, value): - self._progress.min = value - - @property - def progress(self): - return self._progress.value - - @progress.setter - def progress(self, value): - self._progress.value = value - QApplication.processEvents() - - if value == self.max_progress: self._progress.hide() - if value == self.min_progress: self._progress.show() - - @property - def visible(self): - return self.isVisible() - - @visible.setter - def visible(self, value): - self.show() if value else self.hide() - - ########################################################################## - ############ PRIVATE FUNCTIONS ########################################### - ########################################################################## - def closeEvent(self, event): - self.before_close_event() - super(BaseWidget, self).closeEvent(event) + """ + The class implements the most basic widget or window. + """ + + def __init__(self, title='Untitled', parent_win=None, win_flag=None): + if parent_win is not None and win_flag is None: win_flag = QtCore.Qt.Dialog + + QFrame.__init__(self) if parent_win is None else QFrame.__init__(self, parent_win, win_flag) + + # self.setObjectName(self.__class__.__name__) + + layout = QVBoxLayout() + self.setLayout(layout) + + if AnyQt.USED_API=='pyqt5': + layout.setContentsMargins(0,0,0,0) + else: + layout.setMargin(0) + + self.title = title + self.has_progress = False + + self._mainmenu = [] + self._splitters = [] + self._tabs = [] + self._formset = None + self._formLoaded = False + self.uid = id(self) + + self.setAccessibleName('BaseWidget') + + ########################################################################## + ############ FUNCTIONS ################################################## + ########################################################################## + + def init_form(self): + """ + Generate the module Form + """ + if not self._formLoaded: + + if self.has_progress: + self._progress = ControlProgress("Progress", 0, 100) + self._progress.hide() + if self._formset != None: + self._formset += ['_progress'] + + if self._formset is not None: + control = self.generate_panel(self._formset) + self.layout().addWidget(control) + else: + allparams = self.controls + for key, param in allparams.items(): + param.parent = self + param.name = key + self.layout().addWidget(param.form) + self._formLoaded = True + + + + + def generate_tabs(self, formsetdict): + """ + Generate QTabWidget for the module form + @param formset: Tab form configuration + @type formset: dict + """ + tabs = QTabWidget(self) + for key, item in sorted(formsetdict.items()): + ctrl = self.generate_panel(item) + tabs.addTab(ctrl, key[key.find(':') + 1:]) + return tabs + + def generate_panel(self, formset): + """ + Generate a panel for the module form with all the controls + formset format example: [('_video', '_arenas', '_run'), {"Player":['_threshold', "_player", "=", "_results", "_query"], "Background image":[(' ', '_selectBackground', '_paintBackground'), '_image']}, "_progress"] + tuple: will display the controls in the same horizontal line + list: will display the controls in the same vertical line + dict: will display the controls in a tab widget + '||': will plit the controls in a horizontal line + '=': will plit the controls in a vertical line + @param formset: Form configuration + @type formset: list + """ + control = None + if '=' in formset: + control = QSplitter(QtCore.Qt.Vertical) + tmp = list(formset) + index = tmp.index('=') + firstPanel = self.generate_panel(formset[0:index]) + secondPanel = self.generate_panel(formset[index + 1:]) + control.addWidget(firstPanel) + control.addWidget(secondPanel) + self._splitters.append(control) + return control + elif '||' in formset: + control = QSplitter(QtCore.Qt.Horizontal) + tmp = list(formset) + rindex = lindex = index = tmp.index('||') + rindex -= 1 + rindex += 2 + if isinstance(formset[lindex - 1], int): + lindex = lindex - 1 + if len(formset) > rindex and isinstance(formset[index + 1], int): + rindex += 1 + firstPanel = self.generate_panel(formset[0:lindex]) + secondPanel = self.generate_panel(formset[rindex:]) + if isinstance(formset[index - 1], int): + firstPanel.setMaximumWidth(formset[index - 1]) + if isinstance(formset[index + 1], int): + secondPanel.setMaximumWidth(formset[index + 1]) + control.addWidget(firstPanel) + control.addWidget(secondPanel) + self._splitters.append(control) + return control + control = QFrame(self) + layout = None + if type(formset) is tuple: + layout = QHBoxLayout() + for row in formset: + if isinstance(row, (list, tuple)): + panel = self.generate_panel(row) + layout.addWidget(panel) + elif row == " ": + spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + layout.addItem(spacer) + elif type(row) is dict: + c = self.generate_tabs(row) + layout.addWidget(c) + self._tabs.append(c) + else: + param = self.controls.get(row, None) + if param is None: + label = QLabel() + label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) + # layout.addWidget( label ) + + if row.startswith('info:'): + label.setText(row[5:]) + font = QFont() + font.setPointSize(10) + label.setFont(font) + label.setAccessibleName('info') + elif row.startswith('h1:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(17) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h1') + elif row.startswith('h2:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(16) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h2') + elif row.startswith('h3:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(15) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h3') + elif row.startswith('h4:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(14) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h4') + elif row.startswith('h5:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(12) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h5') + else: + label.setText(row) + font = QFont() + font.setPointSize(10) + label.setFont(font) + label.setAccessibleName('msg') + label.setToolTip(label.text()) + layout.addWidget(label) + else: + param.parent = self + param.name = row + layout.addWidget(param.form) + elif type(formset) is list: + layout = QVBoxLayout() + for row in formset: + if isinstance(row, (list, tuple)): + panel = self.generate_panel(row) + layout.addWidget(panel) + elif row == " ": + spacer = QSpacerItem( + 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + layout.addItem(spacer) + elif type(row) is dict: + c = self.generate_tabs(row) + layout.addWidget(c) + self._tabs.append(c) + else: + param = self.controls.get(row, None) + if param is None: + label = QLabel() + label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) + label.resize(30, 30) + # layout.addWidget( label ) + + if row.startswith('info:'): + label.setText(row[5:]) + font = QFont() + font.setPointSize(10) + label.setFont(font) + label.setAccessibleName('info') + elif row.startswith('h1:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(17) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h1') + elif row.startswith('h2:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(16) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h2') + elif row.startswith('h3:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(15) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h3') + elif row.startswith('h4:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(14) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h4') + elif row.startswith('h5:'): + label.setText(row[3:]) + font = QFont() + font.setPointSize(12) + font.setBold(True) + label.setFont(font) + label.setAccessibleName('h5') + else: + label.setText(row) + font = QFont() + font.setPointSize(10) + label.setFont(font) + label.setAccessibleName('msg') + + label.setToolTip(label.text()) + + layout.addWidget(label) + else: + param.parent = self + param.name = row + layout.addWidget(param.form) + + if AnyQt.USED_API=='pyqt5': + layout.setContentsMargins(0,0,0,0) + else: + layout.setMargin(0) + + control.setLayout(layout) + return control + + def show(self): + self.init_form() + super(BaseWidget, self).show() + + def save_form(self, data={}, path=None): + allparams = self.controls + + if hasattr(self, 'load_order'): + for name in self.load_order: + param = allparams[name] + data[name] = {} + param.save_form(data[name]) + else: + for name, param in allparams.items(): + data[name] = {} + param.save_form(data[name]) + return data + + def load_form(self, data, path=None): + allparams = self.controls + + if hasattr(self, 'load_order'): + for name in self.load_order: + param = allparams[name] + if name in data: + param.load_form(data[name]) + else: + for name, param in allparams.items(): + if name in data: + param.load_form(data[name]) + # self.init_form() + + def save_window(self): + allparams = self.controls + data = {} + self.save_form(data) + + filename = QFileDialog.getSaveFileName(self, 'Select file') + with open(filename, 'w') as output_file: json.dump(data, output_file) + + def load_form_filename(self, filename): + with open(filename, 'r') as pkl_file: + project_data = json.load(pkl_file) + data = dict(project_data) + self.load_form(data) + + def load_window(self): + filename = QFileDialog.getOpenFileNames(self, 'Select file') + self.load_form_filename(str(filename[0])) + + def close(self): + super(BaseWidget, self).close() + + def message(self, msg, title=None, msg_type=None): pass + def success(self, msg, title=None): self.message(msg, title, msg_type='success') + def info(self, msg, title=None): self.message(msg, title, msg_type='info') + def warning(self, msg, title=None): self.message(msg, title, msg_type='warning'); + def alert(self, msg, title=None): self.message(msg, title, msg_type='error') + + def message_popup(self, msg, title='', buttons=None, handler=None, msg_type='success'): + pass + def success_popup(self, msg, title='', buttons=None, handler=None): + return self.message_popup(msg, title, buttons, handler, msg_type='success') + def info_popup(self, msg, title='', buttons=None, handler=None): + return self.message_popup(msg, title, buttons, handler, msg_type='info') + def warning_popup(self, msg, title='', buttons=None, handler=None): + return self.message_popup(msg, title, buttons, handler, msg_type='warning') + def alert_popup(self, msg, title='', buttons=None, handler=None): + return self.message_popup(msg, title, buttons, handler, msg_type='alert') + + + ########################################################################## + ############ GUI functions ############################################### + ########################################################################## + + def set_margin(self, margin): + if AnyQt.USED_API=='pyqt5': + self.layout().setContentsMargins(margin,margin,margin,margin) + else: + self.layout().setMargin(margin) + + ########################################################################## + ############ EVENTS ###################################################### + ########################################################################## + + def before_close_event(self): + """ + Do something before closing widget + Note that the window will be closed anyway + """ + pass + + ########################################################################## + ############ Properties ################################################## + ########################################################################## + + @property + def controls(self): + """ + Return all the form controls from the the module + """ + result = {} + for name, var in vars(self).items(): + try: + if isinstance(var, ControlBase): + result[name] = var + except: + pass + return result + + ############################################################################ + ############ GUI Properties ################################################ + ############################################################################ + + + @property + def form_has_loaded(self): + return self._formLoaded + + + + @property + def form(self): + return self + + @property + def title(self): + return self.windowTitle() + + @title.setter + def title(self, value): + self.setWindowTitle(value) + + + @property + def formset(self): + return self._formset + + @formset.setter + def formset(self, value): + self._formset = value + + @property + def uid(self): + return self._uid + + @uid.setter + def uid(self, value): + self._uid = value + + + @property + def visible(self): + return self.isVisible() + + @visible.setter + def visible(self, value): + self.show() if value else self.hide() + + ########################################################################## + ############ PRIVATE FUNCTIONS ########################################### + ########################################################################## + + def closeEvent(self, event): + self.before_close_event() + super(BaseWidget, self).closeEvent(event) diff --git a/pyforms/gui/Controls/ControlBase.py b/pyforms/gui/Controls/ControlBase.py index 036df10..b9f3015 100755 --- a/pyforms/gui/Controls/ControlBase.py +++ b/pyforms/gui/Controls/ControlBase.py @@ -1,230 +1,260 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pysettings import conf -from AnyQt import QtCore, uic +from AnyQt import QtCore, uic from AnyQt.QtWidgets import QMenu, QAction -from AnyQt.QtGui import QIcon, QKeySequence +from AnyQt.QtGui import QIcon, QKeySequence class ControlBase(object): - """ - This class represents the most basic control that can exist - A Control is a Widget or a group of widgets that can be reused from application to application - - @undocumented: __repr__ - """ - - def __init__(self, label='', default=None, helptext=None): - self._help = helptext - self._value = default - self._form = None # Qt widget - self._parent = None # Parent window - self._label = label # Label - self._popup_menu = None - - self.init_form() - - - def init_form(self): - """ - Load Control and initiate the events - """ - if self.help: self.form.setToolTip(self.help) - - - def __repr__(self): return str(self._value) - - ########################################################################## - ############ Funcions #################################################### - ########################################################################## - - def load_form(self, data, path=None): - """ - Load a value from the dict variable - @param data: dictionary with the value of the Control - """ - if 'value' in data: - self.value = data['value'] - - def save_form(self, data, path=None): - """ - Save a value to dict variable - @param data: dictionary with to where the value of the Control will be added - """ - if self.value: - data['value'] = self.value - return data - - def show(self): - """ - Show the control - """ - if self.form is None: - return - self.form.show() - - def hide(self): - """ - Hide the control - """ - if self.form is None: - return - self.form.hide() - - - def __create_popup_menu(self): - if not self._popup_menu: - self.form.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - self.form.customContextMenuRequested.connect(self._open_popup_menu) - self._popup_menu = QMenu(self.parent) - self._popup_menu.aboutToShow.connect( self.about_to_show_contextmenu_event) - - def add_popup_submenu(self, label, submenu=None): - self.__create_popup_menu() - menu = submenu if submenu else self._popup_menu - submenu = QMenu(label, menu) - menu.addMenu(submenu) - return submenu - - def add_popup_menu_option(self, label, function_action=None, key=None, icon=None, submenu=None): - """ - Add an option to the Control popup menu - @param label: label of the option. - @param function_action: function called when the option is selected. - @param key: shortcut key - @param icon: icon - """ - self.__create_popup_menu() - - menu = submenu if submenu else self._popup_menu - - if label == "-": - return menu.addSeparator() - else: - action = QAction(label, self.form) - if icon is not None: - action.setIconVisibleInMenu(True) - action.setIcon(icon if isinstance(icon, QIcon) else QIcon(icon) ) - if key != None: - action.setShortcut(QKeySequence(key)) - if function_action: - action.triggered.connect(function_action) - menu.addAction(action) - return action - - - ########################################################################## - ############ Events ###################################################### - ########################################################################## - - def changed_event(self): - """ - Function called when ever the Control value is changed - """ - return True - - def about_to_show_contextmenu_event(self): - """ - Function called before open the Control popup menu - """ - pass - - def _open_popup_menu(self, position): - if self._popup_menu: - self._popup_menu.exec_(self.form.mapToGlobal(position)) - - ########################################################################## - ############ Properties ################################################## - ########################################################################## - - ########################################################################## - # Set the Control enabled or disabled - - @property - def enabled(self): - return self.form.isEnabled() - - @enabled.setter - def enabled(self, value): - """@type value: boolean""" - self.form.setEnabled(value) - - ########################################################################## - # Return or update the value of the Control - - @property - def value(self): - return self._value - - @value.setter - def value(self, value): - """ - This property return and set what the control should manage or store. - @type value: string - """ - oldvalue = self._value - self._value = value - if oldvalue != value: - self.changed_event() - - @property - def visible(self): return self.form.isVisible() - - @visible.setter - def visible(self, value): - self.show() if value else self.hide() - - @property - def name(self): return self.form.objectName() - - @name.setter - def name(self, value): - """ - This property return and set the name of the control - @type value: string - """ - self.form.setObjectName(value) - - ########################################################################## - # Return or update the label of the Control - - @property - def label(self): - return self._label - - @label.setter - def label(self, value): - """ - Label of the control, if applies - @type value: string - """ - self._label = value - - ########################################################################## - # Return the QT widget - - @property - def form(self): - """ - Returns the Widget of the control. - This property will be deprecated in a future version. - """ - return self._form - - ########################################################################## - # Parent window - - @property - def parent(self): return self._parent - - @parent.setter - def parent(self, value): - """ - Returns or set the parent basewidget where the Control is - @type value: BaseWidget - """ - self._parent = value - - @property - def help(self): return self._help if self._help else '' + """ + This class represents the most basic control that can exist + A Control is a Widget or a group of widgets that can be reused from application to application + + @undocumented: __repr__ + """ + + def __init__(self, label='', default=None, helptext=None): + self._help = helptext + self._value = default + self._form = None # Qt widget + self._parent = None # Parent window + self._label = label # Label + self._popup_menu = None + + self.init_form() + + + def __repr__(self): return str(self._value) + + ########################################################################## + ############ Funcions #################################################### + ########################################################################## + + def init_form(self): + """ + Load Control and initiate the events + """ + if self.help: self.form.setToolTip(self.help) + + + def load_form(self, data, path=None): + """ + Load a value from the dict variable + @param data: dictionary with the value of the Control + """ + if 'value' in data: + self.value = data['value'] + + def save_form(self, data, path=None): + """ + Save a value to dict variable + @param data: dictionary with to where the value of the Control will be added + """ + if self.value: + data['value'] = self.value + return data + + def show(self): + """ + Show the control + """ + if self.form is None: + return + self.form.show() + + def hide(self): + """ + Hide the control + """ + if self.form is None: + return + self.form.hide() + + + def __create_popup_menu(self): + if not self._popup_menu: + self.form.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.form.customContextMenuRequested.connect(self._open_popup_menu) + self._popup_menu = QMenu(self.parent) + self._popup_menu.aboutToShow.connect( self.about_to_show_contextmenu_event) + + def add_popup_submenu(self, label, submenu=None): + self.__create_popup_menu() + menu = submenu if submenu else self._popup_menu + submenu = QMenu(label, menu) + menu.addMenu(submenu) + return submenu + + def add_popup_menu_option(self, label, function_action=None, key=None, icon=None, submenu=None): + """ + Add an option to the Control popup menu + @param label: label of the option. + @param function_action: function called when the option is selected. + @param key: shortcut key + @param icon: icon + """ + self.__create_popup_menu() + + menu = submenu if submenu else self._popup_menu + + if label == "-": + return menu.addSeparator() + else: + action = QAction(label, self.form) + if icon is not None: + action.setIconVisibleInMenu(True) + action.setIcon(icon if isinstance(icon, QIcon) else QIcon(icon) ) + if key != None: + action.setShortcut(QKeySequence(key)) + if function_action: + action.triggered.connect(function_action) + menu.addAction(action) + return action + + + ########################################################################## + ############ Events ###################################################### + ########################################################################## + + def changed_event(self): + """ + Function called when ever the Control value is changed + """ + return True + + def about_to_show_contextmenu_event(self): + """ + Function called before open the Control popup menu + """ + pass + + def _open_popup_menu(self, position): + if self._popup_menu: + self._popup_menu.exec_(self.form.mapToGlobal(position)) + + ########################################################################## + ############ Properties ################################################## + ########################################################################## + + ########################################################################## + # Set the Control enabled or disabled + + @property + def enabled(self): + return self.form.isEnabled() + + @enabled.setter + def enabled(self, value): + """@type value: boolean""" + self.form.setEnabled(value) + + ########################################################################## + # Return or update the value of the Control + + @property + def value(self): + return self._value + + @value.setter + def value(self, value): + """ + This property return and set what the control should manage or store. + @type value: string + """ + oldvalue = self._value + self._value = value + if oldvalue != value: + self.changed_event() + + + @property + def name(self): return self.form.objectName() + + @name.setter + def name(self, value): + """ + This property return and set the name of the control + @type value: string + """ + self.form.setObjectName(value) + + ########################################################################## + # Return or update the label of the Control + + @property + def label(self): + return self._label + + @label.setter + def label(self, value): + """ + Label of the control, if applies + @type value: string + """ + self._label = value + + ########################################################################## + # Parent window + + @property + def parent(self): return self._parent + + @parent.setter + def parent(self, value): + """ + Returns or set the parent basewidget where the Control is + @type value: BaseWidget + """ + self._parent = value + + @property + def visible(self): return self.form.isVisible() + + @property + def help(self): return self._help if self._help else '' + + @property + def error(self): return None + + @error.setter + def error(self, value): + pass + + @property + def label_visible(self): return None + + @label_visible.setter + def label_visible(self, value): + pass + + @property + def readonly(self): return None + + @readonly.setter + def readonly(self, value): + pass + + @property + def css(self): return None + + @css.setter + def css(self, value): + pass + + + ########################################################################## + ############ Properties just for the GUI version ######################### + ########################################################################## + + ########################################################################## + # Return the QT widget + + @property + def form(self): + """ + Returns the Widget of the control. + This property will be deprecated in a future version. + """ + return self._form From 0bf51fd25a426e70fa45bbad9a11c3966e992e5a Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Wed, 27 Dec 2017 09:52:47 +0000 Subject: [PATCH 12/66] Fix bug with mainmenu --- pyforms/gui/BaseWidget.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/BaseWidget.py index a60b88c..5f1fd62 100644 --- a/pyforms/gui/BaseWidget.py +++ b/pyforms/gui/BaseWidget.py @@ -461,9 +461,12 @@ def uid(self, value): def visible(self): return self.isVisible() - @visible.setter - def visible(self, value): - self.show() if value else self.hide() + @property + def mainmenu(self): + return self._mainmenu + @mainmenu.setter + def mainmenu(self, value): + self._mainmenu = value ########################################################################## ############ PRIVATE FUNCTIONS ########################################### From 212d83dd55a1bafcca0a62f312863208589ee169 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 28 Dec 2017 14:05:45 +0000 Subject: [PATCH 13/66] . --- pyforms/gui/Controls/ControlBase.py | 18 +++++++-- pyforms/gui/Controls/ControlWeb.py | 63 ++++++++++++++++++----------- 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/pyforms/gui/Controls/ControlBase.py b/pyforms/gui/Controls/ControlBase.py index b9f3015..dbe8510 100755 --- a/pyforms/gui/Controls/ControlBase.py +++ b/pyforms/gui/Controls/ControlBase.py @@ -15,14 +15,23 @@ class ControlBase(object): @undocumented: __repr__ """ - def __init__(self, label='', default=None, helptext=None): - self._help = helptext - self._value = default + def __init__(self, *args, **kwargs): self._form = None # Qt widget self._parent = None # Parent window - self._label = label # Label self._popup_menu = None + self._help = kwargs.get('helptext', None) + self._value = kwargs.get('default', None) + self._label = kwargs.get('label', args[0] if len(args)>0 else '') + """ + self._visible = kwargs.get('visible', True) + self._error = kwargs.get('error', False) + self._css = kwargs.get('css', None) + self._enabled = kwargs.get('enabled', True) + self._readonly = kwargs.get('readonly', False) + self._label_visible = kwargs.get('label_visible', True) + """ + self.init_form() @@ -37,6 +46,7 @@ def init_form(self): Load Control and initiate the events """ if self.help: self.form.setToolTip(self.help) + def load_form(self, data, path=None): diff --git a/pyforms/gui/Controls/ControlWeb.py b/pyforms/gui/Controls/ControlWeb.py index afe3247..678a54b 100644 --- a/pyforms/gui/Controls/ControlWeb.py +++ b/pyforms/gui/Controls/ControlWeb.py @@ -12,32 +12,49 @@ from pysettings import conf if conf.PYFORMS_USE_QT5: - from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView - from PyQt5.QtCore import QUrl + from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView + from PyQt5.QtCore import QUrl else: - from PyQt4.QtCore import QUrl - from PyQt4.QtWebKit import QWebView + from PyQt4.QtCore import QUrl + from PyQt4.QtWebKit import QWebView from pyforms.gui.Controls.ControlBase import ControlBase class ControlWeb(ControlBase, QWebView): - def __init__(self, label=""): - QWebView.__init__(self) - ControlBase.__init__(self, label) - - ############################################################################ - ############ Properties #################################################### - ############################################################################ - - @property - def value(self): return ControlBase.value.fget(self) - - @value.setter - def value(self, value): - ControlBase.value.fset(self, value) - QWebView.load(self, QUrl(value)) - - @property - def form(self): - return self + def __init__(self, *args, **kwargs): + QWebView.__init__(self) + if 'load_finnished_event' in kwargs: + self.load_finnished_event=kwargs['load_finnished_event'] + self.loadFinished.connect(self.__load_finnished_evt) + ControlBase.__init__(self, *args, **kwargs) + + + def init_form(self): + """ + Load Control and initiate the events + """ + ControlBase.init_form(self) + if self._value: QWebView.load(self, QUrl(self._value)) + if self.help: self.form.setToolTip(self.help) + ############################################################################ + ############ Properties #################################################### + ############################################################################ + + def __load_finnished_evt(self, ok): + self.load_finnished_event(ok) + + def load_finnished_event(self,ok): + pass + + @property + def value(self): return ControlBase.value.fget(self) + + @value.setter + def value(self, value): + ControlBase.value.fset(self, value) + QWebView.load(self, QUrl(value)) + + @property + def form(self): + return self From a90270bd295f185cc3ab685b7d3995dc9289809d Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 29 Dec 2017 19:37:20 +0000 Subject: [PATCH 14/66] . --- pyforms/gui/Controls/ControlNumber.py | 9 +++++---- pyforms/gui/Controls/ControlProgress.py | 11 +++++++---- pyforms/gui/Controls/ControlSlider.py | 16 ++++++++++------ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/pyforms/gui/Controls/ControlNumber.py b/pyforms/gui/Controls/ControlNumber.py index e3b5b1b..b6c78dd 100644 --- a/pyforms/gui/Controls/ControlNumber.py +++ b/pyforms/gui/Controls/ControlNumber.py @@ -12,10 +12,11 @@ class ControlNumber(ControlBase): - def __init__(self, label="", default=0, minimum=0, maximum=100): - self._min = minimum - self._max = maximum - ControlBase.__init__(self, label, default) + def __init__(self, *args, **kwargs): + self._min = kwargs.get('minimum', 0) + self._max = kwargs.get('maximum', 100) + if 'default' not in kwargs: kwargs['default'] = 0 + ControlBase.__init__(self, *args, **kwargs) def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "number.ui") diff --git a/pyforms/gui/Controls/ControlProgress.py b/pyforms/gui/Controls/ControlProgress.py index a3d2a9a..eb7ab67 100755 --- a/pyforms/gui/Controls/ControlProgress.py +++ b/pyforms/gui/Controls/ControlProgress.py @@ -17,12 +17,15 @@ class ControlProgress(ControlBase): - def __init__(self, label="%p%", default=0, min=0, max=100): + + def __init__(self, *args, **kwargs): self._updateSlider = True - self._min = min - self._max = max + self._min = kwargs.get('minimum', 0) + self._max = kwargs.get('maximum', 100) + if 'default' not in kwargs: kwargs['default'] = 0 + ControlBase.__init__(self, *args, **kwargs) - ControlBase.__init__(self, label, default) + def init_form(self): module_path = os.path.abspath(os.path.dirname(__file__)) diff --git a/pyforms/gui/Controls/ControlSlider.py b/pyforms/gui/Controls/ControlSlider.py index 43c8ae7..2c48b9f 100755 --- a/pyforms/gui/Controls/ControlSlider.py +++ b/pyforms/gui/Controls/ControlSlider.py @@ -15,15 +15,19 @@ class ControlSlider(ControlBase): - def __init__(self, label="", default=0, min=0, max=100): - self._updateSlider = True - self._min = min - self._max = max - ControlBase.__init__(self, label, default) - self._form.value.setText(str(default)) + def __init__(self, *args, **kwargs): + self._updateSlider = True + self._min = kwargs.get('minimum', 0) + self._max = kwargs.get('maximum', 100) + if 'default' not in kwargs: kwargs['default'] = 0 + ControlBase.__init__(self, *args, **kwargs) + + self._form.value.setText(str(kwargs['default'])) self._form.horizontalSlider.valueChanged.connect(self.valueChanged) + + def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "sliderInput.ui") self._form = uic.loadUi(control_path) From 92c99befbc98599d0e83ac141077b69730afa6ac Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Sat, 6 Jan 2018 14:51:29 +0000 Subject: [PATCH 15/66] . --- pyforms/gui/Controls/ControlButton.py | 1 + pyforms/gui/Controls/ControlEmptyWidget.py | 6 +++--- .../Controls/ControlEventTimeline/TimelineChart.py | 14 +++++++------- .../ControlEventTimeline/graphs_properties.py | 8 ++++---- pyforms/gui/dialogs/generic_csv_parser.py | 6 +++--- .../ComputerVisionAlgorithmExample/Example.py | 4 ++-- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/pyforms/gui/Controls/ControlButton.py b/pyforms/gui/Controls/ControlButton.py index 7769cd9..51fd71e 100755 --- a/pyforms/gui/Controls/ControlButton.py +++ b/pyforms/gui/Controls/ControlButton.py @@ -16,6 +16,7 @@ class ControlButton(ControlBase): def __init__(self, label='', default=None, checkable=False, helptext=None): self._checkable = checkable super(ControlButton, self).__init__(label=label, default=default, helptext=helptext) + if default: self.value = default def init_form(self): self._form = QPushButton() diff --git a/pyforms/gui/Controls/ControlEmptyWidget.py b/pyforms/gui/Controls/ControlEmptyWidget.py index c7e3821..bb100b1 100755 --- a/pyforms/gui/Controls/ControlEmptyWidget.py +++ b/pyforms/gui/Controls/ControlEmptyWidget.py @@ -10,7 +10,7 @@ class ControlEmptyWidget(ControlBase, QWidget): - def __init__(self, label='', default=None): + def __init__(self, *args, **kwargs): QWidget.__init__(self) layout = QVBoxLayout() @@ -22,8 +22,8 @@ def __init__(self, label='', default=None): self.form.setLayout(layout) - ControlBase.__init__(self, label) - self.value = default + ControlBase.__init__(self, *args, **kwargs) + self.value = kwargs.get('default', None) def init_form(self): pass diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineChart.py b/pyforms/gui/Controls/ControlEventTimeline/TimelineChart.py index 319cb19..5d77d7d 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelineChart.py +++ b/pyforms/gui/Controls/ControlEventTimeline/TimelineChart.py @@ -124,21 +124,21 @@ def draw(self, painter, left, right, top, bottom): painter.setPen(self._color) painter.setOpacity(0.7) - fov_height = (bottom - top) * self._zoom - start = self._widget.x2frame(left) - end = self._widget.x2frame(right) - end = len(self) if end > len(self) else end - diff_max_min = (self._graph_max - self._graph_min) + fov_height = (bottom - top) * self.zoom #calculate the height visible + start = self._widget.x2frame(left) #calculate the start frame to draw + end = self._widget.x2frame(right) #calculate the end frame to draw + end = len(self) if end > len(self) else end #check if the end frame his higher than the available data + diff_max_min = (self._graph_max - self._graph_min) #calculate the difference bettween the lower and higher value top = (-self._graph_min if self._graph_min > 0 else abs(self._graph_min)) * self._zoom if diff_max_min <= 0: diff_max_min = 1 - last_coordenate = None + last_coordenate = None last_real_x_coord = None for i, y in enumerate(self._data[start:end]): - if y: + if y is not None: x = i + start if y == None: continue y = self._top + ((top + y) * fov_height) // diff_max_min diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py b/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py index 0fe89e8..45c395b 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py +++ b/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py @@ -24,10 +24,10 @@ def __init__(self, timelineWidget=None, parent_win=None): # Definition of the forms fields self._graphs_list = ControlList('Graphs list') self._name = ControlText('Name') - self._min_value = ControlNumber('Min', 0, -sys.float_info.max, sys.float_info.max) - self._max_value = ControlNumber('Max', 0, -sys.float_info.max, sys.float_info.max) - self._values_zoom = ControlSlider('Amplitude', 100, 60, 400) - self._values_top = ControlNumber('Bottom', 0, -1000, 1000) + self._min_value = ControlNumber('Min', default=0, minimum=-sys.float_info.min, maximum=sys.float_info.max) + self._max_value = ControlNumber('Max', default=0, minimum=-sys.float_info.min, maximum=sys.float_info.max) + self._values_zoom = ControlSlider('Amplitude', default=100, minimum=60, maximum=400) + self._values_top = ControlNumber('Bottom', default=0, minimum=-1000, maximum=1000) self._remove_graph_btn = ControlButton('Remove graph') self._value = ControlLabel() diff --git a/pyforms/gui/dialogs/generic_csv_parser.py b/pyforms/gui/dialogs/generic_csv_parser.py index 418cc19..d19d2b2 100644 --- a/pyforms/gui/dialogs/generic_csv_parser.py +++ b/pyforms/gui/dialogs/generic_csv_parser.py @@ -18,11 +18,11 @@ def __init__(self, columns, parent=None): # Definition of the forms fields self._filename = ControlFile('CSV File') - self._separator = ControlText('Separator', 'auto') - self._startingrow = ControlNumber('Starting row', 0) + self._separator = ControlText('Separator', default='auto') + self._startingrow = ControlNumber('Starting row', default=0) for index, column in enumerate(columns): - setattr(self, '_col_{0}'.format(index), ControlNumber(column, index, -1, 1000)) + setattr(self, '_col_{0}'.format(index), ControlNumber(column, default=index, minimum=-1, maximum=1000)) self._filePreview = ControlList('Preview') self._loadButton = ControlButton('Load') diff --git a/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py b/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py index 2e5ae24..af913da 100644 --- a/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py +++ b/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py @@ -20,8 +20,8 @@ def __init__(self): #Definition of the forms fields self._videofile = ControlFile('Video') self._outputfile = ControlText('Results output file') - self._threshold = ControlSlider('Threshold', 114, 0,255) - self._blobsize = ControlSlider('Minimum blob size', 100, 100,2000) + self._threshold = ControlSlider('Threshold', default=114, 0,255) + self._blobsize = ControlSlider('Minimum blob size', default=100, 100,2000) self._player = ControlPlayer('Player') self._runbutton = ControlButton('Run') From 85c05efbfc72f5b1fd9a488aadbf26b2e47e2c73 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Sun, 7 Jan 2018 22:14:37 +0000 Subject: [PATCH 16/66] . --- pyforms/Controls.py | 8 + pyforms/dialogs.py | 6 +- pyforms/gui/Controls/ControlCheckBoxList.py | 237 ++++++++++-------- pyforms/gui/Controls/ControlList.py | 4 +- pyforms/gui/standaloneManager.py | 27 +- pyforms/terminal/BaseWidget.py | 2 +- .../Controls/ControlBoundingSlider.py | 5 + .../terminal/Controls/ControlCheckBoxList.py | 5 + .../terminal/Controls/ControlEmptyWidget.py | 5 + pyforms/terminal/Controls/ControlLabel.py | 5 + pyforms/terminal/Controls/ControlList.py | 202 +++++++++++++++ pyforms/terminal/Controls/ControlTextArea.py | 5 + pyforms/terminal/Controls/ControlToolBox.py | 5 + pyforms/terminal/Controls/ControlTree.py | 5 + 14 files changed, 400 insertions(+), 121 deletions(-) create mode 100755 pyforms/terminal/Controls/ControlBoundingSlider.py create mode 100755 pyforms/terminal/Controls/ControlCheckBoxList.py create mode 100755 pyforms/terminal/Controls/ControlEmptyWidget.py create mode 100755 pyforms/terminal/Controls/ControlLabel.py create mode 100755 pyforms/terminal/Controls/ControlList.py create mode 100755 pyforms/terminal/Controls/ControlTextArea.py create mode 100755 pyforms/terminal/Controls/ControlToolBox.py create mode 100755 pyforms/terminal/Controls/ControlTree.py diff --git a/pyforms/Controls.py b/pyforms/Controls.py index 9c33ed1..88d3043 100644 --- a/pyforms/Controls.py +++ b/pyforms/Controls.py @@ -81,9 +81,17 @@ from pyforms.terminal.Controls.ControlDir import ControlDir from pyforms.terminal.Controls.ControlImage import ControlImage from pyforms.terminal.Controls.ControlSlider import ControlSlider + from pyforms.terminal.Controls.ControlList import ControlList from pyforms.terminal.Controls.ControlPlayer import ControlPlayer from pyforms.terminal.Controls.ControlNumber import ControlNumber from pyforms.terminal.Controls.ControlProgress import ControlProgress + from pyforms.terminal.Controls.ControlToolBox import ControlToolBox + from pyforms.terminal.Controls.ControlCheckBoxList import ControlCheckBoxList + from pyforms.terminal.Controls.ControlEmptyWidget import ControlEmptyWidget + from pyforms.terminal.Controls.ControlTree import ControlTree + from pyforms.terminal.Controls.ControlBoundingSlider import ControlBoundingSlider + from pyforms.terminal.Controls.ControlLabel import ControlLabel + from pyforms.terminal.Controls.ControlTextArea import ControlTextArea elif conf.PYFORMS_MODE in ['WEB']: diff --git a/pyforms/dialogs.py b/pyforms/dialogs.py index 84239d7..3a362b6 100644 --- a/pyforms/dialogs.py +++ b/pyforms/dialogs.py @@ -1,4 +1,8 @@ from pyforms import conf if conf.PYFORMS_MODE in ['GUI','GUI-OPENCSP']: - from pyforms.gui.dialogs.csv_parser import CsvParserDialog \ No newline at end of file + from pyforms.gui.dialogs.csv_parser import CsvParserDialog + + +elif conf.PYFORMS_MODE in ['TERMINAL']: + class CsvParserDialog(object): pass \ No newline at end of file diff --git a/pyforms/gui/Controls/ControlCheckBoxList.py b/pyforms/gui/Controls/ControlCheckBoxList.py index 4011ecd..dd41c78 100755 --- a/pyforms/gui/Controls/ControlCheckBoxList.py +++ b/pyforms/gui/Controls/ControlCheckBoxList.py @@ -5,114 +5,141 @@ import pyforms.utils.tools as tools -from AnyQt import uic, QtCore +from AnyQt import uic, QtCore from AnyQt.QtWidgets import QListWidgetItem from pyforms.gui.Controls.ControlBase import ControlBase class ControlCheckBoxList(ControlBase): - def init_form(self): - control_path = tools.getFileInSameDirectory(__file__, "tree.ui") - self._form = uic.loadUi(control_path) - - self._form.label.setText(self._label) - - self._form.listWidget.itemChanged.connect(self.item_changed) - - self._form.listWidget.itemSelectionChanged.connect(self.__itemSelectionChanged) - - if self.help: self.form.setToolTip(self.help) - - def item_changed(self, item): - self.changed_event() - - def __add__(self, val): - if isinstance(val, (tuple, list)): - item = QListWidgetItem(str(val[0])) - item.value = val[0] - if val[1]: - item.setCheckState(QtCore.Qt.Checked) - else: - item.setCheckState(QtCore.Qt.Unchecked) - else: - item = QListWidgetItem(str(val)) - item.value = val - - self._form.listWidget.addItem(item) - return self - - def __sub__(self, other): - if isinstance(other, int): - if other < 0: - indexToRemove = self._form.listWidget.currentRow() - else: - indexToRemove = other - self._form.listWidget.takeItem(indexToRemove) - else: - for row in range(self.count): - item = self._form.listWidget.item(row) - if item != None and hasattr(item, 'value') and item.value == other: - self._form.listWidget.takeItem(row) - return self - - def clear(self): - self._form.listWidget.clear() - - def refresh(self): - for row in range(self.count): - item = self._form.listWidget.item(row) - if hasattr(item, 'value'): item.setText(str(item.value)) - - ############################################################################ - ############ Events ######################################################## - ############################################################################ - - def __itemSelectionChanged(self): - self.selection_changed_event() - - def selection_changed_event(self): - pass - - ############################################################################ - ############ Properties #################################################### - ############################################################################ - - @property - def count(self): - return self._form.listWidget.count() - - @property - def checked_indexes(self): - results = [] - for row in range(self.count): - item = self._form.listWidget.item(row) - if item != None and item.checkState() == QtCore.Qt.Checked: results.append(row) - return results - - @property - def value(self): - results = [] - for row in range(self.count): - item = self._form.listWidget.item(row) - if item != None and item.checkState() == QtCore.Qt.Checked: - results.append(item.value if hasattr(item, 'value') else str(item.text())) - return results - - @value.setter - def value(self, value): - self.clear() - for row in value: self += row - - @property - def selected_row_index(self): - return self.form.listWidget.currentRow() - - @property - def items(self): - results = [] - for row in range(self.count): - item = self._form.listWidget.item(row) - results.append( - [item.value if hasattr(item, 'value') else str(item.text()), item.checkState() == QtCore.Qt.Checked]) - return results + + def init_form(self): + control_path = tools.getFileInSameDirectory(__file__, "tree.ui") + self._form = uic.loadUi(control_path) + + self._form.label.setText(self._label) + + self._form.listWidget.itemChanged.connect(self.item_changed) + + self._form.listWidget.itemSelectionChanged.connect(self.__itemSelectionChanged) + + if self.help: self.form.setToolTip(self.help) + + + + + def save_form(self, data={}, path=None): + results = [] + + for row in range(self.count): + item = self._form.listWidget.item(row) + if item != None and item.checkState() == QtCore.Qt.Checked: + results.append(item.text()) + data['selected'] = results + + return data + + def load_form(self, data, path=None): + results = data['selected'] + + for row in range(self.count): + item = self._form.listWidget.item(row) + if item != None and item.text() in results: + item.setCheckState(QtCore.Qt.Checked) + else: + item.setCheckState(QtCore.Qt.Unchecked) + + + + def item_changed(self, item): + self.changed_event() + + def __add__(self, val): + if isinstance(val, (tuple, list)): + item = QListWidgetItem(str(val[0])) + item.value = val[0] + if val[1]: + item.setCheckState(QtCore.Qt.Checked) + else: + item.setCheckState(QtCore.Qt.Unchecked) + else: + item = QListWidgetItem(str(val)) + item.value = val + + self._form.listWidget.addItem(item) + return self + + def __sub__(self, other): + if isinstance(other, int): + if other < 0: + indexToRemove = self._form.listWidget.currentRow() + else: + indexToRemove = other + self._form.listWidget.takeItem(indexToRemove) + else: + for row in range(self.count): + item = self._form.listWidget.item(row) + if item != None and hasattr(item, 'value') and item.value == other: + self._form.listWidget.takeItem(row) + return self + + def clear(self): + self._form.listWidget.clear() + + def refresh(self): + for row in range(self.count): + item = self._form.listWidget.item(row) + if hasattr(item, 'value'): item.setText(str(item.value)) + + ############################################################################ + ############ Events ######################################################## + ############################################################################ + + def __itemSelectionChanged(self): + self.selection_changed_event() + + def selection_changed_event(self): + pass + + ############################################################################ + ############ Properties #################################################### + ############################################################################ + + @property + def count(self): + return self._form.listWidget.count() + + @property + def checked_indexes(self): + results = [] + for row in range(self.count): + item = self._form.listWidget.item(row) + if item != None and item.checkState() == QtCore.Qt.Checked: results.append(row) + return results + + @property + def value(self): + results = [] + for row in range(self.count): + item = self._form.listWidget.item(row) + if item != None and item.checkState() == QtCore.Qt.Checked: + results.append(item.value if hasattr(item, 'value') else str(item.text())) + return results + + @value.setter + def value(self, value): + self.clear() + for row in value: self += row + + @property + def selected_row_index(self): + return self.form.listWidget.currentRow() + + @property + def items(self): + results = [] + for row in range(self.count): + item = self._form.listWidget.item(row) + results.append( + [item.value if hasattr(item, 'value') else str(item.text()), item.checkState() == QtCore.Qt.Checked]) + return results diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/Controls/ControlList.py index ab28db4..069ff17 100755 --- a/pyforms/gui/Controls/ControlList.py +++ b/pyforms/gui/Controls/ControlList.py @@ -101,7 +101,7 @@ def save_form(self, data, path=None): for column in range(self.columns_count): v = self.get_value(column, row) if isinstance(v, BaseWidget): - columns.append(v.save({})) + columns.append(v.save_form({}, path)) else: columns.append(str(v)) rows.append(columns) @@ -115,7 +115,7 @@ def load_form(self, data, path=None): for column in range(len(rows[row])): v = self.get_value(column, row) if isinstance(v, BaseWidget): - v.load(rows[row][column]) + v.load_form(rows[row][column], path) else: self.set_value(column, row, rows[row][column]) elif 'value' in data.keys(): diff --git a/pyforms/gui/standaloneManager.py b/pyforms/gui/standaloneManager.py index 4e6ba0a..15e6bc2 100644 --- a/pyforms/gui/standaloneManager.py +++ b/pyforms/gui/standaloneManager.py @@ -26,34 +26,34 @@ from PyQt4.QtGui import QApplication from PyQt4 import QtCore +from pyforms.gui.BaseWidget import BaseWidget from pyforms.gui.Controls.ControlDockWidget import ControlDockWidget logger = logging.getLogger(__name__) class StandAloneContainer(QMainWindow): - def __init__(self, ClassObject): + def __init__(self, app_instance): super(QMainWindow, self).__init__() - w = ClassObject() - w.app_main_window = self - self._widget = w + app_instance.app_main_window = self + self._widget = app_instance - if len(w.mainmenu) > 0: - w._mainmenu = self.__initMainMenu(w.mainmenu) + if len(app_instance.mainmenu) > 0: + app_instance._mainmenu = self.__initMainMenu(app_instance.mainmenu) - w.init_form() + app_instance.init_form() if conf.PYFORMS_USE_QT5: self.layout().setContentsMargins(conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN) else: self.layout().setMargin(conf.PYFORMS_MAINWINDOW_MARGIN) - self.setCentralWidget(w) - self.setWindowTitle(w.title) + self.setCentralWidget(app_instance) + self.setWindowTitle(app_instance.title) docks = {} - for name, item in w.controls.items(): + for name, item in app_instance.controls.items(): if isinstance(item, ControlDockWidget): if item.side not in docks: docks[item.side] = [] @@ -176,14 +176,17 @@ def execute_test_file(myapp): exec(code, global_vars, local_vars) -def start_app(ClassObject, geometry=None): +def start_app(AppClass, geometry=None, **kwargs): from pysettings import conf app = QApplication(sys.argv) conf += 'pyforms.gui.settings' - mainwindow = StandAloneContainer(ClassObject) + app_def = AppClass(**kwargs) + + + mainwindow = StandAloneContainer(app_def) myapp = mainwindow.centralWidget() diff --git a/pyforms/terminal/BaseWidget.py b/pyforms/terminal/BaseWidget.py index 97fc159..3e57fa9 100755 --- a/pyforms/terminal/BaseWidget.py +++ b/pyforms/terminal/BaseWidget.py @@ -10,7 +10,7 @@ class BaseWidget(object): - def __init__(self, title): + def __init__(self, title, parent_win=None, win_flag=None): self._parser = argparse.ArgumentParser() with open('pid.txt', 'w') as f: f.write( str(os.getpid()) ) diff --git a/pyforms/terminal/Controls/ControlBoundingSlider.py b/pyforms/terminal/Controls/ControlBoundingSlider.py new file mode 100755 index 0000000..1eb7a97 --- /dev/null +++ b/pyforms/terminal/Controls/ControlBoundingSlider.py @@ -0,0 +1,5 @@ +from pyforms.terminal.Controls.ControlBase import ControlBase + +class ControlBoundingSlider(ControlBase):pass + + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlCheckBoxList.py b/pyforms/terminal/Controls/ControlCheckBoxList.py new file mode 100755 index 0000000..6beb37b --- /dev/null +++ b/pyforms/terminal/Controls/ControlCheckBoxList.py @@ -0,0 +1,5 @@ +from pyforms.terminal.Controls.ControlBase import ControlBase + +class ControlCheckBoxList(ControlBase):pass + + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlEmptyWidget.py b/pyforms/terminal/Controls/ControlEmptyWidget.py new file mode 100755 index 0000000..6709038 --- /dev/null +++ b/pyforms/terminal/Controls/ControlEmptyWidget.py @@ -0,0 +1,5 @@ +from pyforms.terminal.Controls.ControlBase import ControlBase + +class ControlEmptyWidget(ControlBase):pass + + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlLabel.py b/pyforms/terminal/Controls/ControlLabel.py new file mode 100755 index 0000000..36d42f0 --- /dev/null +++ b/pyforms/terminal/Controls/ControlLabel.py @@ -0,0 +1,5 @@ +from pyforms.terminal.Controls.ControlBase import ControlBase + +class ControlLabel(ControlBase):pass + + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlList.py b/pyforms/terminal/Controls/ControlList.py new file mode 100755 index 0000000..977a297 --- /dev/null +++ b/pyforms/terminal/Controls/ControlList.py @@ -0,0 +1,202 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" pyforms.gui.Controls.ControlList + +""" +import logging +from pyforms.terminal.Controls.ControlBase import ControlBase + +logger = logging.getLogger(__name__) + + +class ControlList(ControlBase): + """ This class represents a wrapper to the table widget + It allows to implement a list view + """ + + def clear(self, headers=False): + pass + + def save_form(self, data, path=None): + if self.value: + rows = [] + for row in range(self.rows_count): + columns = [] + for column in range(self.columns_count): + v = self.get_value(column, row) + if isinstance(v, BaseWidget): + columns.append(v.save({})) + else: + columns.append(str(v)) + rows.append(columns) + data['value'] = rows + return data + + def load_form(self, data, path=None): + if self.value: + rows = data['value'] + for row in range(len(rows)): + for column in range(len(rows[row])): + v = self.get_value(column, row) + if isinstance(v, BaseWidget): + v.load(rows[row][column]) + else: + self.set_value(column, row, rows[row][column]) + elif 'value' in data.keys(): + self.value = data['value'] + + def __add__(self, other): + """ + row_index = self.tableWidget.rowCount() + + self.tableWidget.insertRow(row_index) + + #increase the number of columns if necessary #### + if self.tableWidget.currentColumn() < len(other): + self.tableWidget.setColumnCount(len(other)) + ################################################# + + for column, e in enumerate(other): self.set_value(column, row_index, e) + + self.tableWidget.resizeColumnsToContents() + + # auto scroll the list to the new inserted item ################## + if self.autoscroll: + self.tableWidget.scrollToItem( self.get_cell(0,row_index) ) + ################################################################## + return self + """ + + def __sub__(self, other): + """ + if isinstance(other, int): + if other < 0: + indexToRemove = self.tableWidget.currentRow() + else: + indexToRemove = other + + self.tableWidget.removeRow(indexToRemove) + return self + """ + + def set_value(self, column, row, value): + pass + + def get_value(self, column, row): + pass + + def resize_rows_contents(self): + pass + + def get_currentrow_value(self): + return None + + def get_cell(self, column, row): + return None + + def set_sorting_enabled(self, value): + pass + + ########################################################################## + ############ EVENTS ###################################################### + ########################################################################## + + def data_changed_event(self, row, col, item): + pass + + def item_selection_changed_event(self): + pass + + def current_cell_changed_event(self, next_row, next_col, previous_row, previous_col): + pass + + def current_item_changed_event(self, current, previous): + pass + + def cell_double_clicked_event(self, row, column): + pass + + ########################################################################## + ############ PROPERTIES ################################################## + ########################################################################## + + + @property + def horizontal_headers(self): + return self._horizontalHeaders + + @horizontal_headers.setter + def horizontal_headers(self, horizontal_headers): + """Set horizontal headers in the table list.""" + + self._horizontalHeaders = horizontal_headers + + + @property + def word_wrap(self): + return True + + @word_wrap.setter + def word_wrap(self, value): + pass + + @property + def readonly(self): + return False + + @readonly.setter + def readonly(self, value): + pass + + @property + def select_entire_row(self): + pass + + @select_entire_row.setter + def select_entire_row(self, value): + pass + + @property + def rows_count(self): + return 0 + + @property + def columns_count(self): + return 0 + + def __len__(self): + return 0 + + @property + def value(self): + return None + + @value.setter + def value(self, value): + pass + + # TODO: implement += on self.value? I want to add a list of tuples to + # self.value + + @property + def selected_rows_indexes(self): + return None + + @property + def selected_row_index(self): + pass + + @property + def icon_size(self): + return 0 + + @icon_size.setter + def icon_size(self, value): + pass + + @property + def autoscroll(self): return False + @autoscroll.setter + def autoscroll(self, value): pass + diff --git a/pyforms/terminal/Controls/ControlTextArea.py b/pyforms/terminal/Controls/ControlTextArea.py new file mode 100755 index 0000000..0a560e5 --- /dev/null +++ b/pyforms/terminal/Controls/ControlTextArea.py @@ -0,0 +1,5 @@ +from pyforms.terminal.Controls.ControlBase import ControlBase + +class ControlTextArea(ControlBase):pass + + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlToolBox.py b/pyforms/terminal/Controls/ControlToolBox.py new file mode 100755 index 0000000..1171f71 --- /dev/null +++ b/pyforms/terminal/Controls/ControlToolBox.py @@ -0,0 +1,5 @@ +from pyforms.terminal.Controls.ControlBase import ControlBase + +class ControlToolBox(ControlBase):pass + + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlTree.py b/pyforms/terminal/Controls/ControlTree.py new file mode 100755 index 0000000..0f298eb --- /dev/null +++ b/pyforms/terminal/Controls/ControlTree.py @@ -0,0 +1,5 @@ +from pyforms.terminal.Controls.ControlBase import ControlBase + +class ControlTree(ControlBase):pass + + \ No newline at end of file From 664eeda1821d4ce58964cdca60b608b11952d611 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Sun, 7 Jan 2018 23:02:18 +0000 Subject: [PATCH 17/66] . --- pyforms/terminal/Controls/ControlBase.py | 6 +- .../terminal/Controls/ControlCheckBoxList.py | 16 +- pyforms/terminal/Controls/ControlList.py | 343 +++++++++--------- pyforms/terminal/Controls/ControlPlayer.py | 20 +- pyforms/terminal/appmanager.py | 4 +- 5 files changed, 203 insertions(+), 186 deletions(-) diff --git a/pyforms/terminal/Controls/ControlBase.py b/pyforms/terminal/Controls/ControlBase.py index bb53838..4142991 100755 --- a/pyforms/terminal/Controls/ControlBase.py +++ b/pyforms/terminal/Controls/ControlBase.py @@ -7,11 +7,11 @@ class ControlBase(object): _label = None _controlHTML = "" - def __init__(self, label = "", defaultValue = "", helptext=None): + def __init__(self, *args, **kwargs): self._id = uuid.uuid4() - self._value = defaultValue + self._value = kwargs.get('default', None) self._parent = 1 - self._label = label + self._label = kwargs.get('label', args[0] if len(args)>0 else '') def init_form(self): pass diff --git a/pyforms/terminal/Controls/ControlCheckBoxList.py b/pyforms/terminal/Controls/ControlCheckBoxList.py index 6beb37b..8033cff 100755 --- a/pyforms/terminal/Controls/ControlCheckBoxList.py +++ b/pyforms/terminal/Controls/ControlCheckBoxList.py @@ -1,5 +1,17 @@ from pyforms.terminal.Controls.ControlBase import ControlBase -class ControlCheckBoxList(ControlBase):pass +class ControlCheckBoxList(ControlBase): + + def __init__(self, *args, **kwargs): + if 'default' not in kwargs: kwargs['default'] = [] + super(ControlCheckBoxList, self).__init__(*args, **kwargs) + + - \ No newline at end of file + def __add__(self, val): + self._value.append(val) + return self + + def __sub__(self, other): + self._value.remove(other) + return self \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlList.py b/pyforms/terminal/Controls/ControlList.py index 977a297..991fd60 100755 --- a/pyforms/terminal/Controls/ControlList.py +++ b/pyforms/terminal/Controls/ControlList.py @@ -11,192 +11,193 @@ class ControlList(ControlBase): - """ This class represents a wrapper to the table widget - It allows to implement a list view - """ - - def clear(self, headers=False): - pass - - def save_form(self, data, path=None): - if self.value: - rows = [] - for row in range(self.rows_count): - columns = [] - for column in range(self.columns_count): - v = self.get_value(column, row) - if isinstance(v, BaseWidget): - columns.append(v.save({})) - else: - columns.append(str(v)) - rows.append(columns) - data['value'] = rows - return data - - def load_form(self, data, path=None): - if self.value: - rows = data['value'] - for row in range(len(rows)): - for column in range(len(rows[row])): - v = self.get_value(column, row) - if isinstance(v, BaseWidget): - v.load(rows[row][column]) - else: - self.set_value(column, row, rows[row][column]) - elif 'value' in data.keys(): - self.value = data['value'] - - def __add__(self, other): - """ - row_index = self.tableWidget.rowCount() - - self.tableWidget.insertRow(row_index) - - #increase the number of columns if necessary #### - if self.tableWidget.currentColumn() < len(other): - self.tableWidget.setColumnCount(len(other)) - ################################################# - - for column, e in enumerate(other): self.set_value(column, row_index, e) - - self.tableWidget.resizeColumnsToContents() - - # auto scroll the list to the new inserted item ################## - if self.autoscroll: - self.tableWidget.scrollToItem( self.get_cell(0,row_index) ) - ################################################################## - return self - """ - - def __sub__(self, other): - """ - if isinstance(other, int): - if other < 0: - indexToRemove = self.tableWidget.currentRow() - else: - indexToRemove = other - - self.tableWidget.removeRow(indexToRemove) - return self - """ - - def set_value(self, column, row, value): - pass - - def get_value(self, column, row): - pass - - def resize_rows_contents(self): - pass - - def get_currentrow_value(self): - return None - - def get_cell(self, column, row): - return None - - def set_sorting_enabled(self, value): - pass - - ########################################################################## - ############ EVENTS ###################################################### - ########################################################################## - - def data_changed_event(self, row, col, item): - pass - - def item_selection_changed_event(self): - pass - - def current_cell_changed_event(self, next_row, next_col, previous_row, previous_col): - pass - - def current_item_changed_event(self, current, previous): - pass - - def cell_double_clicked_event(self, row, column): - pass - - ########################################################################## - ############ PROPERTIES ################################################## - ########################################################################## - - - @property - def horizontal_headers(self): - return self._horizontalHeaders + """ This class represents a wrapper to the table widget + It allows to implement a list view + """ + def __init__(self, *args, **kwargs): + if 'default' not in kwargs: kwargs['default'] = [] + super(ControlList, self).__init__(*args, **kwargs) + + + def clear(self, headers=False): + pass + + def save_form(self, data, path=None): + if self.value: + rows = [] + for row in range(self.rows_count): + columns = [] + for column in range(self.columns_count): + v = self.get_value(column, row) + if isinstance(v, BaseWidget): + columns.append(v.save({})) + else: + columns.append(str(v)) + rows.append(columns) + data['value'] = rows + return data + + def load_form(self, data, path=None): + if self.value: + rows = data['value'] + for row in range(len(rows)): + for column in range(len(rows[row])): + v = self.get_value(column, row) + if isinstance(v, BaseWidget): + v.load(rows[row][column]) + else: + self.set_value(column, row, rows[row][column]) + elif 'value' in data.keys(): + self.value = data['value'] + + def __add__(self, other): + self._value.append(val) + return self + """ + row_index = self.tableWidget.rowCount() + + self.tableWidget.insertRow(row_index) + + #increase the number of columns if necessary #### + if self.tableWidget.currentColumn() < len(other): + self.tableWidget.setColumnCount(len(other)) + ################################################# + + for column, e in enumerate(other): self.set_value(column, row_index, e) + + self.tableWidget.resizeColumnsToContents() + + # auto scroll the list to the new inserted item ################## + if self.autoscroll: + self.tableWidget.scrollToItem( self.get_cell(0,row_index) ) + ################################################################## + return self + """ + + def __sub__(self, other): + self._value.remove(other) + return self + """ + if isinstance(other, int): + if other < 0: + indexToRemove = self.tableWidget.currentRow() + else: + indexToRemove = other + + self.tableWidget.removeRow(indexToRemove) + return self + """ + + def set_value(self, column, row, value): + pass + + def get_value(self, column, row): + pass + + def resize_rows_contents(self): + pass + + def get_currentrow_value(self): + return None + + def get_cell(self, column, row): + return None + + def set_sorting_enabled(self, value): + pass + + ########################################################################## + ############ EVENTS ###################################################### + ########################################################################## + + def data_changed_event(self, row, col, item): + pass + + def item_selection_changed_event(self): + pass + + def current_cell_changed_event(self, next_row, next_col, previous_row, previous_col): + pass + + def current_item_changed_event(self, current, previous): + pass + + def cell_double_clicked_event(self, row, column): + pass + + ########################################################################## + ############ PROPERTIES ################################################## + ########################################################################## + + + @property + def horizontal_headers(self): + return self._horizontalHeaders - @horizontal_headers.setter - def horizontal_headers(self, horizontal_headers): - """Set horizontal headers in the table list.""" + @horizontal_headers.setter + def horizontal_headers(self, horizontal_headers): + """Set horizontal headers in the table list.""" - self._horizontalHeaders = horizontal_headers + self._horizontalHeaders = horizontal_headers - - @property - def word_wrap(self): - return True + + @property + def word_wrap(self): + return True - @word_wrap.setter - def word_wrap(self, value): - pass + @word_wrap.setter + def word_wrap(self, value): + pass - @property - def readonly(self): - return False + @property + def readonly(self): + return False - @readonly.setter - def readonly(self, value): - pass + @readonly.setter + def readonly(self, value): + pass - @property - def select_entire_row(self): - pass + @property + def select_entire_row(self): + pass - @select_entire_row.setter - def select_entire_row(self, value): - pass + @select_entire_row.setter + def select_entire_row(self, value): + pass - @property - def rows_count(self): - return 0 + @property + def rows_count(self): + return 0 - @property - def columns_count(self): - return 0 + @property + def columns_count(self): + return 0 - def __len__(self): - return 0 + def __len__(self): + return 0 - @property - def value(self): - return None + + # TODO: implement += on self.value? I want to add a list of tuples to + # self.value - @value.setter - def value(self, value): - pass + @property + def selected_rows_indexes(self): + return None - # TODO: implement += on self.value? I want to add a list of tuples to - # self.value + @property + def selected_row_index(self): + pass - @property - def selected_rows_indexes(self): - return None + @property + def icon_size(self): + return 0 - @property - def selected_row_index(self): - pass + @icon_size.setter + def icon_size(self, value): + pass - @property - def icon_size(self): - return 0 - - @icon_size.setter - def icon_size(self, value): - pass - - @property - def autoscroll(self): return False - @autoscroll.setter - def autoscroll(self, value): pass + @property + def autoscroll(self): return False + @autoscroll.setter + def autoscroll(self, value): pass diff --git a/pyforms/terminal/Controls/ControlPlayer.py b/pyforms/terminal/Controls/ControlPlayer.py index b47a294..95f3c18 100755 --- a/pyforms/terminal/Controls/ControlPlayer.py +++ b/pyforms/terminal/Controls/ControlPlayer.py @@ -87,14 +87,18 @@ def value(self): @value.setter def value(self, value): - if isinstance( value, (str, unicode) ): - ControlBase.value.fset(self, cv2.VideoCapture( value ) ) - self._filename = value - if isinstance( value, dict ): - ControlBase.value.fset(self, cv2.VideoCapture( value['filename'] ) ) - if 'position' in value.keys(): self.video_index = int(value['position']) - self._filename = value['filename'] - self._max = int(self._value.get(7)) + if value: + if isinstance( value, str ): + ControlBase.value.fset(self, cv2.VideoCapture( value ) ) + self._filename = value + if isinstance( value, dict ): + ControlBase.value.fset(self, cv2.VideoCapture( value['filename'] ) ) + if 'position' in value.keys(): self.video_index = int(value['position']) + self._filename = value['filename'] + self._max = int(self._value.get(7)) + else: + self._filename = None + self._value = None diff --git a/pyforms/terminal/appmanager.py b/pyforms/terminal/appmanager.py index 153b00d..59da37e 100755 --- a/pyforms/terminal/appmanager.py +++ b/pyforms/terminal/appmanager.py @@ -1,5 +1,5 @@ from pyforms import BaseWidget -def start_app(ClassObject): - app = ClassObject() +def start_app(AppClass, **kwargs): + app = AppClass(**kwargs) app.init_form() From 74ff7044497694843fabbd6a5a433724a68a7789 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 12 Jan 2018 23:28:50 +0000 Subject: [PATCH 18/66] . --- pyforms/gui/BaseWidget.py | 8 +- pyforms/gui/Controls/ControlBase.py | 11 +- pyforms/gui/Controls/ControlBoundingSlider.py | 779 +++++++++--------- pyforms/gui/Controls/ControlButton.py | 8 +- pyforms/gui/Controls/ControlCheckBox.py | 2 +- pyforms/gui/Controls/ControlCheckBoxList.py | 1 + .../ControlEventTimeline/TimelineDelta.py | 14 +- .../graphs_eventsgenerator.py | 2 +- .../ControlEventTimeline/graphs_properties.py | 21 +- pyforms/gui/Controls/ControlList.py | 13 +- pyforms/gui/Controls/ControlNumber.py | 5 +- pyforms/gui/Controls/ControlSlider.py | 2 +- pyforms/gui/Controls/ControlTextArea.py | 5 +- pyforms/gui/standaloneManager.py | 9 +- pyforms/settings.py | 8 +- pyforms/terminal/BaseWidget.py | 387 +++++---- pyforms/terminal/Controls/ControlBase.py | 40 +- pyforms/terminal/Controls/ControlButton.py | 7 + .../terminal/Controls/ControlCheckBoxList.py | 42 +- pyforms/terminal/Controls/ControlCombo.py | 19 +- .../terminal/Controls/ControlEmptyWidget.py | 7 +- pyforms/terminal/Controls/ControlList.py | 27 +- pyforms/terminal/Controls/ControlPlayer.py | 24 +- pyforms/terminal/Controls/ControlProgress.py | 2 +- pyforms/terminal/Controls/ControlSlider.py | 13 +- pyforms/terminal/appmanager.py | 6 +- 26 files changed, 802 insertions(+), 660 deletions(-) diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/BaseWidget.py index 5f1fd62..11740b2 100644 --- a/pyforms/gui/BaseWidget.py +++ b/pyforms/gui/BaseWidget.py @@ -33,7 +33,12 @@ class BaseWidget(QFrame): The class implements the most basic widget or window. """ - def __init__(self, title='Untitled', parent_win=None, win_flag=None): + def __init__(self, *args, **kwargs): + title = kwargs.get('title', args[0] if len(args)>0 else '') + + parent_win = kwargs.get('parent_win', None) + win_flag = kwargs.get('win_flag', None) + if parent_win is not None and win_flag is None: win_flag = QtCore.Qt.Dialog QFrame.__init__(self) if parent_win is None else QFrame.__init__(self, parent_win, win_flag) @@ -48,6 +53,7 @@ def __init__(self, title='Untitled', parent_win=None, win_flag=None): else: layout.setMargin(0) + self.title = title self.has_progress = False diff --git a/pyforms/gui/Controls/ControlBase.py b/pyforms/gui/Controls/ControlBase.py index dbe8510..9809644 100755 --- a/pyforms/gui/Controls/ControlBase.py +++ b/pyforms/gui/Controls/ControlBase.py @@ -19,6 +19,8 @@ def __init__(self, *args, **kwargs): self._form = None # Qt widget self._parent = None # Parent window self._popup_menu = None + + self.changed_event = kwargs.get('changed_event', self.changed_event) self._help = kwargs.get('helptext', None) self._value = kwargs.get('default', None) @@ -34,6 +36,12 @@ def __init__(self, *args, **kwargs): self.init_form() + self.enabled = kwargs.get('enabled', True) + self.readonly = kwargs.get('readonly', False) + + if not kwargs.get('visible', True): + self.hide() + def __repr__(self): return str(self._value) @@ -62,8 +70,7 @@ def save_form(self, data, path=None): Save a value to dict variable @param data: dictionary with to where the value of the Control will be added """ - if self.value: - data['value'] = self.value + data['value'] = self.value return data def show(self): diff --git a/pyforms/gui/Controls/ControlBoundingSlider.py b/pyforms/gui/Controls/ControlBoundingSlider.py index 4868658..b7d8c70 100755 --- a/pyforms/gui/Controls/ControlBoundingSlider.py +++ b/pyforms/gui/Controls/ControlBoundingSlider.py @@ -3,392 +3,417 @@ from pysettings import conf -from AnyQt import QtCore +from AnyQt import QtCore from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QSpinBox -from AnyQt.QtGui import QFont, QColor, QCursor, QPainter +from AnyQt.QtGui import QFont, QColor, QCursor, QPainter from pyforms.gui.Controls.ControlBase import ControlBase class GaugeWidgetVertical(QWidget): - def __init__(self, *args, **kwargs): - QWidget.__init__(self, *args, **kwargs) - - self.setMouseTracking(True) - self.setMinimumHeight(30) - self.setMinimumWidth(30) - self.setMaximumWidth(50) - - self._lower = 0 - self._higher = 100 - self._minVal = 0 - self._maxVal = 75 - self._lastMouseY = None - self._moving = False - self._resizingBottom = False - self._resizingTop = False - self._scale = 1.0 - self._use_float = False - - def changed_event(self): - pass - - def paintEvent(self, e): - # call the base implementation to paint normal interface - super(GaugeWidgetVertical, self).paintEvent(e) - draw = QPainter() - draw.begin(self) - - window_with = self.width() - 1 - diff = (self._higher - self._lower) * self.scale - try: - self._step = float(self.height()) / float(diff) - except ZeroDivisionError: - self._step = 0 - y_start = self.height() - (self._minVal - self._lower) * self._step * self.scale - y_end = self.height() - (self._maxVal - self._lower) * self._step * self.scale - - draw.setOpacity(1.0) - draw.setBrush(QtCore.Qt.NoBrush) - draw.setPen(QColor(200, 200, 255)) - - for i in range(self.height() / 5, (self.height() - self.height() / 5) + 1, self.height() / 5): - draw.drawLine(0, i, window_with, i) - - draw.setBrush(QColor(33, 133, 208)) - draw.setPen(QColor(33, 133, 208)) - draw.setOpacity(0.7) - draw.drawRect(0, y_start, window_with, y_end - y_start) - - draw.setFont(QFont('Decorative', 8)) - draw.setPen(QColor(30, 30, 30)) - draw.drawText(3, self.height() - 3, str(self._lower) if self._use_float else str(int(round(self._lower)))) - draw.drawText(3, 10, str(self._higher) if self._use_float else str(int(round(self._higher)))) - - draw.drawText(3, y_start + 11, str(self._minVal) if self._use_float else str(int(round(self._minVal)))) - draw.drawText(3, y_end - 4, str(self._maxVal) if self._use_float else str(int(round(self._maxVal)))) - - draw.end() - - def mousePressEvent(self, event): - self._moving = False - self._resizingBottom = False - self._resizingTop = False - - y_start = self.height() - (self._minVal - self._lower) * self._step * self.scale - y_end = self.height() - (self._maxVal - self._lower) * self._step * self.scale - - if event.buttons() == QtCore.Qt.LeftButton: - if y_start > event.y() > y_end: - self._moving = True - elif event.y() < y_end: - self._resizingTop = True - elif y_start < event.y(): - self._resizingBottom = True - - def mouseReleaseEvent(self, event): - self._moving = False - self._resizingBottom = False - self._resizingTop = False - - def mouseMoveEvent(self, event): - super(GaugeWidgetVertical, self).mouseMoveEvent(event) - - y_start = self.height() - (self._minVal - self._lower) * self._step * self.scale - y_end = self.height() - (self._maxVal - self._lower) * self._step * self.scale - - if y_start < event.y() or event.y() < y_end: - self.setCursor(QCursor(QtCore.Qt.SizeVerCursor)) - else: - self.setCursor(QCursor(QtCore.Qt.ArrowCursor)) - - if event.buttons() == QtCore.Qt.LeftButton: - if self._lastMouseY != None: - diff = self._lastMouseY - event.y() - if diff != 0: - if self._moving: - new_min = self._minVal * self.scale + diff * 1 / self._step - new_max = self._maxVal * self.scale + diff * 1 / self._step - if new_min < new_max: - self._minVal = new_min / self.scale - self._maxVal = new_max / self.scale - elif self._resizingTop: - new_max = self._maxVal * self.scale + diff * 1 / self._step - if self._minVal < (new_max / self.scale): self._maxVal = new_max / self.scale - elif self._resizingBottom: - new_min = self._minVal * self.scale + diff * 1 / self._step - if (new_min / self.scale) < self._maxVal: self._minVal = new_min / self.scale - - self.repaint() - - self.changed_event() - - self._lastMouseY = event.y() - - def mouseReleaseEvent(self, event): - self._lastMouseY = None - - @property - def scale(self): - return self._scale - - @scale.setter - def scale(self, value): - self._scale = value + def __init__(self, *args, **kwargs): + QWidget.__init__(self, *args, **kwargs) + + self.setMouseTracking(True) + self.setMinimumHeight(30) + self.setMinimumWidth(30) + self.setMaximumWidth(50) + + self._lower = 0 + self._higher = 100 + self._minVal = 0 + self._maxVal = 75 + self._lastMouseY = None + self._moving = False + self._resizingBottom = False + self._resizingTop = False + self._scale = 1.0 + self._use_float = False + + def changed_event(self): + pass + + def paintEvent(self, e): + # call the base implementation to paint normal interface + super(GaugeWidgetVertical, self).paintEvent(e) + draw = QPainter() + draw.begin(self) + + window_with = self.width() - 1 + diff = (self._higher - self._lower) * self.scale + try: + self._step = float(self.height()) / float(diff) + except ZeroDivisionError: + self._step = 0 + y_start = self.height() - (self._minVal - self._lower) * self._step * self.scale + y_end = self.height() - (self._maxVal - self._lower) * self._step * self.scale + + draw.setOpacity(1.0) + draw.setBrush(QtCore.Qt.NoBrush) + draw.setPen(QColor(200, 200, 255)) + + for i in range(self.height() / 5, (self.height() - self.height() / 5) + 1, self.height() / 5): + draw.drawLine(0, i, window_with, i) + + draw.setBrush(QColor(33, 133, 208)) + draw.setPen(QColor(33, 133, 208)) + draw.setOpacity(0.7) + draw.drawRect(0, y_start, window_with, y_end - y_start) + + draw.setFont(QFont('Decorative', 8)) + draw.setPen(QColor(30, 30, 30)) + draw.drawText(3, self.height() - 3, str(self._lower) if self._use_float else str(int(round(self._lower)))) + draw.drawText(3, 10, str(self._higher) if self._use_float else str(int(round(self._higher)))) + + draw.drawText(3, y_start + 11, str(self._minVal) if self._use_float else str(int(round(self._minVal)))) + draw.drawText(3, y_end - 4, str(self._maxVal) if self._use_float else str(int(round(self._maxVal)))) + + draw.end() + + def mousePressEvent(self, event): + self._moving = False + self._resizingBottom = False + self._resizingTop = False + + y_start = self.height() - (self._minVal - self._lower) * self._step * self.scale + y_end = self.height() - (self._maxVal - self._lower) * self._step * self.scale + + if event.buttons() == QtCore.Qt.LeftButton: + if y_start > event.y() > y_end: + self._moving = True + elif event.y() < y_end: + self._resizingTop = True + elif y_start < event.y(): + self._resizingBottom = True + + def mouseReleaseEvent(self, event): + self._moving = False + self._resizingBottom = False + self._resizingTop = False + + def mouseMoveEvent(self, event): + super(GaugeWidgetVertical, self).mouseMoveEvent(event) + + y_start = self.height() - (self._minVal - self._lower) * self._step * self.scale + y_end = self.height() - (self._maxVal - self._lower) * self._step * self.scale + + if y_start < event.y() or event.y() < y_end: + self.setCursor(QCursor(QtCore.Qt.SizeVerCursor)) + else: + self.setCursor(QCursor(QtCore.Qt.ArrowCursor)) + + if event.buttons() == QtCore.Qt.LeftButton: + if self._lastMouseY != None: + diff = self._lastMouseY - event.y() + if diff != 0: + if self._moving: + new_min = self._minVal * self.scale + diff * 1 / self._step + new_max = self._maxVal * self.scale + diff * 1 / self._step + if new_min < new_max: + self._minVal = new_min / self.scale + self._maxVal = new_max / self.scale + elif self._resizingTop: + new_max = self._maxVal * self.scale + diff * 1 / self._step + if self._minVal < (new_max / self.scale): self._maxVal = new_max / self.scale + elif self._resizingBottom: + new_min = self._minVal * self.scale + diff * 1 / self._step + if (new_min / self.scale) < self._maxVal: self._minVal = new_min / self.scale + + self.repaint() + + self.changed_event() + + self._lastMouseY = event.y() + + def mouseReleaseEvent(self, event): + self._lastMouseY = None + + @property + def scale(self): + return self._scale + + @scale.setter + def scale(self, value): + self._scale = value class GaugeWidgetHorizontal(GaugeWidgetVertical): - def __init__(self, *args, **kwargs): - super(GaugeWidgetHorizontal, self).__init__(*args, **kwargs) - - self.setMaximumWidth(1000000) - self.setMinimumHeight(20) - self.setMaximumHeight(20) - - def paintEvent(self, e): - # call the base implementation to paint normal interface - QWidget.paintEvent(self, e); - draw = QPainter(); - draw.begin(self) - - h = self.height() - 1 - diff = (self._higher - self._lower) * self.scale - - try: - self._step = float(self.width()) / float(diff) - except ZeroDivisionError: - self._step = 0 - x_start = (self._minVal - self._lower) * self._step * self.scale - x_end = (self._maxVal - self._lower) * self._step * self.scale - - draw.setOpacity(1.0) - draw.setBrush(QtCore.Qt.NoBrush) - draw.setPen(QColor(200, 200, 255)) - - for i in range( int(self.width()/5), int(self.width()-self.width()/5) + 1, int(self.width()/5) ): - draw.drawLine(i, 0, i, h) - - draw.setBrush(QColor(238, 238, 238)) - draw.setPen(QColor(238, 238, 238)) - draw.drawRoundedRect(0, 2, self.width(), h - 4, 3, 3) - - draw.setBrush(QColor(33, 133, 208)) - draw.setPen(QColor(33, 133, 208)) - draw.drawRoundedRect(int(round(x_start)), 2, int(round(x_end - x_start)), h - 4, 3, 3) - # draw.setOpacity(1.0) - draw.setFont(QFont('Decorative', 8)) - draw.setPen(QColor(80, 80, 80)) - - str(self._maxVal) if self._use_float else str(int(round(self._maxVal))) - - boundtext = draw.boundingRect(QtCore.QRectF(), - str(self._higher) if self._use_float else str(int(round(self._higher)))) - draw.drawText(self.width() - boundtext.width(), 14, - str(self._higher) if self._use_float else str(int(round(self._higher)))) - draw.drawText(0, 14, str(self._lower) if self._use_float else str(int(round(self._lower)))) - - draw.setPen(QColor(255, 255, 255)) - boundtext = draw.boundingRect(QtCore.QRectF(), - str(self._minVal) if self._use_float else str(int(round(self._minVal)))) - draw.drawText(x_start + 2, 14, str(self._minVal) if self._use_float else str(int(round(self._minVal)))) - boundtext = draw.boundingRect(QtCore.QRectF(), - str(self._maxVal) if self._use_float else str(int(round(self._maxVal)))) - draw.drawText(x_end - boundtext.width(), 14, - str(self._maxVal) if self._use_float else str(int(round(self._maxVal)))) - - draw.end() - - def mousePressEvent(self, event): - self._moving = False - self._resizingLeft = False - self._resizingRight = False - - x_start = (self._minVal - self._lower) * self._step * self.scale - x_end = (self._maxVal - self._lower) * self._step * self.scale - - if event.buttons() == QtCore.Qt.LeftButton: - if x_start < event.x() < x_end: - self._moving = True - elif event.x() > x_end: - self._resizingLeft = True - elif x_start > event.x(): - self._resizingRight = True - - def mouseMoveEvent(self, event): - super(GaugeWidgetVertical, self).mouseMoveEvent(event) - - x_start = (self._minVal - self._lower) * self._step * self.scale - x_end = (self._maxVal - self._lower) * self._step * self.scale - - # set the cursors - if x_start >= event.x() or event.x() >= x_end: - self.setCursor(QCursor(QtCore.Qt.SizeHorCursor)) - else: - self.setCursor(QCursor(QtCore.Qt.ArrowCursor)) - - if event.buttons() == QtCore.Qt.LeftButton: - if self._lastMouseY != None: - diff = self._lastMouseY - event.x() - if diff != 0: - if self._moving: - new_min = self._minVal * self.scale - diff * 1 / self._step - new_max = self._maxVal * self.scale - diff * 1 / self._step - if new_min < new_max: - self._minVal = new_min / self.scale - self._maxVal = new_max / self.scale - elif self._resizingLeft: - new_max = self._maxVal * self.scale - diff * 1 / self._step - if self._minVal < (new_max / self.scale): self._maxVal = new_max / self.scale - elif self._resizingRight: - new_min = self._minVal * self.scale - diff * 1 / self._step - if (new_min / self.scale) < self._maxVal: self._minVal = new_min / self.scale - - self.repaint() - self.changed_event() - - self._lastMouseY = event.x() + def __init__(self, *args, **kwargs): + super(GaugeWidgetHorizontal, self).__init__(*args, **kwargs) + + self.setMaximumWidth(1000000) + self.setMinimumHeight(20) + self.setMaximumHeight(20) + + def paintEvent(self, e): + # call the base implementation to paint normal interface + QWidget.paintEvent(self, e); + draw = QPainter(); + draw.begin(self) + + h = self.height() - 1 + diff = (self._higher - self._lower) * self.scale + + try: + self._step = float(self.width()) / float(diff) + except ZeroDivisionError: + self._step = 0 + x_start = (self._minVal - self._lower) * self._step * self.scale + x_end = (self._maxVal - self._lower) * self._step * self.scale + + draw.setOpacity(1.0) + draw.setBrush(QtCore.Qt.NoBrush) + draw.setPen(QColor(200, 200, 255)) + + for i in range( int(self.width()/5), int(self.width()-self.width()/5) + 1, int(self.width()/5) ): + draw.drawLine(i, 0, i, h) + + draw.setBrush(QColor(238, 238, 238)) + draw.setPen(QColor(238, 238, 238)) + draw.drawRoundedRect(0, 2, self.width(), h - 4, 3, 3) + + draw.setBrush(QColor(33, 133, 208)) + draw.setPen(QColor(33, 133, 208)) + draw.drawRoundedRect(int(round(x_start)), 2, int(round(x_end - x_start)), h - 4, 3, 3) + # draw.setOpacity(1.0) + draw.setFont(QFont('Decorative', 8)) + draw.setPen(QColor(80, 80, 80)) + + str(self._maxVal) if self._use_float else str(int(round(self._maxVal))) + + boundtext = draw.boundingRect(QtCore.QRectF(), + str(self._higher) if self._use_float else str(int(round(self._higher)))) + draw.drawText(self.width() - boundtext.width(), 14, + str(self._higher) if self._use_float else str(int(round(self._higher)))) + draw.drawText(0, 14, str(self._lower) if self._use_float else str(int(round(self._lower)))) + + draw.setPen(QColor(255, 255, 255)) + boundtext = draw.boundingRect(QtCore.QRectF(), + str(self._minVal) if self._use_float else str(int(round(self._minVal)))) + draw.drawText(x_start + 2, 14, str(self._minVal) if self._use_float else str(int(round(self._minVal)))) + boundtext = draw.boundingRect(QtCore.QRectF(), + str(self._maxVal) if self._use_float else str(int(round(self._maxVal)))) + draw.drawText(x_end - boundtext.width(), 14, + str(self._maxVal) if self._use_float else str(int(round(self._maxVal)))) + + draw.end() + + def mousePressEvent(self, event): + self._moving = False + self._resizingLeft = False + self._resizingRight = False + + x_start = (self._minVal - self._lower) * self._step * self.scale + x_end = (self._maxVal - self._lower) * self._step * self.scale + + if event.buttons() == QtCore.Qt.LeftButton: + if x_start < event.x() < x_end: + self._moving = True + elif event.x() > x_end: + self._resizingLeft = True + elif x_start > event.x(): + self._resizingRight = True + + def mouseMoveEvent(self, event): + super(GaugeWidgetVertical, self).mouseMoveEvent(event) + + x_start = (self._minVal - self._lower) * self._step * self.scale + x_end = (self._maxVal - self._lower) * self._step * self.scale + + # set the cursors + if x_start >= event.x() or event.x() >= x_end: + self.setCursor(QCursor(QtCore.Qt.SizeHorCursor)) + else: + self.setCursor(QCursor(QtCore.Qt.ArrowCursor)) + + if event.buttons() == QtCore.Qt.LeftButton: + if self._lastMouseY != None: + diff = self._lastMouseY - event.x() + if diff != 0: + if self._moving: + new_min = self._minVal * self.scale - diff * 1 / self._step + new_max = self._maxVal * self.scale - diff * 1 / self._step + if new_min < new_max: + self._minVal = new_min / self.scale + self._maxVal = new_max / self.scale + elif self._resizingLeft: + new_max = self._maxVal * self.scale - diff * 1 / self._step + if self._minVal < (new_max / self.scale): self._maxVal = new_max / self.scale + elif self._resizingRight: + new_min = self._minVal * self.scale - diff * 1 / self._step + if (new_min / self.scale) < self._maxVal: self._minVal = new_min / self.scale + + self.repaint() + self.changed_event() + + self._lastMouseY = event.x() class ControlBoundingSlider(ControlBase): - def __init__(self, label="", default=[20, 40], min=0, max=100, horizontal=False, helptext=None, - show_spinboxes=True): - self._horizontal = horizontal - self._show_spinboxes = show_spinboxes - ControlBase.__init__(self, label, default, helptext=helptext) - - self.min = min - self.max = max - self.value = default - self.__update() - - def init_form(self): - self._boundingbox = GaugeWidgetHorizontal() if self._horizontal else GaugeWidgetVertical() - self._boundingbox.changed_event = self.__update - - if self._show_spinboxes: - self._form = hwidget = QWidget() - if self._horizontal: - hlayout = QHBoxLayout() - else: - hlayout = QVBoxLayout() - - - if conf.PYFORMS_USE_QT5: - hlayout.setContentsMargins(0,0,0,0) - else: - hlayout.setMargin(0) - - - hwidget.setLayout(hlayout) - self._min_spinbox = QSpinBox() - self._min_spinbox.valueChanged.connect(self.__min_spinbox_changed) - self._min_spinbox.setMaximumWidth(95) - - self._max_spinbox = QSpinBox() - self._max_spinbox.valueChanged.connect(self.__max_spinbox_changed) - self._max_spinbox.setMaximumWidth(95) - - if self._horizontal: - hlayout.addWidget(self._min_spinbox) - else: - hlayout.addWidget(self._max_spinbox) - hlayout.addWidget(self._boundingbox) - if self._horizontal: - hlayout.addWidget(self._max_spinbox) - else: - hlayout.addWidget(self._min_spinbox) - - else: - self._form = self._boundingbox - - super(ControlBoundingSlider, self).init_form() - - def __max_spinbox_changed(self, value): - if value < self._boundingbox._minVal: return - if hasattr(self, '_is_updating_spinboxes'): return - self.scale = self.__find_scale_factor(value) - self._boundingbox._maxVal = value - self._boundingbox.repaint() - self.changed_event() - - def __min_spinbox_changed(self, value): - if value > self._boundingbox._maxVal: return - if hasattr(self, '_is_updating_spinboxes'): return - self.scale = self.__find_scale_factor(value) - self._boundingbox._minVal = value - self._boundingbox.repaint() - self.changed_event() - - def __update(self): - l, h = self._boundingbox._minVal, self._boundingbox._maxVal - self._is_updating_spinboxes = True - self._min_spinbox.setValue(l) - self._max_spinbox.setValue(h) - del self._is_updating_spinboxes - self.changed_event() - - def changed_event(self): - pass - - def __find_scale_factor(self, value): - scale = 1.0 - new_value = value - while abs(new_value) < 0.0: - scale *= 10.0 - new_value = value * scale - return scale - - ########################################################################## - ############ Properties ################################################## - ########################################################################## - - @property - def value(self): - return self._boundingbox._minVal, self._boundingbox._maxVal - - @value.setter - def value(self, value): - ControlBase.value.fset(self, value) - self.scale = self.__find_scale_factor(value[0]) - self._boundingbox._minVal, self._boundingbox._maxVal = value[0], value[1] - if hasattr(self, '_min_spinbox'): self._min_spinbox.setValue(value[0]) - if hasattr(self, '_max_spinbox'): self._max_spinbox.setValue(value[1]) - self._boundingbox.repaint() - - @property - def min(self): - return self._boundingbox._lower - - @min.setter - def min(self, value): - self._boundingbox._lower = value - self._boundingbox.repaint() - if hasattr(self, '_min_spinbox'): self._min_spinbox.setMinimum(value) - if hasattr(self, '_max_spinbox'): self._max_spinbox.setMinimum(value) - - @property - def max(self): - return self._boundingbox._higher - - @max.setter - def max(self, value): - self._boundingbox._higher = value - self._boundingbox.repaint() - if hasattr(self, '_min_spinbox'): self._min_spinbox.setMaximum(value) - if hasattr(self, '_max_spinbox'): self._max_spinbox.setMaximum(value) - - @property - def scale(self): - return self._boundingbox.scale - - @scale.setter - def scale(self, value): - self._boundingbox.scale = value - - @property - def convert_2_int(self): - return not self._boundingbox._use_float - - @convert_2_int.setter - def convert_2_int(self, value): - self._boundingbox._use_float = not value + def __init__(self, label="", default=[20, 40], min=0, max=100, horizontal=False, helptext=None, + show_spinboxes=True): + self._horizontal = horizontal + self._show_spinboxes = show_spinboxes + ControlBase.__init__(self, label, default, helptext=helptext) + + self.min = min + self.max = max + self.value = default + self.__update() + + def init_form(self): + self._boundingbox = GaugeWidgetHorizontal() if self._horizontal else GaugeWidgetVertical() + self._boundingbox.changed_event = self.__update + + if self._show_spinboxes: + self._form = hwidget = QWidget() + if self._horizontal: + hlayout = QHBoxLayout() + else: + hlayout = QVBoxLayout() + + + if conf.PYFORMS_USE_QT5: + hlayout.setContentsMargins(0,0,0,0) + else: + hlayout.setMargin(0) + + + hwidget.setLayout(hlayout) + self._min_spinbox = QSpinBox() + self._min_spinbox.valueChanged.connect(self.__min_spinbox_changed) + self._min_spinbox.setMaximumWidth(95) + + self._max_spinbox = QSpinBox() + self._max_spinbox.valueChanged.connect(self.__max_spinbox_changed) + self._max_spinbox.setMaximumWidth(95) + + if self._horizontal: + hlayout.addWidget(self._min_spinbox) + else: + hlayout.addWidget(self._max_spinbox) + hlayout.addWidget(self._boundingbox) + if self._horizontal: + hlayout.addWidget(self._max_spinbox) + else: + hlayout.addWidget(self._min_spinbox) + + else: + self._form = self._boundingbox + + super(ControlBoundingSlider, self).init_form() + + def __max_spinbox_changed(self, value): + if value < self._boundingbox._minVal: return + if hasattr(self, '_is_updating_spinboxes'): return + self.scale = self.__find_scale_factor(value) + self._boundingbox._maxVal = value + self._boundingbox.repaint() + self.changed_event() + + def __min_spinbox_changed(self, value): + if value > self._boundingbox._maxVal: return + if hasattr(self, '_is_updating_spinboxes'): return + self.scale = self.__find_scale_factor(value) + self._boundingbox._minVal = value + self._boundingbox.repaint() + self.changed_event() + + def __update(self): + l, h = self._boundingbox._minVal, self._boundingbox._maxVal + self._is_updating_spinboxes = True + self._min_spinbox.setValue(l) + self._max_spinbox.setValue(h) + del self._is_updating_spinboxes + self.changed_event() + + def changed_event(self): + pass + + def __find_scale_factor(self, value): + scale = 1.0 + new_value = value + while abs(new_value) < 0.0: + scale *= 10.0 + new_value = value * scale + return scale + + def load_form(self, data, path=None): + """ + Load a value from the dict variable + @param data: dictionary with the value of the Control + """ + + self.convert_2_int = data.get('convert-int', self.convert_2_int) + self.scale = data.get('scale', self.scale) + self.max = data.get('max', self.max) + self.min = data.get('min', self.min) + self.value = data.get('value', self.value) + + + def save_form(self, data, path=None): + """ + Save a value to dict variable + @param data: dictionary with to where the value of the Control will be added + """ + data['value'] = self.value + data['max'] = self.max + data['min'] = self.min + data['scale'] = self.scale + data['convert-int'] = self.convert_2_int + return data + + ########################################################################## + ############ Properties ################################################## + ########################################################################## + + @property + def value(self): + return self._boundingbox._minVal, self._boundingbox._maxVal + + @value.setter + def value(self, value): + self.scale = self.__find_scale_factor(value[0]) + self._boundingbox._minVal, self._boundingbox._maxVal = value[0], value[1] + if hasattr(self, '_min_spinbox'): self._min_spinbox.setValue(value[0]) + if hasattr(self, '_max_spinbox'): self._max_spinbox.setValue(value[1]) + ControlBase.value.fset(self, value) + self._boundingbox.repaint() + + @property + def min(self): + return self._boundingbox._lower + + @min.setter + def min(self, value): + self._boundingbox._lower = value + self._boundingbox.repaint() + if hasattr(self, '_min_spinbox'): self._min_spinbox.setMinimum(value) + if hasattr(self, '_max_spinbox'): self._max_spinbox.setMinimum(value) + + @property + def max(self): + return self._boundingbox._higher + + @max.setter + def max(self, value): + self._boundingbox._higher = value + self._boundingbox.repaint() + if hasattr(self, '_min_spinbox'): self._min_spinbox.setMaximum(value) + if hasattr(self, '_max_spinbox'): self._max_spinbox.setMaximum(value) + + @property + def scale(self): + return self._boundingbox.scale + + @scale.setter + def scale(self, value): + self._boundingbox.scale = value + + @property + def convert_2_int(self): + return not self._boundingbox._use_float + + @convert_2_int.setter + def convert_2_int(self, value): + self._boundingbox._use_float = not value diff --git a/pyforms/gui/Controls/ControlButton.py b/pyforms/gui/Controls/ControlButton.py index 51fd71e..a1f7043 100755 --- a/pyforms/gui/Controls/ControlButton.py +++ b/pyforms/gui/Controls/ControlButton.py @@ -13,9 +13,11 @@ class ControlButton(ControlBase): - def __init__(self, label='', default=None, checkable=False, helptext=None): - self._checkable = checkable - super(ControlButton, self).__init__(label=label, default=default, helptext=helptext) + def __init__(self, *args, **kwargs): + self._checkable = kwargs.get('checkable', False) + super(ControlButton, self).__init__(*args, **kwargs) + + default = kwargs.get('default', None) if default: self.value = default def init_form(self): diff --git a/pyforms/gui/Controls/ControlCheckBox.py b/pyforms/gui/Controls/ControlCheckBox.py index f3e7f6e..17a9eee 100755 --- a/pyforms/gui/Controls/ControlCheckBox.py +++ b/pyforms/gui/Controls/ControlCheckBox.py @@ -29,7 +29,7 @@ def __checkedToggle(self): def load_form(self, data, path=None): if 'value' in data: - self._form.checkBox.setChecked(data['value'] == 'True') + self._form.checkBox.setChecked(data['value'] == 'True' or data['value'] == True) def save_form(self, data, path=None): data['value'] = str(self._form.checkBox.isChecked()) diff --git a/pyforms/gui/Controls/ControlCheckBoxList.py b/pyforms/gui/Controls/ControlCheckBoxList.py index dd41c78..180e034 100755 --- a/pyforms/gui/Controls/ControlCheckBoxList.py +++ b/pyforms/gui/Controls/ControlCheckBoxList.py @@ -130,6 +130,7 @@ def value(self): def value(self, value): self.clear() for row in value: self += row + self.changed_event() @property def selected_row_index(self): diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py b/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py index 1ac8f5d..2482d34 100755 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py +++ b/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py @@ -26,9 +26,9 @@ def __init__(self, parent_win, label, begin, end): else: self.layout().setMargin(5) - self._label = ControlText('Label', label) - self._begin = ControlNumber('Begin', begin, 0, 100000000000000) - self._end = ControlNumber('End', end, 0, 100000000000000) + self._label = ControlText('Label', default=label) + self._begin = ControlNumber('Begin', default=begin, minimum=0, maximum=100000000000000) + self._end = ControlNumber('End', default=end, minimum=0, maximum=100000000000000) self._applybtn = ControlButton('Apply') @@ -42,12 +42,16 @@ def __init__(self, parent_win, label, begin, end): self._end.changed_event = self.__end_changed_event def __begin_changed_event(self): - if self._begin.value>=self._end.value: + if not hasattr(self, '_updating') and self._begin.value>=self._end.value: + self._updating = True self._begin.value = self._end.value-1 + del self._updating def __end_changed_event(self): - if self._end.value<=self._begin.value: + if not hasattr(self, '_updating') and self._end.value<=self._begin.value: + self._updating = True self._end.value = self._begin.value+1 + del self._updating @property diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py b/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py index 9a55b45..d6edefc 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py +++ b/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py @@ -31,7 +31,7 @@ def __init__(self, timeline=None): # Definition of the forms fields - self._graphs_list = ControlList('Graphs list (try double click)') + self._graphs_list = ControlList('Graphs list (try double click)', readonly=False, select_entire_row=True) self._equation = ControlTextArea('Equation') self._graphname = ControlText('Graph name') self._genevts_btn = ControlButton('Generate graph') diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py b/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py index 45c395b..7d00c39 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py +++ b/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py @@ -7,6 +7,10 @@ from pyforms.Controls import ControlSlider from pyforms.Controls import ControlText from pyforms.Controls import ControlLabel +from pysettings import conf + +if conf.PYFORMS_MODE=='GUI': + from AnyQt.QtWidgets import QColorDialog logger = logging.getLogger(__name__) @@ -24,12 +28,13 @@ def __init__(self, timelineWidget=None, parent_win=None): # Definition of the forms fields self._graphs_list = ControlList('Graphs list') self._name = ControlText('Name') - self._min_value = ControlNumber('Min', default=0, minimum=-sys.float_info.min, maximum=sys.float_info.max) - self._max_value = ControlNumber('Max', default=0, minimum=-sys.float_info.min, maximum=sys.float_info.max) + self._min_value = ControlNumber('Min', default=0, minimum=-sys.float_info.max, maximum=sys.float_info.max) + self._max_value = ControlNumber('Max', default=0, minimum=-sys.float_info.max, maximum=sys.float_info.max) self._values_zoom = ControlSlider('Amplitude', default=100, minimum=60, maximum=400) self._values_top = ControlNumber('Bottom', default=0, minimum=-1000, maximum=1000) self._remove_graph_btn = ControlButton('Remove graph') self._value = ControlLabel() + self._pickcolor = ControlButton('Pick color', default=self.__pickcolor_evt) self._graphs_list.readonly = True @@ -41,7 +46,7 @@ def __init__(self, timelineWidget=None, parent_win=None): ' ', '_name', ('_min_value', '_max_value', ' '), - ('_values_top', ' '), + ('_values_top', '_pickcolor'), '_values_zoom', 'info:Choose one graph and move the mouse over \nthe timeline to visualize the coordenates.', '_value' @@ -66,6 +71,7 @@ def __init__(self, timelineWidget=None, parent_win=None): self._values_zoom.enabled = False self._values_top.enabled = False self._remove_graph_btn.enabled = False + self._pickcolor.enabled = False self._remove_graph_btn.value = self.__remove_chart @@ -97,6 +103,13 @@ def show(self): super(GraphsProperties, self).show() self._loaded = False + def __pickcolor_evt(self): + color = QColorDialog.getColor( + self._current_selected_graph._color, + self, 'Pick a color for the graph') + self._current_selected_graph._color = color + self._timeline.repaint() + def __remove_chart(self): index = self._graphs_list.selected_row_index @@ -110,6 +123,7 @@ def __remove_chart(self): self._values_zoom.enabled = False self._values_top.enabled = False self._remove_graph_btn.enabled = False + self._pickcolor.enabled = False self._timeline.repaint() self._mainwindow -= index @@ -143,6 +157,7 @@ def __graphs_list_selection_changed(self): self._values_zoom.enabled = True self._values_top.enabled = True self._remove_graph_btn.enabled = True + self._pickcolor.enabled = True self._current_selected_graph = graph del self._updating_properties diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/Controls/ControlList.py index 069ff17..a83452a 100755 --- a/pyforms/gui/Controls/ControlList.py +++ b/pyforms/gui/Controls/ControlList.py @@ -26,15 +26,16 @@ class ControlList(ControlBase, QWidget): CELL_VALUE_BEFORE_CHANGE = None # store value when cell is double clicked - def __init__(self, label="", default="", add_function=None, - remove_function=None): + def __init__(self, *args, **kwargs): QWidget.__init__(self) - self._plusFunction = add_function - self._minusFunction = remove_function - ControlBase.__init__(self, label, default) + self._plusFunction = kwargs.get('add_function', None) + self._minusFunction = kwargs.get('remove_function', None) + ControlBase.__init__(self, *args, **kwargs) self.autoscroll = False + + self.select_entire_row = kwargs.get('select_entire_row', False) ########################################################################## @@ -73,6 +74,8 @@ def init_form(self): self.plusButton.pressed.connect(plusFunction) self.minusButton.pressed.connect(minusFunction) + + def __repr__(self): return "ControlList " + str(self._value) diff --git a/pyforms/gui/Controls/ControlNumber.py b/pyforms/gui/Controls/ControlNumber.py index b6c78dd..5386678 100644 --- a/pyforms/gui/Controls/ControlNumber.py +++ b/pyforms/gui/Controls/ControlNumber.py @@ -17,6 +17,7 @@ def __init__(self, *args, **kwargs): self._max = kwargs.get('maximum', 100) if 'default' not in kwargs: kwargs['default'] = 0 ControlBase.__init__(self, *args, **kwargs) + self.decimals = kwargs.get('decimals', 0) def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "number.ui") @@ -27,7 +28,7 @@ def init_form(self): self.value = self._value self.form.label.setAccessibleName('ControlNumber-label') self.form.spinBox.valueChanged.connect(self.update_event) - self.form.spinBox.setDecimals(0) + def update_event(self, value): self._updateSlider = False @@ -50,7 +51,7 @@ def value(self): return self._value @value.setter - def value(self, value): + def value(self, value): self.form.spinBox.setValue(value) ControlBase.value.fset(self, value) diff --git a/pyforms/gui/Controls/ControlSlider.py b/pyforms/gui/Controls/ControlSlider.py index 2c48b9f..b3cecb3 100755 --- a/pyforms/gui/Controls/ControlSlider.py +++ b/pyforms/gui/Controls/ControlSlider.py @@ -47,7 +47,7 @@ def load_form(self, data, path=None): if 'value' in data: self.value = int(data['value']) def save_form(self, data, path=None): - if self.value: data['value'] = self.value + data['value'] = self.value @property def value(self): diff --git a/pyforms/gui/Controls/ControlTextArea.py b/pyforms/gui/Controls/ControlTextArea.py index b1f670d..75ef327 100755 --- a/pyforms/gui/Controls/ControlTextArea.py +++ b/pyforms/gui/Controls/ControlTextArea.py @@ -20,10 +20,11 @@ class ControlTextArea(ControlBase): - def __init__(self, label='', default=None, helptext=None): - ControlBase.__init__(self, label, default, helptext) + def __init__(self, *args, **kwargs): + ControlBase.__init__(self, *args, **kwargs) self.autoscroll = False + def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "textArea.ui") diff --git a/pyforms/gui/standaloneManager.py b/pyforms/gui/standaloneManager.py index 15e6bc2..4747bd0 100644 --- a/pyforms/gui/standaloneManager.py +++ b/pyforms/gui/standaloneManager.py @@ -176,20 +176,25 @@ def execute_test_file(myapp): exec(code, global_vars, local_vars) -def start_app(AppClass, geometry=None, **kwargs): +def start_app(*args, **kwargs): from pysettings import conf + AppClass = args[0] + app = QApplication(sys.argv) conf += 'pyforms.gui.settings' - app_def = AppClass(**kwargs) + + app_def = AppClass(**kwargs.get('app_args', {})) mainwindow = StandAloneContainer(app_def) myapp = mainwindow.centralWidget() + geometry = kwargs.get('geometry', None) + if geometry is not None: mainwindow.show() mainwindow.setGeometry(*geometry) diff --git a/pyforms/settings.py b/pyforms/settings.py index 0441907..eafca9e 100644 --- a/pyforms/settings.py +++ b/pyforms/settings.py @@ -2,9 +2,13 @@ # -*- coding: utf-8 -*- -import logging, os +import logging, os, sys + +if 'terminal_mode' in sys.argv: + PYFORMS_MODE = 'TERMINAL' +else: + PYFORMS_MODE = os.environ.get('PYFORMS_MODE', 'GUI') -PYFORMS_MODE = os.environ.get('PYFORMS_MODE', 'GUI') PYFORMS_LOG_FILENAME = 'pyforms.log' PYFORMS_LOG_HANDLER_FILE_LEVEL = logging.DEBUG diff --git a/pyforms/terminal/BaseWidget.py b/pyforms/terminal/BaseWidget.py index 3e57fa9..31d2382 100755 --- a/pyforms/terminal/BaseWidget.py +++ b/pyforms/terminal/BaseWidget.py @@ -1,185 +1,220 @@ -from pyforms.Controls import ControlFile, ControlSlider, ControlText, ControlCombo, ControlCheckBox, ControlBase, ControlDir, ControlNumber +from pyforms.terminal.Controls.ControlFile import ControlFile +from pyforms.terminal.Controls.ControlSlider import ControlSlider +from pyforms.terminal.Controls.ControlText import ControlText +from pyforms.terminal.Controls.ControlCombo import ControlCombo +from pyforms.terminal.Controls.ControlCheckBox import ControlCheckBox +from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.Controls.ControlDir import ControlDir +from pyforms.terminal.Controls.ControlNumber import ControlNumber from datetime import datetime, timedelta import argparse, uuid, os, shutil, time, sys, subprocess +import simplejson as json try: - import requests + import requests except: - print("No requests lib") + print("No requests lib") class BaseWidget(object): - def __init__(self, title, parent_win=None, win_flag=None): - self._parser = argparse.ArgumentParser() - with open('pid.txt', 'w') as f: - f.write( str(os.getpid()) ) - - self._controlsPrefix = '' - self._title = title - self.stop = False - - ############################################################################ - ############ Module functions ############################################# - ############################################################################ - - def init_form(self, parse=True): - result = {} - for fieldname, var in self.controls.items(): - name = var._name - if isinstance(var, ( - ControlFile,ControlSlider,ControlText, - ControlCombo,ControlCheckBox, ControlDir, ControlNumber - ) - ): - self._parser.add_argument("--%s" % name, help=var.label) - - if parse: - - self._parser.add_argument( - "--exec{0}".format(self._controlsPrefix), - default='', - help='Function from the application that should be executed. Use | to separate a list of functions.') - self._args = self._parser.parse_args() - - self.__parse_terminal_parameters() - self.__execute_events() - - - def __parse_terminal_parameters(self): - for fieldname, var in self.controls.items(): - name = var._name - if self._args.__dict__.get(name, None): - - if isinstance(var, ControlFile): - value = self._args.__dict__[name] - if value!=None and (value.startswith('http://') or value.startswith('https://')): - local_filename = value.split('/')[-1] - outputFileName = os.path.join('input', local_filename) - self.__downloadFile(value, outputFileName) - var.value = outputFileName - else: - var.value = value - - if isinstance(var, ControlDir): - value = self._args.__dict__[name] - var.value = value - elif isinstance(var, (ControlText, ControlCombo)): - var.value = self._args.__dict__[name] - elif isinstance(var, ControlCheckBox): - var.value = self._args.__dict__[name]=='True' - elif isinstance(var, (ControlSlider, ControlNumber) ): - var.value = int(self._args.__dict__[name]) - - - - def __execute_events(self): - for function in self._args.__dict__.get("exec{0}".format(self._controlsPrefix), []).split('|'): - if len(function)>0: - getattr(self, function)() - - res = {} - for controlName, control in self.controls.items(): - res[controlName] = {'value': control.value } - with open('out-parameters.txt', 'w') as outfile: - outfile.write( str(res) ) - - - def __downloadFile(self, url, outFilepath): - chunksize = 512*1024 - r = requests.get(url, stream=True) - with open(outFilepath, 'w') as f: - for chunk in r.iter_content(chunk_size=chunksize): - if chunk: f.write(chunk); f.flush(); - - - - def execute(self): pass - - - def start_progress(self, total = 100): - self._total_processing_count = total - self._processing_initial_time = time.time() - self._processing_count = 1 - - def update_progress(self): - div = int(self._total_processing_count/400) - if div==0: div = 1 - if (self._processing_count % div )==0: - self._processing_last_time = time.time() - total_passed_time = self._processing_last_time - self._processing_initial_time - remaining_time = ( (self._total_processing_count * total_passed_time) / self._processing_count ) - total_passed_time - if remaining_time<0: remaining_time = 0 - time_remaining = datetime(1,1,1) + timedelta(seconds=remaining_time ) - time_elapsed = datetime(1,1,1) + timedelta(seconds=(total_passed_time) ) - - values = ( - time_elapsed.day-1, time_elapsed.hour, time_elapsed.minute, time_elapsed.second, - time_remaining.day-1, time_remaining.hour, time_remaining.minute, time_remaining.second, - (float(self._processing_count)/float(self._total_processing_count))*100.0, self._processing_count, self._total_processing_count, - ) - - print("Elapsed: %d:%d:%d:%d; Remaining: %d:%d:%d:%d; Processed %0.2f %% (%d/%d); | \r" % values) - sys.stdout.flush() - - self._processing_count += 1 - - def end_progress(self): - self._processing_count = self._total_processing_count - self.update_progress() - - - - def __savePID(self, pid): - try: - with open('pending_PID.txt', 'w') as f: - f.write(str(pid)) - f.write('\n') - except (IOError) as e: - raise e - - def __savePID(self, pid): - try: - with open('pending_PID.txt', 'w') as f: - f.write(str(pid)) - f.write('\n') - except (IOError) as e: - raise e - - - def executeCommand(self, cmd, cwd=None, env=None): - if cwd!=None: - currentdirectory = os.getcwd() - os.chdir(cwd) - - print(" ".join(cmd)) - proc = subprocess.Popen(cmd) - - if cwd!=None: os.chdir(currentdirectory) - self.__savePID(proc.pid) - proc.wait() - #(output, error) = proc.communicate() - #if error: print 'error: ', error - #print 'output: ', output - return ''#output - - def exec_terminal_cmd(self, args, **kwargs): - print('TERMINAL <<',' '.join(args) ) - sys.stdout.flush() - proc = subprocess.Popen(args, **kwargs) - self.__savePID(proc.pid) - proc.wait() - sys.stdout.flush() - - - @property - def controls(self): - """ - Return all the form controls from the the module - """ - result = {} - for name, var in vars(self).items(): - if isinstance(var, ControlBase): - var._name = self._controlsPrefix+"-"+name if len(self._controlsPrefix)>0 else name - result[name] = var - return result \ No newline at end of file + def __init__(self, *args, **kwargs): + self._parser = argparse.ArgumentParser() + self._controlsPrefix = '' + self._title = kwargs.get('title', args[0] if len(args)>0 else '') + self.stop = False + + self._conf = kwargs.get('load', None) + + ############################################################################ + ############ Module functions ############################################# + ############################################################################ + + def init_form(self, parse=True): + result = {} + for fieldname, var in self.controls.items(): + name = var._name + if isinstance(var, ( + ControlFile, ControlSlider, ControlText, + ControlCombo,ControlCheckBox, ControlDir, ControlNumber + ) + ): + self._parser.add_argument("--%s" % name, help=var.label) + + if parse: + self._parser.add_argument('terminal_mode', type=str, default='terminal_mode', help='Flag to run pyforms in terminal mode') + self._parser.add_argument( + "--exec{0}".format(self._controlsPrefix), + default='', + help='Function from the application that should be executed. Use | to separate a list of functions.') + self._parser.add_argument( + "--load{0}".format(self._controlsPrefix), + default=None, + help='Load a json file containing the pyforms form configuration.') + self._args = self._parser.parse_args() + + self.__parse_terminal_parameters() + self.__execute_events() + + def load_form(self, data, path=None): + allparams = self.controls + + if hasattr(self, 'load_order'): + for name in self.load_order: + param = allparams[name] + if name in data: + param.load_form(data[name]) + else: + for name, param in allparams.items(): + if name in data: + param.load_form(data[name]) + + + def __parse_terminal_parameters(self): + for fieldname, var in self.controls.items(): + name = var._name + if self._args.__dict__.get(name, None): + + if isinstance(var, ControlFile): + value = self._args.__dict__[name] + if value!=None and (value.startswith('http://') or value.startswith('https://')): + local_filename = value.split('/')[-1] + outputFileName = os.path.join('input', local_filename) + self.__downloadFile(value, outputFileName) + var.value = outputFileName + else: + var.value = value + + if isinstance(var, ControlDir): + value = self._args.__dict__[name] + var.value = value + elif isinstance(var, (ControlText, ControlCombo)): + var.value = self._args.__dict__[name] + elif isinstance(var, ControlCheckBox): + var.value = self._args.__dict__[name]=='True' + elif isinstance(var, (ControlSlider, ControlNumber) ): + var.value = int(self._args.__dict__[name]) + + if self._args.load: + print('\n--------- LOADING CONFIG ------------------') + with open(self._args.load) as infile: + data = json.load(infile) + self.load_form(data, os.path.dirname(self._args.load)) + print('--------- END LOADING CONFIG --------------\n') + elif self._conf is not None: + print('\n--------- LOADING DEFAULT CONFIG ------------------') + self.load_form(self._conf, '.') + print('--------- END LOADING DEFAULT CONFIG --------------\n') + + + + def __execute_events(self): + for function in self._args.__dict__.get("exec{0}".format(self._controlsPrefix), []).split('|'): + if len(function)>0: + getattr(self, function)() + + res = {} + for controlName, control in self.controls.items(): + res[controlName] = {'value': control.value } + with open('out-parameters.txt', 'w') as outfile: + outfile.write( str(res) ) + + + def __downloadFile(self, url, outFilepath): + chunksize = 512*1024 + r = requests.get(url, stream=True) + with open(outFilepath, 'w') as f: + for chunk in r.iter_content(chunk_size=chunksize): + if chunk: f.write(chunk); f.flush(); + + + + def execute(self): pass + + + def start_progress(self, total = 100): + self._total_processing_count = total + self._processing_initial_time = time.time() + self._processing_count = 1 + + def update_progress(self): + div = int(self._total_processing_count/400) + if div==0: div = 1 + if (self._processing_count % div )==0: + self._processing_last_time = time.time() + total_passed_time = self._processing_last_time - self._processing_initial_time + remaining_time = ( (self._total_processing_count * total_passed_time) / self._processing_count ) - total_passed_time + if remaining_time<0: remaining_time = 0 + time_remaining = datetime(1,1,1) + timedelta(seconds=remaining_time ) + time_elapsed = datetime(1,1,1) + timedelta(seconds=(total_passed_time) ) + + values = ( + time_elapsed.day-1, time_elapsed.hour, time_elapsed.minute, time_elapsed.second, + time_remaining.day-1, time_remaining.hour, time_remaining.minute, time_remaining.second, + (float(self._processing_count)/float(self._total_processing_count))*100.0, self._processing_count, self._total_processing_count, + ) + + print("Elapsed: %d:%d:%d:%d; Remaining: %d:%d:%d:%d; Processed %0.2f %% (%d/%d); | \r" % values) + sys.stdout.flush() + + self._processing_count += 1 + + def end_progress(self): + self._processing_count = self._total_processing_count + self.update_progress() + + + + def __savePID(self, pid): + try: + with open('pending_PID.txt', 'w') as f: + f.write(str(pid)) + f.write('\n') + except (IOError) as e: + raise e + + def __savePID(self, pid): + try: + with open('pending_PID.txt', 'w') as f: + f.write(str(pid)) + f.write('\n') + except (IOError) as e: + raise e + + + def executeCommand(self, cmd, cwd=None, env=None): + if cwd!=None: + currentdirectory = os.getcwd() + os.chdir(cwd) + + print(" ".join(cmd)) + proc = subprocess.Popen(cmd) + + if cwd!=None: os.chdir(currentdirectory) + self.__savePID(proc.pid) + proc.wait() + #(output, error) = proc.communicate() + #if error: print 'error: ', error + #print 'output: ', output + return ''#output + + def exec_terminal_cmd(self, args, **kwargs): + print('TERMINAL <<',' '.join(args) ) + sys.stdout.flush() + proc = subprocess.Popen(args, **kwargs) + self.__savePID(proc.pid) + proc.wait() + sys.stdout.flush() + + + @property + def controls(self): + """ + Return all the form controls from the the module + """ + result = {} + for name, var in vars(self).items(): + if isinstance(var, ControlBase): + var._name = self._controlsPrefix+"-"+name if len(self._controlsPrefix)>0 else name + result[name] = var + return result \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlBase.py b/pyforms/terminal/Controls/ControlBase.py index 4142991..033b160 100755 --- a/pyforms/terminal/Controls/ControlBase.py +++ b/pyforms/terminal/Controls/ControlBase.py @@ -16,12 +16,15 @@ def __init__(self, *args, **kwargs): def init_form(self): pass def load_form(self, data, path=None): - if 'value' in data: self.value = data['value'] + oldvalue = self.value + self.value = data.get('value', None) + if oldvalue!=self.value: self.changed_event() - def save_form(self, data, path=None): - if self.value: data['value'] = self.value - - def value_updated(self, value): pass + def changed_event(self): + """ + Function called when ever the Control value is changed + """ + return True def show(self):pass @@ -55,7 +58,7 @@ def value(self): return self._value def value(self, value): oldvalue = self._value self._value = value - if oldvalue!=value: self.value_updated(value) + if oldvalue!=value: self.changed_event() ############################################################################ @@ -80,27 +83,4 @@ def parent(self, value): self._parent = value - @property - def maxWidth(self): return -1 - - @maxWidth.setter - def maxWidth(self, value): pass - - @property - def minWidth(self): return -1 - - @minWidth.setter - def minWidth(self, value): pass - - - @property - def maxHeight(self): return -1 - - @maxHeight.setter - def maxHeight(self, value): pass - - @property - def minHeight(self): return -1 - - @minHeight.setter - def minHeight(self, value): pass + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlButton.py b/pyforms/terminal/Controls/ControlButton.py index 6e9835d..3349535 100755 --- a/pyforms/terminal/Controls/ControlButton.py +++ b/pyforms/terminal/Controls/ControlButton.py @@ -2,9 +2,16 @@ class ControlButton(ControlBase): + def __init__(self, *args, **kwargs): + super(ControlButton, self).__init__(*args, **kwargs) + self.checked = False + @property def value(self): return None @value.setter def value(self, value): self._value = value + + + \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlCheckBoxList.py b/pyforms/terminal/Controls/ControlCheckBoxList.py index 8033cff..4b66268 100755 --- a/pyforms/terminal/Controls/ControlCheckBoxList.py +++ b/pyforms/terminal/Controls/ControlCheckBoxList.py @@ -6,7 +6,8 @@ def __init__(self, *args, **kwargs): if 'default' not in kwargs: kwargs['default'] = [] super(ControlCheckBoxList, self).__init__(*args, **kwargs) - + def clear(self): + self._value = [] def __add__(self, val): self._value.append(val) @@ -14,4 +15,41 @@ def __add__(self, val): def __sub__(self, other): self._value.remove(other) - return self \ No newline at end of file + return self + + def load_form(self, data, path=None): + results = data['selected'] + for row in range(self.count): + item = self._value[row][0] + if item != None and str(item) in results: + self._value[row] = [item, True] + else: + self._value[row] = [item, False] + self.changed_event() + + @property + def count(self): + return len(self._value) + + @property + def selected_row_index(self): + return -1 + + @property + def value(self): + results = [] + for item, checked in self._value: + if checked: + results.append(item) + return results + + @value.setter + def value(self, value): + self.clear() + for row in value: self += row + self.changed_event() + + @property + def items(self): + for item, checked in self._value: + yield (item, checked) \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlCombo.py b/pyforms/terminal/Controls/ControlCombo.py index b3cb855..32a81ff 100755 --- a/pyforms/terminal/Controls/ControlCombo.py +++ b/pyforms/terminal/Controls/ControlCombo.py @@ -2,23 +2,21 @@ class ControlCombo(ControlBase): + def __init__(self, *args, **kwargs): + super(ControlCombo, self).__init__(*args, **kwargs) + self._items = None def add_item(self, label, value = None): if self._items==None: self._items={} - self._addingItem = True - #if not (label in self._items.keys()): - # self._form.comboBox.addItem( label ) - - firstValue = False - if self._items=={}: firstValue = True + + first_value = (len(self._items)==0) if value==None: self._items[label] = label else: self._items[label] = value - self._addingItem = False - - if firstValue: self.value = self._items[label] + + if first_value: self.value = self._items[label] def clear(self): @@ -39,7 +37,8 @@ def value(self): return self._value def value(self, value): for key, val in self._items.items(): if value == val: - if self._value!=value: self.value_updated(value) + if self._value!=value: + self.changed_event() self._value = val @property diff --git a/pyforms/terminal/Controls/ControlEmptyWidget.py b/pyforms/terminal/Controls/ControlEmptyWidget.py index 6709038..8490a32 100755 --- a/pyforms/terminal/Controls/ControlEmptyWidget.py +++ b/pyforms/terminal/Controls/ControlEmptyWidget.py @@ -1,5 +1,8 @@ from pyforms.terminal.Controls.ControlBase import ControlBase -class ControlEmptyWidget(ControlBase):pass +class ControlEmptyWidget(ControlBase): - \ No newline at end of file + + def load_form(self, data, path=None): + if 'value' in data and self.value is not None and self.value != '': + self.value.load_form(data['value'], path) \ No newline at end of file diff --git a/pyforms/terminal/Controls/ControlList.py b/pyforms/terminal/Controls/ControlList.py index 991fd60..e3a46a8 100755 --- a/pyforms/terminal/Controls/ControlList.py +++ b/pyforms/terminal/Controls/ControlList.py @@ -5,8 +5,10 @@ """ import logging +from pyforms.terminal.BaseWidget import BaseWidget from pyforms.terminal.Controls.ControlBase import ControlBase + logger = logging.getLogger(__name__) @@ -38,17 +40,20 @@ def save_form(self, data, path=None): return data def load_form(self, data, path=None): - if self.value: - rows = data['value'] - for row in range(len(rows)): - for column in range(len(rows[row])): - v = self.get_value(column, row) + rows = data.get('value') + + if self.value is not None and rows is not None: + for row_index in range(len(self.value)): + for column_index in range(len(self.value[row_index])): + v = self.get_value(column_index, row_index) + if isinstance(v, BaseWidget): - v.load(rows[row][column]) + v.load_form(rows[row_index][column_index], path) else: - self.set_value(column, row, rows[row][column]) - elif 'value' in data.keys(): - self.value = data['value'] + self.value[row_index] = list(self.value[row_index]) + self.value[row_index][column_index] = rows[row_index][column_index] + elif rows is not None: + self.value = rows def __add__(self, other): self._value.append(val) @@ -89,10 +94,10 @@ def __sub__(self, other): """ def set_value(self, column, row, value): - pass + self.value[row][column] = value def get_value(self, column, row): - pass + return self.value[row][column] def resize_rows_contents(self): pass diff --git a/pyforms/terminal/Controls/ControlPlayer.py b/pyforms/terminal/Controls/ControlPlayer.py index 95f3c18..9291012 100755 --- a/pyforms/terminal/Controls/ControlPlayer.py +++ b/pyforms/terminal/Controls/ControlPlayer.py @@ -38,25 +38,25 @@ class ControlPlayer(ControlBase): def process_frame_event(self, frame): pass - def play(): pass + def play(self): pass - def stop(): pass + def stop(self): pass - def refresh(): pass + def refresh(self): pass - def update_frame(): pass + def update_frame(self): pass - def double_click_event(event, x, y): pass + def double_click_event(self, event, x, y): pass - def click_event(event, x, y): pass + def click_event(self, event, x, y): pass - def drag_event(start_point, end_point): pass + def drag_event(self, start_point, end_point): pass - def end_drag_event(start_point, end_point): pass + def end_drag_event(self, start_point, end_point): pass - def key_release_event(event): pass + def key_release_event(self, event): pass - def process_frame_event(frame): pass + def process_frame_event(self, frame): pass def save_Form(self, data): pass @@ -95,6 +95,10 @@ def value(self, value): ControlBase.value.fset(self, cv2.VideoCapture( value['filename'] ) ) if 'position' in value.keys(): self.video_index = int(value['position']) self._filename = value['filename'] + + if isinstance(value, cv2.VideoCapture): + ControlBase.value.fset(self, value ) + self._max = int(self._value.get(7)) else: self._filename = None diff --git a/pyforms/terminal/Controls/ControlProgress.py b/pyforms/terminal/Controls/ControlProgress.py index 16c90fc..9550f25 100755 --- a/pyforms/terminal/Controls/ControlProgress.py +++ b/pyforms/terminal/Controls/ControlProgress.py @@ -16,7 +16,7 @@ def __init__(self, label = "%p%", defaultValue = 0, min = 0, max = 100, helptext def value(self): return self._value @value.setter - def value(self, value): self._value = value + def value(self, value):self._value = value @property def min(self): return diff --git a/pyforms/terminal/Controls/ControlSlider.py b/pyforms/terminal/Controls/ControlSlider.py index 4df2c46..007599d 100755 --- a/pyforms/terminal/Controls/ControlSlider.py +++ b/pyforms/terminal/Controls/ControlSlider.py @@ -2,16 +2,13 @@ class ControlSlider(ControlBase): - _min = 0 - _max = 100 - def __init__(self, label = "", helptext=None, defaultValue = 0, min = 0, max = 100): - self._updateSlider = True - self._min = min - self._max = max + def __init__(self, *args, **kwargs): + self._min = kwargs.get('minimum', 0) + self._max = kwargs.get('maximum', 100) + if 'default' not in kwargs: kwargs['default'] = 0 + ControlBase.__init__(self, *args, **kwargs) - ControlBase.__init__(self, label, defaultValue) - @property def min(self): return self._min diff --git a/pyforms/terminal/appmanager.py b/pyforms/terminal/appmanager.py index 59da37e..7cd5b4c 100755 --- a/pyforms/terminal/appmanager.py +++ b/pyforms/terminal/appmanager.py @@ -1,5 +1,5 @@ from pyforms import BaseWidget -def start_app(AppClass, **kwargs): - app = AppClass(**kwargs) - app.init_form() +def start_app(AppClass, **kwargs): + app = AppClass(**kwargs.get('app_args', {})) + app.init_form() From 3815d6cb66534e676691b2e1c74d17314fa80cb1 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 18 Jan 2018 11:00:01 +0000 Subject: [PATCH 19/66] Fix errors on ControlEventTimeline and ControlBoundingSlider --- build_settings/win/build.bat | 0 pyforms/gui/Controls/ControlBase.py | 0 pyforms/gui/Controls/ControlBoundingSlider.py | 24 +- pyforms/gui/Controls/ControlButton.py | 0 pyforms/gui/Controls/ControlCheckBox.py | 0 pyforms/gui/Controls/ControlCheckBoxList.py | 0 pyforms/gui/Controls/ControlCodeEditor.py | 0 pyforms/gui/Controls/ControlCombo.py | 0 pyforms/gui/Controls/ControlDir.py | 2 + pyforms/gui/Controls/ControlEmptyWidget.py | 0 .../ControlEventTimeline.py | 0 .../ControlEventTimeline/TimelineDelta.py | 0 .../ControlEventTimeline/TimelinePointer.py | 0 .../ControlEventTimeline/TimelineWidget.py | 0 .../graphs_eventsgenerator.py | 159 +++++++------ .../graphs_graph2event.py | 220 +++++++++--------- .../ControlEventsGraph/ControlEventsGraph.py | 0 .../ControlEventsGraph/EventsWidget.py | 0 pyforms/gui/Controls/ControlFile.py | 0 pyforms/gui/Controls/ControlFilesTree.py | 0 pyforms/gui/Controls/ControlImage.py | 0 pyforms/gui/Controls/ControlLabel.py | 0 pyforms/gui/Controls/ControlList.py | 0 .../Controls/ControlPlayer/ControlPlayer.py | 0 pyforms/gui/Controls/ControlPlayer/video.ui | 0 pyforms/gui/Controls/ControlProgress.py | 0 pyforms/gui/Controls/ControlSlider.py | 0 pyforms/gui/Controls/ControlText.py | 0 pyforms/gui/Controls/ControlTextArea.py | 0 pyforms/gui/Controls/ControlVisVis.py | 0 pyforms/gui/Controls/ControlVisVisVolume.py | 0 pyforms/gui/Controls/__init__.py | 0 pyforms/gui/Controls/button.ui | 0 pyforms/gui/Controls/checkbox.ui | 0 pyforms/gui/Controls/dbquery.ui | 0 pyforms/gui/Controls/fileInput.ui | 0 pyforms/gui/Controls/image.ui | 0 pyforms/gui/Controls/list.ui | 0 pyforms/gui/Controls/progressInput.ui | 0 pyforms/gui/Controls/sliderInput.ui | 0 pyforms/gui/Controls/textArea.ui | 0 pyforms/gui/Controls/textInput.ui | 0 pyforms/gui/Controls/tree.ui | 0 pyforms/gui/mainWindow.ui | 0 pyforms/terminal/BaseWidget.py | 0 pyforms/terminal/Controls/ControlBase.py | 0 .../Controls/ControlBoundingSlider.py | 0 pyforms/terminal/Controls/ControlButton.py | 0 .../terminal/Controls/ControlCheckBoxList.py | 0 pyforms/terminal/Controls/ControlCombo.py | 0 .../terminal/Controls/ControlEmptyWidget.py | 0 pyforms/terminal/Controls/ControlFile.py | 0 pyforms/terminal/Controls/ControlImage.py | 0 pyforms/terminal/Controls/ControlLabel.py | 0 pyforms/terminal/Controls/ControlList.py | 0 pyforms/terminal/Controls/ControlPlayer.py | 0 pyforms/terminal/Controls/ControlProgress.py | 0 pyforms/terminal/Controls/ControlSlider.py | 0 pyforms/terminal/Controls/ControlText.py | 0 pyforms/terminal/Controls/ControlTextArea.py | 0 pyforms/terminal/Controls/ControlToolBox.py | 0 pyforms/terminal/Controls/ControlTree.py | 0 pyforms/terminal/appmanager.py | 0 pyforms/utils/BioradWriter.py | 0 pyforms/utils/ImageBlobTools.py | 0 pyforms/utils/__init__.py | 0 pyforms/utils/timeit.py | 0 pyforms/utils/tools.py | 0 68 files changed, 211 insertions(+), 194 deletions(-) mode change 100644 => 100755 build_settings/win/build.bat mode change 100755 => 100644 pyforms/gui/Controls/ControlBase.py mode change 100755 => 100644 pyforms/gui/Controls/ControlBoundingSlider.py mode change 100755 => 100644 pyforms/gui/Controls/ControlButton.py mode change 100755 => 100644 pyforms/gui/Controls/ControlCheckBox.py mode change 100755 => 100644 pyforms/gui/Controls/ControlCheckBoxList.py mode change 100755 => 100644 pyforms/gui/Controls/ControlCodeEditor.py mode change 100755 => 100644 pyforms/gui/Controls/ControlCombo.py mode change 100755 => 100644 pyforms/gui/Controls/ControlDir.py mode change 100755 => 100644 pyforms/gui/Controls/ControlEmptyWidget.py mode change 100755 => 100644 pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py mode change 100755 => 100644 pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py mode change 100755 => 100644 pyforms/gui/Controls/ControlEventTimeline/TimelinePointer.py mode change 100755 => 100644 pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py mode change 100755 => 100644 pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py mode change 100755 => 100644 pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py mode change 100755 => 100644 pyforms/gui/Controls/ControlFile.py mode change 100755 => 100644 pyforms/gui/Controls/ControlFilesTree.py mode change 100755 => 100644 pyforms/gui/Controls/ControlImage.py mode change 100755 => 100644 pyforms/gui/Controls/ControlLabel.py mode change 100755 => 100644 pyforms/gui/Controls/ControlList.py mode change 100755 => 100644 pyforms/gui/Controls/ControlPlayer/ControlPlayer.py mode change 100755 => 100644 pyforms/gui/Controls/ControlPlayer/video.ui mode change 100755 => 100644 pyforms/gui/Controls/ControlProgress.py mode change 100755 => 100644 pyforms/gui/Controls/ControlSlider.py mode change 100755 => 100644 pyforms/gui/Controls/ControlText.py mode change 100755 => 100644 pyforms/gui/Controls/ControlTextArea.py mode change 100755 => 100644 pyforms/gui/Controls/ControlVisVis.py mode change 100755 => 100644 pyforms/gui/Controls/ControlVisVisVolume.py mode change 100755 => 100644 pyforms/gui/Controls/__init__.py mode change 100755 => 100644 pyforms/gui/Controls/button.ui mode change 100755 => 100644 pyforms/gui/Controls/checkbox.ui mode change 100755 => 100644 pyforms/gui/Controls/dbquery.ui mode change 100755 => 100644 pyforms/gui/Controls/fileInput.ui mode change 100755 => 100644 pyforms/gui/Controls/image.ui mode change 100755 => 100644 pyforms/gui/Controls/list.ui mode change 100755 => 100644 pyforms/gui/Controls/progressInput.ui mode change 100755 => 100644 pyforms/gui/Controls/sliderInput.ui mode change 100755 => 100644 pyforms/gui/Controls/textArea.ui mode change 100755 => 100644 pyforms/gui/Controls/textInput.ui mode change 100755 => 100644 pyforms/gui/Controls/tree.ui mode change 100755 => 100644 pyforms/gui/mainWindow.ui mode change 100755 => 100644 pyforms/terminal/BaseWidget.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlBase.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlBoundingSlider.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlButton.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlCheckBoxList.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlCombo.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlEmptyWidget.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlFile.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlImage.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlLabel.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlList.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlPlayer.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlProgress.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlSlider.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlText.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlTextArea.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlToolBox.py mode change 100755 => 100644 pyforms/terminal/Controls/ControlTree.py mode change 100755 => 100644 pyforms/terminal/appmanager.py mode change 100755 => 100644 pyforms/utils/BioradWriter.py mode change 100755 => 100644 pyforms/utils/ImageBlobTools.py mode change 100755 => 100644 pyforms/utils/__init__.py mode change 100755 => 100644 pyforms/utils/timeit.py mode change 100755 => 100644 pyforms/utils/tools.py diff --git a/build_settings/win/build.bat b/build_settings/win/build.bat old mode 100644 new mode 100755 diff --git a/pyforms/gui/Controls/ControlBase.py b/pyforms/gui/Controls/ControlBase.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlBoundingSlider.py b/pyforms/gui/Controls/ControlBoundingSlider.py old mode 100755 new mode 100644 index b7d8c70..6a00005 --- a/pyforms/gui/Controls/ControlBoundingSlider.py +++ b/pyforms/gui/Controls/ControlBoundingSlider.py @@ -19,6 +19,7 @@ def __init__(self, *args, **kwargs): self.setMinimumWidth(30) self.setMaximumWidth(50) + self._step = 0 self._lower = 0 self._higher = 100 self._minVal = 0 @@ -52,7 +53,11 @@ def paintEvent(self, e): draw.setBrush(QtCore.Qt.NoBrush) draw.setPen(QColor(200, 200, 255)) - for i in range(self.height() / 5, (self.height() - self.height() / 5) + 1, self.height() / 5): + b = int(self.height() / 5) + e = int(self.height() - (self.height() / 5) + 1) + s = int(self.height() / 5) + + for i in range( b, e, s ): draw.drawLine(0, i, window_with, i) draw.setBrush(QColor(33, 133, 208)) @@ -250,15 +255,14 @@ def mouseMoveEvent(self, event): class ControlBoundingSlider(ControlBase): - def __init__(self, label="", default=[20, 40], min=0, max=100, horizontal=False, helptext=None, - show_spinboxes=True): - self._horizontal = horizontal - self._show_spinboxes = show_spinboxes - ControlBase.__init__(self, label, default, helptext=helptext) - - self.min = min - self.max = max - self.value = default + def __init__(self, *args, **kwargs): + self._horizontal = kwargs.get('horizontal', True) + self._show_spinboxes = kwargs.get('show_spinboxes', True) + ControlBase.__init__(self, *args, **kwargs) + + self.min = kwargs.get('min', kwargs.get('minimum', 0)) + self.max = kwargs.get('max', kwargs.get('maximum', 100)) + self.value = kwargs.get('default', [10,20]) self.__update() def init_form(self): diff --git a/pyforms/gui/Controls/ControlButton.py b/pyforms/gui/Controls/ControlButton.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlCheckBox.py b/pyforms/gui/Controls/ControlCheckBox.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlCheckBoxList.py b/pyforms/gui/Controls/ControlCheckBoxList.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlCodeEditor.py b/pyforms/gui/Controls/ControlCodeEditor.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlCombo.py b/pyforms/gui/Controls/ControlCombo.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlDir.py b/pyforms/gui/Controls/ControlDir.py old mode 100755 new mode 100644 index b8d1ecd..1212f21 --- a/pyforms/gui/Controls/ControlDir.py +++ b/pyforms/gui/Controls/ControlDir.py @@ -13,10 +13,12 @@ class ControlDir(ControlText): + def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "fileInput.ui") self._form = uic.loadUi(control_path) self._form.label.setText(self._label) + self._form.lineEdit.setText(self._value) def click(self): value = str(QFileDialog.getExistingDirectory(self._form, 'Choose a directory', self.value)) diff --git a/pyforms/gui/Controls/ControlEmptyWidget.py b/pyforms/gui/Controls/ControlEmptyWidget.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py b/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py b/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelinePointer.py b/pyforms/gui/Controls/ControlEventTimeline/TimelinePointer.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py b/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py b/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py index d6edefc..fd47231 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py +++ b/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py @@ -9,120 +9,127 @@ from pyforms.Controls import ControlText from pyforms.Controls import ControlNumber from pyforms.Controls import ControlLabel - +import traceback import time import datetime from pysettings import conf if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QMessageBox + from PyQt5.QtWidgets import QMessageBox else: - from PyQt4.QtGui import QMessageBox + from PyQt4.QtGui import QMessageBox class GraphsEventsGenerator(BaseWidget): - def __init__(self, timeline=None): - super(GraphsEventsGenerator, self).__init__('Apply a function to the graph values', parent_win=timeline) - self.setContentsMargins(10, 10, 10, 10) - self._timeline = timeline + def __init__(self, timeline=None): + super(GraphsEventsGenerator, self).__init__('Apply a function to the graph values', parent_win=timeline) + self.setContentsMargins(10, 10, 10, 10) + self._timeline = timeline - # Definition of the forms fields - self._graphs_list = ControlList('Graphs list (try double click)', readonly=False, select_entire_row=True) - self._equation = ControlTextArea('Equation') - self._graphname = ControlText('Graph name') - self._genevts_btn = ControlButton('Generate graph') + # Definition of the forms fields + self._graphs_list = ControlList('Graphs list (try double click)', readonly=False, select_entire_row=True) + self._equation = ControlTextArea('Equation') + self._graphname = ControlText('Graph name') + self._genevts_btn = ControlButton('Generate graph') - - self._formset = [ - ( - ['_graphs_list'], - '||', - [ - '_graphname', - '_equation', - '_genevts_btn', - ] - ), - ] + + self._formset = [ + ( + ['_graphs_list'], + '||', + [ + '_graphname', + '_equation', + '_genevts_btn', + ] + ), + ] - self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt - self._graphs_list.readonly = True - self._graphs_list.select_entire_row = True - self._genevts_btn.value = self.__generage_events_evt + self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt + self._graphs_list.readonly = True + self._graphs_list.select_entire_row = True + self._genevts_btn.value = self.__generage_events_evt - def __add__(self, other): - self._graphs_list += [other.name] - return self + def __add__(self, other): + self._graphs_list += [other.name] + return self - def __sub__(self, other): - self._graphs_list -= other - return self + def __sub__(self, other): + self._graphs_list -= other + return self - def rename_graph(self, graph_index, newname): - self._graphs_list.set_value(graph_index, 0, newname) + def rename_graph(self, graph_index, newname): + self._graphs_list.set_value(graph_index, 0, newname) - @property - def graphs(self): - return self._timeline._charts + @property + def graphs(self): + return self._timeline._charts - def show(self): - super(GraphsEventsGenerator, self).show() + def show(self): + super(GraphsEventsGenerator, self).show() - if len(self._graphname.value.strip())==0: - self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) + if len(self._graphname.value.strip())==0: + self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) - def __cell_double_clicked_evt(self, row, column): - if len(self._equation.value.strip())==0: - self._equation.value += '[{0}]'.format( self._graphs_list.value[row][column] ) - else: - self._equation.value += ' and [{0}]'.format( self._graphs_list.value[row][column] ) + def __cell_double_clicked_evt(self, row, column): + if len(self._equation.value.strip())==0: + self._equation.value += '[{0}]'.format( self._graphs_list.value[row][column] ) + else: + self._equation.value += ' and [{0}]'.format( self._graphs_list.value[row][column] ) - def __generage_events_evt(self): - if len(self._graphname.value.strip())==0: - QMessageBox.warning( - self, "Attention!", 'The graph name cannot be empty') - return + def __generage_events_evt(self): + if len(self._graphname.value.strip())==0: + QMessageBox.warning( + self, "Attention!", 'The graph name cannot be empty') + return - if len(self._equation.value.strip())==0: - QMessageBox.warning( - self, "Attention!", 'The equation cannot be empty') - return + if len(self._equation.value.strip())==0: + QMessageBox.warning( + self, "Attention!", 'The equation cannot be empty') + return - max_frame = 0 - equation = self._equation.value - for i, values in enumerate(self._graphs_list.value): - graphname = '[{0}]'.format(values[0]) + max_frame = 0 + equation = self._equation.value + for i, values in enumerate(self._graphs_list.value): + graphname = '[{0}]'.format(values[0]) - if graphname in equation: max_frame = max(max_frame, len(self.graphs[i])) + if graphname in equation: max_frame = max(max_frame, len(self.graphs[i])) - equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i) ) - - graphs = self.graphs - data = [] - try: - for i in range(max_frame): - data.append( (i, eval(equation)) ) - self._timeline.add_chart(self._graphname.value, data) + equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i) ) + + graphs = self.graphs + data = [] + try: + for i in range(max_frame): - self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) - except Exception as e: - QMessageBox.warning( self, "Error!", str(e) ) + try: + value = eval(equation) + except: + value = None - + data.append( (i, value) ) + self._timeline.add_chart(self._graphname.value, data) + + self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) + except Exception as e: + traceback.print_exc() + QMessageBox.warning( self, "Error!", str(e) ) + + ################################################################################################################## ################################################################################################################## ################################################################################################################## # Execute the application if __name__ == "__main__": - import pyforms - pyforms.start_app(GraphsEventsGenerator, geometry=(0, 0, 600, 400)) + import pyforms + pyforms.start_app(GraphsEventsGenerator, geometry=(0, 0, 600, 400)) diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py b/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py index afc2793..00228f6 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py +++ b/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py @@ -9,129 +9,133 @@ from pyforms.Controls import ControlText from pyforms.Controls import ControlNumber from pyforms.Controls import ControlLabel - +import traceback import time import datetime from pysettings import conf if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QMessageBox + from PyQt5.QtWidgets import QMessageBox else: - from PyQt4.QtGui import QMessageBox + from PyQt4.QtGui import QMessageBox class Graph2Event(BaseWidget): - def __init__(self, timeline=None): - super(Graph2Event, self).__init__('Graph to event', parent_win=timeline) - self.setContentsMargins(10, 10, 10, 10) - self._timeline = timeline - - # Definition of the forms fields - self._graphs_list = ControlList('Graphs list (try double click)') - self._equation = ControlTextArea('Equation') - self._eventname = ControlText('Event name', 'New event') - self._rownumber = ControlNumber('Row number', 0,0,1000) - self._mindiff = ControlNumber('Minimum of frames', 0, 0, 1000000) - self._genevts_btn = ControlButton('Generate events') - - self._formset = [ - ( - ['_graphs_list'], - '||', - [ - ('_eventname','_rownumber','_mindiff'), - '_equation', - '_genevts_btn', - ] - ), - ] - - self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt - self._graphs_list.readonly = True - self._graphs_list.select_entire_row = True - self._genevts_btn.value = self.__generage_events_evt - - - - def __add__(self, other): - self._graphs_list += [other.name] - return self - - def __sub__(self, other): - self._graphs_list -= other - return self - - def rename_graph(self, graph_index, newname): - self._graphs_list.set_value(graph_index, 0, newname) - - @property - def graphs(self): - return self._timeline._charts - - - def __cell_double_clicked_evt(self, row, column): - if len(self._equation.value.strip())==0: - self._equation.value += '[{0}]'.format( self._graphs_list.value[row][column] ) - else: - self._equation.value += ' and [{0}]'.format( self._graphs_list.value[row][column] ) - - - def __generage_events_evt(self): - if len(self._eventname.value.strip())==0: - QMessageBox.warning( - self, "Attention!", 'The event name cannot be empty') - return - - if len(self._equation.value.strip())==0: - QMessageBox.warning( - self, "Attention!", 'The equation cannot be empty') - return - - max_frame = 0 - equation = self._equation.value - for i, values in enumerate(self._graphs_list.value): - graphname = '[{0}]'.format(values[0]) - - if graphname in equation: max_frame = max(max_frame, len(self.graphs[i])) - - equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i) ) - - graphs = self.graphs - - last_index = None - last_value = False - - try: - for i in range(max_frame): - value = eval(equation) - - if not last_value and bool(value): - last_index = i - last_value = True - - if last_value and not bool(value): - if (i-1-last_index)>=self._mindiff.value: - self._timeline.addPeriod([last_index, i-1, self._eventname.value], int(self._rownumber.value) ) - last_value = False - last_index = None - - if last_value and (max_frame-last_index)>=self._mindiff.value: - self._timeline.addPeriod([last_index, max_frame, self._eventname.value], int(self._rownumber.value) ) - except Exception as e: - QMessageBox.warning( self, "Error!", str(e) ) - - - self._timeline.repaint() - - + def __init__(self, timeline=None): + super(Graph2Event, self).__init__('Graph to event', parent_win=timeline) + self.setContentsMargins(10, 10, 10, 10) + self._timeline = timeline + + # Definition of the forms fields + self._graphs_list = ControlList('Graphs list (try double click)') + self._equation = ControlTextArea('Equation') + self._eventname = ControlText('Event name', 'New event') + self._rownumber = ControlNumber('Row number', 0,0,1000) + self._mindiff = ControlNumber('Minimum of frames', 0, 0, 1000000) + self._genevts_btn = ControlButton('Generate events') + + self._formset = [ + ( + ['_graphs_list'], + '||', + [ + ('_eventname','_rownumber','_mindiff'), + '_equation', + '_genevts_btn', + ] + ), + ] + + self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt + self._graphs_list.readonly = True + self._graphs_list.select_entire_row = True + self._genevts_btn.value = self.__generage_events_evt + + + + def __add__(self, other): + self._graphs_list += [other.name] + return self + + def __sub__(self, other): + self._graphs_list -= other + return self + + def rename_graph(self, graph_index, newname): + self._graphs_list.set_value(graph_index, 0, newname) + + @property + def graphs(self): + return self._timeline._charts + + + def __cell_double_clicked_evt(self, row, column): + if len(self._equation.value.strip())==0: + self._equation.value += '[{0}]'.format( self._graphs_list.value[row][column] ) + else: + self._equation.value += ' and [{0}]'.format( self._graphs_list.value[row][column] ) + + + def __generage_events_evt(self): + if len(self._eventname.value.strip())==0: + QMessageBox.warning( + self, "Attention!", 'The event name cannot be empty') + return + + if len(self._equation.value.strip())==0: + QMessageBox.warning( + self, "Attention!", 'The equation cannot be empty') + return + + max_frame = 0 + equation = self._equation.value + for i, values in enumerate(self._graphs_list.value): + graphname = '[{0}]'.format(values[0]) + + if graphname in equation: max_frame = max(max_frame, len(self.graphs[i])) + + equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i) ) + + graphs = self.graphs + + last_index = None + last_value = False + + try: + for i in range(max_frame): + try: + value = eval(equation) + except: + value = False + + if not last_value and bool(value): + last_index = i + last_value = True + + if last_value and not bool(value): + if (i-1-last_index)>=self._mindiff.value: + self._timeline.addPeriod([last_index, i-1, self._eventname.value], int(self._rownumber.value) ) + last_value = False + last_index = None + + if last_value and (max_frame-last_index)>=self._mindiff.value: + self._timeline.addPeriod([last_index, max_frame, self._eventname.value], int(self._rownumber.value) ) + except Exception as e: + traceback.print_exc() + QMessageBox.warning( self, "Error!", str(e) ) + + + self._timeline.repaint() + + ################################################################################################################## ################################################################################################################## ################################################################################################################## # Execute the application if __name__ == "__main__": - import pyforms - pyforms.start_app(Graph2Event, geometry=(0, 0, 600, 400)) + import pyforms + pyforms.start_app(Graph2Event, geometry=(0, 0, 600, 400)) diff --git a/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py b/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py b/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlFile.py b/pyforms/gui/Controls/ControlFile.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlFilesTree.py b/pyforms/gui/Controls/ControlFilesTree.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlImage.py b/pyforms/gui/Controls/ControlImage.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlLabel.py b/pyforms/gui/Controls/ControlLabel.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/Controls/ControlList.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py b/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlPlayer/video.ui b/pyforms/gui/Controls/ControlPlayer/video.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlProgress.py b/pyforms/gui/Controls/ControlProgress.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlSlider.py b/pyforms/gui/Controls/ControlSlider.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlText.py b/pyforms/gui/Controls/ControlText.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlTextArea.py b/pyforms/gui/Controls/ControlTextArea.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlVisVis.py b/pyforms/gui/Controls/ControlVisVis.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/ControlVisVisVolume.py b/pyforms/gui/Controls/ControlVisVisVolume.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/__init__.py b/pyforms/gui/Controls/__init__.py old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/button.ui b/pyforms/gui/Controls/button.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/checkbox.ui b/pyforms/gui/Controls/checkbox.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/dbquery.ui b/pyforms/gui/Controls/dbquery.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/fileInput.ui b/pyforms/gui/Controls/fileInput.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/image.ui b/pyforms/gui/Controls/image.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/list.ui b/pyforms/gui/Controls/list.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/progressInput.ui b/pyforms/gui/Controls/progressInput.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/sliderInput.ui b/pyforms/gui/Controls/sliderInput.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/textArea.ui b/pyforms/gui/Controls/textArea.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/textInput.ui b/pyforms/gui/Controls/textInput.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/Controls/tree.ui b/pyforms/gui/Controls/tree.ui old mode 100755 new mode 100644 diff --git a/pyforms/gui/mainWindow.ui b/pyforms/gui/mainWindow.ui old mode 100755 new mode 100644 diff --git a/pyforms/terminal/BaseWidget.py b/pyforms/terminal/BaseWidget.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlBase.py b/pyforms/terminal/Controls/ControlBase.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlBoundingSlider.py b/pyforms/terminal/Controls/ControlBoundingSlider.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlButton.py b/pyforms/terminal/Controls/ControlButton.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlCheckBoxList.py b/pyforms/terminal/Controls/ControlCheckBoxList.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlCombo.py b/pyforms/terminal/Controls/ControlCombo.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlEmptyWidget.py b/pyforms/terminal/Controls/ControlEmptyWidget.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlFile.py b/pyforms/terminal/Controls/ControlFile.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlImage.py b/pyforms/terminal/Controls/ControlImage.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlLabel.py b/pyforms/terminal/Controls/ControlLabel.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlList.py b/pyforms/terminal/Controls/ControlList.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlPlayer.py b/pyforms/terminal/Controls/ControlPlayer.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlProgress.py b/pyforms/terminal/Controls/ControlProgress.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlSlider.py b/pyforms/terminal/Controls/ControlSlider.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlText.py b/pyforms/terminal/Controls/ControlText.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlTextArea.py b/pyforms/terminal/Controls/ControlTextArea.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlToolBox.py b/pyforms/terminal/Controls/ControlToolBox.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/Controls/ControlTree.py b/pyforms/terminal/Controls/ControlTree.py old mode 100755 new mode 100644 diff --git a/pyforms/terminal/appmanager.py b/pyforms/terminal/appmanager.py old mode 100755 new mode 100644 diff --git a/pyforms/utils/BioradWriter.py b/pyforms/utils/BioradWriter.py old mode 100755 new mode 100644 diff --git a/pyforms/utils/ImageBlobTools.py b/pyforms/utils/ImageBlobTools.py old mode 100755 new mode 100644 diff --git a/pyforms/utils/__init__.py b/pyforms/utils/__init__.py old mode 100755 new mode 100644 diff --git a/pyforms/utils/timeit.py b/pyforms/utils/timeit.py old mode 100755 new mode 100644 diff --git a/pyforms/utils/tools.py b/pyforms/utils/tools.py old mode 100755 new mode 100644 From 2516e5fb74be6669306c892d3ef47c3a23d934a6 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 23 Jan 2018 23:46:49 +0000 Subject: [PATCH 20/66] Rename some modules; converted averything to any qt --- docs/getting-started/multiple-windows.md | 10 +- docs/getting-started/run-terminal.md | 4 +- pyforms/Controls.py | 149 +++++------ pyforms/__init__.py | 31 +-- pyforms/dialogs.py | 2 +- pyforms/gui/.DS_Store | Bin 0 -> 6148 bytes pyforms/gui/BaseWidget.py | 103 ++----- pyforms/gui/Controls/ControlBoundingSlider.py | 6 +- pyforms/gui/Controls/ControlButton.py | 2 +- pyforms/gui/Controls/ControlCheckBox.py | 2 +- pyforms/gui/Controls/ControlCheckBoxList.py | 2 +- pyforms/gui/Controls/ControlCodeEditor.py | 4 +- pyforms/gui/Controls/ControlCombo.py | 2 +- pyforms/gui/Controls/ControlDir.py | 2 +- pyforms/gui/Controls/ControlDockWidget.py | 2 +- pyforms/gui/Controls/ControlEmptyWidget.py | 12 +- pyforms/gui/Controls/ControlFile.py | 9 +- pyforms/gui/Controls/ControlFilesTree.py | 2 +- pyforms/gui/Controls/ControlImage.py | 10 +- pyforms/gui/Controls/ControlLabel.py | 4 +- pyforms/gui/Controls/ControlList.py | 6 +- pyforms/gui/Controls/ControlMatplotlib.py | 2 +- pyforms/gui/Controls/ControlMdiArea.py | 2 +- pyforms/gui/Controls/ControlNumber.py | 2 +- pyforms/gui/Controls/ControlOpenGL.py | 10 +- .../Controls/ControlPlayer/VideoGLWidget.py | 18 -- pyforms/gui/Controls/ControlProgress.py | 16 +- pyforms/gui/Controls/ControlSlider.py | 11 +- pyforms/gui/Controls/ControlText.py | 14 +- pyforms/gui/Controls/ControlTextArea.py | 11 +- pyforms/gui/Controls/ControlToolBox.py | 26 +- pyforms/gui/Controls/ControlTree.py | 17 +- pyforms/gui/Controls/ControlTreeView.py | 13 +- pyforms/gui/Controls/ControlVisVis.py | 20 +- pyforms/gui/Controls/ControlVisVisVolume.py | 22 +- pyforms/gui/Controls/ControlWeb.py | 13 +- .../ControlEventTimeline.py | 40 ++- .../TimelineChart.py | 10 +- .../TimelineDelta.py | 25 +- .../TimelinePointer.py | 13 +- .../TimelinePopupWindow.py | 18 +- .../TimelinePopupWindow.ui | 0 .../TimelineWidget.py | 24 +- .../Track.py | 13 +- .../__init__.py | 2 +- .../graphs_eventsgenerator.py | 34 +-- .../graphs_graph2event.py | 34 +-- .../graphs_properties.py | 14 +- .../import_window.py | 12 +- .../ControlEventsGraph.py | 21 +- .../Event.py | 11 +- .../EventsWidget.py | 23 +- .../Pointer.py | 12 +- .../Track.py | 10 +- .../__init__.py | 2 +- .../AbstractGLWidget.py | 43 ++- .../ControlPlayer.py | 59 ++-- .../Controls/control_player/VideoGLWidget.py | 11 + .../VideoQt5GLWidget.py | 8 +- .../__init__.py | 0 .../video.ui | 0 pyforms/gui/Controls/dbquery.ui | 52 ---- pyforms/gui/Controls/list_with_headers.ui | 147 ---------- pyforms/gui/Controls/table.ui | 113 -------- pyforms/gui/appmanager.py | 253 +++++++++++++----- pyforms/gui/dialogs/csv_parser.py | 10 +- pyforms/gui/dialogs/generic_csv_parser.py | 10 +- pyforms/gui/mainWindow.ui | 76 ------ pyforms/gui/settings.py | 14 +- pyforms/gui/standaloneManager.py | 218 --------------- pyforms/settings.py | 11 +- pyforms/terminal/BaseWidget.py | 2 +- setup.py | 19 +- .../__init__.py | 10 +- .../SimpleExample1/__init__.py | 6 +- .../SimpleExample2/__init__.py | 4 +- .../SimpleExample3/__init__.py | 4 +- .../SimpleExample4/__init__.py | 4 +- .../SimpleExample5/__init__.py | 4 +- .../SimpleExample6/__init__.py | 4 +- tutorials/2.ControlsExamples/__init__.py | 40 +-- tutorials/3.CodeOrganization/PeopleWindow.py | 2 +- tutorials/3.CodeOrganization/PersonWindow.py | 4 +- tutorials/3.CodeOrganization/__init__.py | 6 +- tutorials/4.MdiApplication/Core/BaseWindow.py | 8 +- .../Core/Controllers/ProjectTree.py | 6 +- .../4.MdiApplication/Core/SimpleExample1.py | 4 +- tutorials/Controls4Docs/__init__.py | 2 +- 88 files changed, 614 insertions(+), 1419 deletions(-) create mode 100644 pyforms/gui/.DS_Store delete mode 100644 pyforms/gui/Controls/ControlPlayer/VideoGLWidget.py rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/ControlEventTimeline.py (93%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/TimelineChart.py (97%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/TimelineDelta.py (94%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/TimelinePointer.py (91%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/TimelinePopupWindow.py (93%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/TimelinePopupWindow.ui (100%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/TimelineWidget.py (96%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/Track.py (92%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/__init__.py (89%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/graphs_eventsgenerator.py (83%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/graphs_graph2event.py (84%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/graphs_properties.py (95%) rename pyforms/gui/Controls/{ControlEventTimeline => control_event_timeline}/import_window.py (95%) rename pyforms/gui/Controls/{ControlEventsGraph => control_events_graph}/ControlEventsGraph.py (89%) rename pyforms/gui/Controls/{ControlEventsGraph => control_events_graph}/Event.py (92%) rename pyforms/gui/Controls/{ControlEventsGraph => control_events_graph}/EventsWidget.py (94%) rename pyforms/gui/Controls/{ControlEventsGraph => control_events_graph}/Pointer.py (91%) rename pyforms/gui/Controls/{ControlEventsGraph => control_events_graph}/Track.py (94%) rename pyforms/gui/Controls/{ControlEventsGraph => control_events_graph}/__init__.py (88%) rename pyforms/gui/Controls/{ControlPlayer => control_player}/AbstractGLWidget.py (95%) rename pyforms/gui/Controls/{ControlPlayer => control_player}/ControlPlayer.py (91%) create mode 100644 pyforms/gui/Controls/control_player/VideoGLWidget.py rename pyforms/gui/Controls/{ControlPlayer => control_player}/VideoQt5GLWidget.py (88%) rename pyforms/gui/Controls/{ControlPlayer => control_player}/__init__.py (100%) rename pyforms/gui/Controls/{ControlPlayer => control_player}/video.ui (100%) delete mode 100755 pyforms/gui/Controls/dbquery.ui delete mode 100644 pyforms/gui/Controls/list_with_headers.ui delete mode 100644 pyforms/gui/Controls/table.ui delete mode 100755 pyforms/gui/mainWindow.ui delete mode 100644 pyforms/gui/standaloneManager.py diff --git a/docs/getting-started/multiple-windows.md b/docs/getting-started/multiple-windows.md index 7212031..12c124a 100644 --- a/docs/getting-started/multiple-windows.md +++ b/docs/getting-started/multiple-windows.md @@ -67,8 +67,8 @@ This window should inherit from the BaseWidget and Person classes. ```python import pyforms from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton from Person import Person class PersonWindow(Person, BaseWidget): @@ -111,7 +111,7 @@ This window should inherit from the BaseWidget and People classes. ```python import pyforms from pyforms import BaseWidget -from pyforms.Controls import ControlList +from pyforms.controls import ControlList from People import People from PersonWindow import PersonWindow from AddMenuFuntionality import AddMenuFuntionality @@ -179,7 +179,7 @@ The application will look like: Instead of opening a new window everytime we want to add a new Person, we will change the Application to open the PersonWindow inside the PeopleWindow. For this we will use the ControlEmptyWidget. ```python -from pyforms.Controls import ControlEmptyWidget +from pyforms.controls import ControlEmptyWidget ... def __init__(self): @@ -205,7 +205,7 @@ from pyforms.Controls import ControlEmptyWidget A DockWidget works like the EmptyWidget but can be detached or moved around the sides of the main Window. ```python -from pyforms.Controls import ControlDockWidget +from pyforms.controls import ControlDockWidget ... def __init__(self): diff --git a/docs/getting-started/run-terminal.md b/docs/getting-started/run-terminal.md index 1d89a8a..38d7fd3 100644 --- a/docs/getting-started/run-terminal.md +++ b/docs/getting-started/run-terminal.md @@ -7,8 +7,8 @@ The next code produces this Window: ```python import pyforms from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton from Person import Person class PersonWindow(Person, BaseWidget): diff --git a/pyforms/Controls.py b/pyforms/Controls.py index 9c33ed1..67e6680 100644 --- a/pyforms/Controls.py +++ b/pyforms/Controls.py @@ -1,108 +1,105 @@ from pyforms import conf -import logging, traceback -logger = logging.getLogger(__file__) +if conf.PYFORMS_MODE=='GUI': + import logging, traceback; logger=logging.getLogger(__file__) -if conf.PYFORMS_MODE in ['GUI', 'GUI-OPENCSP']: - - from pyforms.gui.Controls.ControlBase import ControlBase - from pyforms.gui.Controls.ControlText import ControlText - from pyforms.gui.Controls.ControlBoundingSlider import ControlBoundingSlider - from pyforms.gui.Controls.ControlButton import ControlButton - from pyforms.gui.Controls.ControlCheckBoxList import ControlCheckBoxList - from pyforms.gui.Controls.ControlCheckBox import ControlCheckBox - from pyforms.gui.Controls.ControlCombo import ControlCombo - from pyforms.gui.Controls.ControlDir import ControlDir - from pyforms.gui.Controls.ControlDockWidget import ControlDockWidget - from pyforms.gui.Controls.ControlEmptyWidget import ControlEmptyWidget - from pyforms.gui.Controls.ControlFile import ControlFile - from pyforms.gui.Controls.ControlFilesTree import ControlFilesTree - from pyforms.gui.Controls.ControlLabel import ControlLabel - from pyforms.gui.Controls.ControlList import ControlList - from pyforms.gui.Controls.ControlMdiArea import ControlMdiArea - from pyforms.gui.Controls.ControlNumber import ControlNumber + from pyforms.gui.controls.ControlBase import ControlBase + from pyforms.gui.controls.ControlText import ControlText + from pyforms.gui.controls.ControlBoundingSlider import ControlBoundingSlider + from pyforms.gui.controls.ControlButton import ControlButton + from pyforms.gui.controls.ControlCheckBoxList import ControlCheckBoxList + from pyforms.gui.controls.ControlCheckBox import ControlCheckBox + from pyforms.gui.controls.ControlCombo import ControlCombo + from pyforms.gui.controls.ControlDir import ControlDir + from pyforms.gui.controls.ControlDockWidget import ControlDockWidget + from pyforms.gui.controls.ControlEmptyWidget import ControlEmptyWidget + from pyforms.gui.controls.ControlFile import ControlFile + from pyforms.gui.controls.ControlFilesTree import ControlFilesTree + from pyforms.gui.controls.ControlLabel import ControlLabel + from pyforms.gui.controls.ControlList import ControlList + from pyforms.gui.controls.ControlMdiArea import ControlMdiArea + from pyforms.gui.controls.ControlNumber import ControlNumber + from pyforms.gui.controls.ControlProgress import ControlProgress + from pyforms.gui.controls.ControlSlider import ControlSlider + from pyforms.gui.controls.ControlTextArea import ControlTextArea + from pyforms.gui.controls.ControlToolBox import ControlToolBox + from pyforms.gui.controls.ControlTree import ControlTree + from pyforms.gui.controls.ControlTreeView import ControlTreeView + from pyforms.gui.controls.control_event_timeline.ControlEventTimeline import ControlEventTimeline + from pyforms.gui.controls.control_events_graph.ControlEventsGraph import ControlEventsGraph if conf.PYFORMS_MATPLOTLIB_ENABLED: try: - from pyforms.gui.Controls.ControlMatplotlib import ControlMatplotlib + from pyforms.gui.controls.ControlMatplotlib import ControlMatplotlib except: logger.warning("Matplot lib not installed or not working properly") logger.warning(traceback.format_exc()) if conf.PYFORMS_WEB_ENABLED: try: - from pyforms.gui.Controls.ControlWeb import ControlWeb + from pyforms.gui.controls.ControlWeb import ControlWeb except: logger.warning("QtWebKit lib not installed or not working properly") logger.warning(traceback.format_exc()) if conf.PYFORMS_GL_ENABLED: try: - from pyforms.gui.Controls.ControlOpenGL import ControlOpenGL - from pyforms.gui.Controls.ControlImage import ControlImage - from pyforms.gui.Controls.ControlPlayer.ControlPlayer import ControlPlayer + from pyforms.gui.controls.ControlOpenGL import ControlOpenGL + from pyforms.gui.controls.ControlImage import ControlImage + from pyforms.gui.controls.control_player.ControlPlayer import ControlPlayer except: logger.warning("GL widgets or Opencv not installed") logger.warning(traceback.format_exc()) - - from pyforms.gui.Controls.ControlProgress import ControlProgress - from pyforms.gui.Controls.ControlSlider import ControlSlider - from pyforms.gui.Controls.ControlTextArea import ControlTextArea - from pyforms.gui.Controls.ControlToolBox import ControlToolBox - from pyforms.gui.Controls.ControlTree import ControlTree - from pyforms.gui.Controls.ControlTreeView import ControlTreeView - + if conf.PYFORMS_VISVIS_ENABLED: try: - from pyforms.gui.Controls.ControlVisVis import ControlVisVis - from pyforms.gui.Controls.ControlVisVisVolume import ControlVisVisVolume + from pyforms.gui.controls.ControlVisVis import ControlVisVis + from pyforms.gui.controls.ControlVisVisVolume import ControlVisVisVolume except: logger.warning("VisVis not installed") - #logger.warning(traceback.format_exc()) - - from pyforms.gui.Controls.ControlEventTimeline.ControlEventTimeline import ControlEventTimeline - from pyforms.gui.Controls.ControlEventsGraph.ControlEventsGraph import ControlEventsGraph + logger.warning(traceback.format_exc()) - try: - from pyforms.gui.Controls.ControlCodeEditor import ControlCodeEditor - except: - logger.debug("QScintilla2 not installed") - logger.debug(traceback.format_exc()) + if conf.PYFORMS_QSCINTILLA_ENABLED: + try: + from pyforms.gui.controls.ControlCodeEditor import ControlCodeEditor + except: + logger.debug("QScintilla2 not installed") + logger.debug(traceback.format_exc()) -elif conf.PYFORMS_MODE in ['TERMINAL']: +elif conf.PYFORMS_MODE=='TERMINAL': - from pyforms.terminal.Controls.ControlBase import ControlBase - from pyforms.terminal.Controls.ControlText import ControlText - from pyforms.terminal.Controls.ControlButton import ControlButton - from pyforms.terminal.Controls.ControlCheckBox import ControlCheckBox - from pyforms.terminal.Controls.ControlCombo import ControlCombo - from pyforms.terminal.Controls.ControlFile import ControlFile - from pyforms.terminal.Controls.ControlDir import ControlDir - from pyforms.terminal.Controls.ControlImage import ControlImage - from pyforms.terminal.Controls.ControlSlider import ControlSlider - from pyforms.terminal.Controls.ControlPlayer import ControlPlayer - from pyforms.terminal.Controls.ControlNumber import ControlNumber - from pyforms.terminal.Controls.ControlProgress import ControlProgress + from pyforms.terminal.controls.ControlBase import ControlBase + from pyforms.terminal.controls.ControlText import ControlText + from pyforms.terminal.controls.ControlButton import ControlButton + from pyforms.terminal.controls.ControlCheckBox import ControlCheckBox + from pyforms.terminal.controls.ControlCombo import ControlCombo + from pyforms.terminal.controls.ControlFile import ControlFile + from pyforms.terminal.controls.ControlDir import ControlDir + from pyforms.terminal.controls.ControlImage import ControlImage + from pyforms.terminal.controls.ControlSlider import ControlSlider + from pyforms.terminal.controls.ControlPlayer import ControlPlayer + from pyforms.terminal.controls.ControlNumber import ControlNumber + from pyforms.terminal.controls.ControlProgress import ControlProgress -elif conf.PYFORMS_MODE in ['WEB']: +elif conf.PYFORMS_MODE=='WEB': - from pyforms_web.web.Controls.ControlBase import ControlBase - from pyforms_web.web.Controls.ControlText import ControlText + from pyforms_web.web.Controls.ControlBase import ControlBase + from pyforms_web.web.Controls.ControlText import ControlText from pyforms_web.web.Controls.ControlBoundingSlider import ControlBoundingSlider - from pyforms_web.web.Controls.ControlDate import ControlDate - from pyforms_web.web.Controls.ControlButton import ControlButton - from pyforms_web.web.Controls.ControlCheckBox import ControlCheckBox - from pyforms_web.web.Controls.ControlCombo import ControlCombo - from pyforms_web.web.Controls.ControlDir import ControlDir - from pyforms_web.web.Controls.ControlFile import ControlFile - from pyforms_web.web.Controls.ControlImage import ControlImage - from pyforms_web.web.Controls.ControlSlider import ControlSlider - from pyforms_web.web.Controls.ControlPlayer import ControlPlayer - from pyforms_web.web.Controls.ControlProgress import ControlProgress - from pyforms_web.web.Controls.ControlVisVis import ControlVisVis - from pyforms_web.web.Controls.ControlList import ControlList - from pyforms_web.web.Controls.ControlLabel import ControlLabel - from pyforms_web.web.Controls.ControlTimeout import ControlTimeout - from pyforms_web.web.Controls.ControlEmptyWidget import ControlEmptyWidget - from pyforms_web.web.Controls.ControlWorkflow import ControlWorkflow + from pyforms_web.web.Controls.ControlDate import ControlDate + from pyforms_web.web.Controls.ControlButton import ControlButton + from pyforms_web.web.Controls.ControlCheckBox import ControlCheckBox + from pyforms_web.web.Controls.ControlCombo import ControlCombo + from pyforms_web.web.Controls.ControlDir import ControlDir + from pyforms_web.web.Controls.ControlFile import ControlFile + from pyforms_web.web.Controls.ControlImage import ControlImage + from pyforms_web.web.Controls.ControlSlider import ControlSlider + from pyforms_web.web.Controls.ControlPlayer import ControlPlayer + from pyforms_web.web.Controls.ControlProgress import ControlProgress + from pyforms_web.web.Controls.ControlVisVis import ControlVisVis + from pyforms_web.web.Controls.ControlList import ControlList + from pyforms_web.web.Controls.ControlLabel import ControlLabel + from pyforms_web.web.Controls.ControlTimeout import ControlTimeout + from pyforms_web.web.Controls.ControlEmptyWidget import ControlEmptyWidget + from pyforms_web.web.Controls.ControlWorkflow import ControlWorkflow diff --git a/pyforms/__init__.py b/pyforms/__init__.py index 35fbb35..5b0bd74 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -1,35 +1,28 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import logging -import loggingbootstrap from pysettings import conf conf += 'pyforms.settings' -__author__ = "Ricardo Ribeiro" -__credits__ = ["Ricardo Ribeiro"] -__license__ = "MIT" -__version__ = '2.1.0' -__maintainer__ = ["Ricardo Ribeiro", "Carlos Mão de Ferro"] -__email__ = ["ricardojvr@gmail.com", "cajomferro@gmail.com"] -__status__ = "Production" +__author__ = "Ricardo Ribeiro" +__credits__ = ["Ricardo Ribeiro"] +__license__ = "MIT" +__version__ = '3.0.0' +__maintainer__ = ["Ricardo Ribeiro", "Carlos Mão de Ferro"] +__email__ = ["ricardojvr@gmail.com", "cajomferro@gmail.com"] +__status__ = "Production" -logger = logging.getLogger(__name__) if conf.PYFORMS_MODE in ['GUI', 'GUI-OPENCSP']: - from pyforms.gui import Controls - from pyforms.gui.BaseWidget import BaseWidget - - if conf.PYFORMS_MODE in ['GUI-OPENCSP']: - from pyforms.gui.appmanager import start_app - else: - from pyforms.gui.standaloneManager import start_app + from pyforms.gui import controls + from pyforms.gui.basewidget import BaseWidget + from pyforms.gui.appmanager import start_app elif conf.PYFORMS_MODE in ['TERMINAL']: - from pyforms.terminal import Controls - from pyforms.terminal.BaseWidget import BaseWidget + from pyforms.terminal import controls + from pyforms.terminal.basewidget import BaseWidget from pyforms.terminal.appmanager import start_app diff --git a/pyforms/dialogs.py b/pyforms/dialogs.py index 84239d7..fce28a0 100644 --- a/pyforms/dialogs.py +++ b/pyforms/dialogs.py @@ -1,4 +1,4 @@ from pyforms import conf -if conf.PYFORMS_MODE in ['GUI','GUI-OPENCSP']: +if conf.PYFORMS_MODE=='GUI': from pyforms.gui.dialogs.csv_parser import CsvParserDialog \ No newline at end of file diff --git a/pyforms/gui/.DS_Store b/pyforms/gui/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e4da2b0b51e9fdf6c42dc9ba10bb4f9e6691f1ea GIT binary patch literal 6148 zcmeHKJE{Uf5bRci1rtNVxq>$s#CL+dfS_O^E9iU18+opGG^;;|vYH4cQVrcT)6+G} zR;f zw~Kq96Pcv~RDcRl0V+TR-crDNFRYmcGExC5Km~3J*!Q8p4QpZ_=${S*9|3?9q}{Og zSprxr0j!CAATlrwDln*;BZdYY`I2=tu@4NoXbvBmPu84J)Sr&~i;s*SywidF88BUFRN&JJTmh4g70mzu literal 0 HcmV?d00001 diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/BaseWidget.py index 49678a1..ea2606e 100644 --- a/pyforms/gui/BaseWidget.py +++ b/pyforms/gui/BaseWidget.py @@ -1,45 +1,23 @@ #!/usr/bin/python # -*- coding: utf-8 -*- - -import os import json -import subprocess -import time, sys -from datetime import datetime, timedelta - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QFrame - from PyQt5.QtWidgets import QVBoxLayout - from PyQt5.QtWidgets import QTabWidget - from PyQt5.QtWidgets import QSplitter - from PyQt5.QtWidgets import QHBoxLayout - from PyQt5.QtWidgets import QSpacerItem - from PyQt5.QtWidgets import QSizePolicy - from PyQt5.QtWidgets import QLabel - from PyQt5.QtGui import QFont - from PyQt5.QtWidgets import QFileDialog - from PyQt5.QtWidgets import QApplication - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QFrame - from PyQt4.QtGui import QVBoxLayout - from PyQt4.QtGui import QTabWidget - from PyQt4.QtGui import QSplitter - from PyQt4.QtGui import QHBoxLayout - from PyQt4.QtGui import QSpacerItem - from PyQt4.QtGui import QSizePolicy - from PyQt4.QtGui import QLabel - from PyQt4.QtGui import QFont - from PyQt4.QtGui import QFileDialog - from PyQt4.QtGui import QApplication - from PyQt4 import QtCore - -from pyforms.gui.Controls.ControlBase import ControlBase -from pyforms.gui.Controls.ControlProgress import ControlProgress + +from pysettings import conf +from AnyQt.QtWidgets import QFrame +from AnyQt.QtWidgets import QVBoxLayout +from AnyQt.QtWidgets import QTabWidget +from AnyQt.QtWidgets import QSplitter +from AnyQt.QtWidgets import QHBoxLayout +from AnyQt.QtWidgets import QSpacerItem +from AnyQt.QtWidgets import QSizePolicy +from AnyQt.QtWidgets import QLabel +from AnyQt.QtGui import QFont +from AnyQt.QtWidgets import QFileDialog +from AnyQt.QtWidgets import QApplication +from AnyQt import QtCore, _api + +from pyforms.gui.controls.ControlBase import ControlBase class BaseWidget(QFrame): @@ -58,13 +36,12 @@ def __init__(self, title='Untitled', parent_win=None, win_flag=None): layout = QVBoxLayout() self.setLayout(layout) - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) self.title = title - self.has_progress = False self._mainmenu = [] self._splitters = [] @@ -86,12 +63,7 @@ def init_form(self): """ if not self._formLoaded: - if self.has_progress: - self._progress = ControlProgress("Progress", 0, 100) - self._progress.hide() - if self._formset != None: - self._formset += ['_progress'] - + if self._formset is not None: control = self.generate_panel(self._formset) self.layout().addWidget(control) @@ -104,9 +76,9 @@ def init_form(self): self._formLoaded = True def set_margin(self, margin): - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: self.layout().setContentsMargins(margin,margin,margin,margin) - else: + elif _api.USED_API == _api.QT_API_PYQT4: self.layout().setMargin(margin) @@ -318,9 +290,9 @@ def generate_panel(self, formset): param.name = row layout.addWidget(param.form) - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) control.setLayout(layout) @@ -448,34 +420,7 @@ def uid(self): def uid(self, value): self._uid = value - @property - def max_progress(self): - return self._progress.max - - @max_progress.setter - def max_progress(self, value): - self._progress.max = value - - @property - def min_progress(self): - return self._progress.min - - @min_progress.setter - def min_progress(self, value): - self._progress.min = value - - @property - def progress(self): - return self._progress.value - - @progress.setter - def progress(self, value): - self._progress.value = value - QApplication.processEvents() - - if value == self.max_progress: self._progress.hide() - if value == self.min_progress: self._progress.show() - + @property def visible(self): return self.isVisible() diff --git a/pyforms/gui/Controls/ControlBoundingSlider.py b/pyforms/gui/Controls/ControlBoundingSlider.py index 4868658..8d55445 100755 --- a/pyforms/gui/Controls/ControlBoundingSlider.py +++ b/pyforms/gui/Controls/ControlBoundingSlider.py @@ -7,7 +7,7 @@ from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QSpinBox from AnyQt.QtGui import QFont, QColor, QCursor, QPainter -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase class GaugeWidgetVertical(QWidget): @@ -273,9 +273,9 @@ def init_form(self): hlayout = QVBoxLayout() - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: hlayout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: hlayout.setMargin(0) diff --git a/pyforms/gui/Controls/ControlButton.py b/pyforms/gui/Controls/ControlButton.py index 7769cd9..9380e0d 100755 --- a/pyforms/gui/Controls/ControlButton.py +++ b/pyforms/gui/Controls/ControlButton.py @@ -9,7 +9,7 @@ from AnyQt.QtWidgets import QPushButton, QSizePolicy from AnyQt.QtGui import QIcon -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase class ControlButton(ControlBase): diff --git a/pyforms/gui/Controls/ControlCheckBox.py b/pyforms/gui/Controls/ControlCheckBox.py index f3e7f6e..dde8a8f 100755 --- a/pyforms/gui/Controls/ControlCheckBox.py +++ b/pyforms/gui/Controls/ControlCheckBox.py @@ -7,7 +7,7 @@ import pyforms.utils.tools as tools -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase class ControlCheckBox(ControlBase): diff --git a/pyforms/gui/Controls/ControlCheckBoxList.py b/pyforms/gui/Controls/ControlCheckBoxList.py index 4011ecd..7051398 100755 --- a/pyforms/gui/Controls/ControlCheckBoxList.py +++ b/pyforms/gui/Controls/ControlCheckBoxList.py @@ -8,7 +8,7 @@ from AnyQt import uic, QtCore from AnyQt.QtWidgets import QListWidgetItem -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase class ControlCheckBoxList(ControlBase): diff --git a/pyforms/gui/Controls/ControlCodeEditor.py b/pyforms/gui/Controls/ControlCodeEditor.py index fd8c54d..5a595c7 100755 --- a/pyforms/gui/Controls/ControlCodeEditor.py +++ b/pyforms/gui/Controls/ControlCodeEditor.py @@ -6,7 +6,7 @@ from AnyQt import _api from pysettings import conf -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase import pyforms.utils.tools as tools from AnyQt import QtCore, uic @@ -14,7 +14,7 @@ from AnyQt.QtGui import QFontMetrics, QColor, QIcon, QFont if _api.USED_API == _api.QT_API_PYQT5: - from PyQt5.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs + from AnyQt.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs elif _api.USED_API == _api.QT_API_PYQT4: from PyQt4.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs diff --git a/pyforms/gui/Controls/ControlCombo.py b/pyforms/gui/Controls/ControlCombo.py index 9201a94..9fc30a7 100755 --- a/pyforms/gui/Controls/ControlCombo.py +++ b/pyforms/gui/Controls/ControlCombo.py @@ -8,7 +8,7 @@ from AnyQt.QtWidgets import QLabel, QWidget, QComboBox, QHBoxLayout, QSizePolicy -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase class ControlCombo(ControlBase, QWidget): diff --git a/pyforms/gui/Controls/ControlDir.py b/pyforms/gui/Controls/ControlDir.py index b8d1ecd..7dae938 100755 --- a/pyforms/gui/Controls/ControlDir.py +++ b/pyforms/gui/Controls/ControlDir.py @@ -3,7 +3,7 @@ from pysettings import conf -from pyforms.gui.Controls.ControlText import ControlText +from pyforms.gui.controls.ControlText import ControlText import pyforms.utils.tools as tools diff --git a/pyforms/gui/Controls/ControlDockWidget.py b/pyforms/gui/Controls/ControlDockWidget.py index fd7fb35..0d967a8 100644 --- a/pyforms/gui/Controls/ControlDockWidget.py +++ b/pyforms/gui/Controls/ControlDockWidget.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pyforms.gui.Controls.ControlEmptyWidget import ControlEmptyWidget +from pyforms.gui.controls.ControlEmptyWidget import ControlEmptyWidget class ControlDockWidget(ControlEmptyWidget): diff --git a/pyforms/gui/Controls/ControlEmptyWidget.py b/pyforms/gui/Controls/ControlEmptyWidget.py index c7e3821..afc4f30 100755 --- a/pyforms/gui/Controls/ControlEmptyWidget.py +++ b/pyforms/gui/Controls/ControlEmptyWidget.py @@ -3,10 +3,10 @@ from pysettings import conf -from AnyQt.QtWidgets import QWidget, QVBoxLayout - -from pyforms.gui.Controls.ControlBase import ControlBase -from pyforms.gui.BaseWidget import BaseWidget +from AnyQt import _api +from AnyQt.QtWidgets import QWidget, QVBoxLayout +from pyforms.gui.controls.ControlBase import ControlBase +from pyforms.gui.basewidget import BaseWidget class ControlEmptyWidget(ControlBase, QWidget): @@ -14,9 +14,9 @@ def __init__(self, label='', default=None): QWidget.__init__(self) layout = QVBoxLayout() - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) diff --git a/pyforms/gui/Controls/ControlFile.py b/pyforms/gui/Controls/ControlFile.py index 5c56d77..84b1ab1 100755 --- a/pyforms/gui/Controls/ControlFile.py +++ b/pyforms/gui/Controls/ControlFile.py @@ -1,9 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf - -from pyforms.gui.Controls.ControlText import ControlText +from pysettings import conf +from pyforms.gui.controls.ControlText import ControlText import pyforms.utils.tools as tools @@ -28,9 +27,9 @@ def finishEditing(self): def click(self): value = QFileDialog.getOpenFileName(self.parent, self._label, self.value) - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: value = value[0] - else: + elif _api.USED_API == _api.QT_API_PYQT4: value = str(value) if value and len(value)>0: self.value = value diff --git a/pyforms/gui/Controls/ControlFilesTree.py b/pyforms/gui/Controls/ControlFilesTree.py index fe25201..ab4d5f1 100755 --- a/pyforms/gui/Controls/ControlFilesTree.py +++ b/pyforms/gui/Controls/ControlFilesTree.py @@ -4,7 +4,7 @@ from pysettings import conf -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase from AnyQt import QtCore from AnyQt.QtWidgets import QTreeView, QFileSystemModel diff --git a/pyforms/gui/Controls/ControlImage.py b/pyforms/gui/Controls/ControlImage.py index a1f14dc..6d178d3 100755 --- a/pyforms/gui/Controls/ControlImage.py +++ b/pyforms/gui/Controls/ControlImage.py @@ -7,7 +7,7 @@ logger = logging.getLogger(__name__) -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase from pyforms.utils import tools try: @@ -25,15 +25,15 @@ if _api.USED_API == _api.QT_API_PYQT5: try: - from PyQt5.QtOpenGL import QGLWidget + from AnyQt.QtOpenGL import QGLWidget except: logger.debug("No OpenGL library available") import platform if platform.system() == 'Darwin': - from pyforms.gui.Controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + from pyforms.gui.controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget else: - from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget elif _api.USED_API == _api.QT_API_PYQT4: try: @@ -41,7 +41,7 @@ except: logger.debug("No OpenGL library available") - from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget import numpy as np diff --git a/pyforms/gui/Controls/ControlLabel.py b/pyforms/gui/Controls/ControlLabel.py index 817de4b..7aadbb3 100755 --- a/pyforms/gui/Controls/ControlLabel.py +++ b/pyforms/gui/Controls/ControlLabel.py @@ -1,14 +1,14 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -""" pyforms.gui.Controls.ControlLabel""" +""" pyforms.gui.controls.ControlLabel""" import pyforms.utils.tools as tools from pysettings import conf from AnyQt import uic -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase __author__ = "Carlos Mão de Ferro" __copyright__ = "" diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/Controls/ControlList.py index ab28db4..f000863 100755 --- a/pyforms/gui/Controls/ControlList.py +++ b/pyforms/gui/Controls/ControlList.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -""" pyforms.gui.Controls.ControlList +""" pyforms.gui.controls.ControlList """ import logging @@ -13,8 +13,8 @@ from AnyQt.QtWidgets import QTableWidgetItem, QWidget, QAbstractItemView from AnyQt.QtGui import QIcon -from pyforms.gui.BaseWidget import BaseWidget -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.basewidget import BaseWidget +from pyforms.gui.controls.ControlBase import ControlBase logger = logging.getLogger(__name__) diff --git a/pyforms/gui/Controls/ControlMatplotlib.py b/pyforms/gui/Controls/ControlMatplotlib.py index 76844dc..797bb6d 100644 --- a/pyforms/gui/Controls/ControlMatplotlib.py +++ b/pyforms/gui/Controls/ControlMatplotlib.py @@ -14,7 +14,7 @@ from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase from AnyQt import _api diff --git a/pyforms/gui/Controls/ControlMdiArea.py b/pyforms/gui/Controls/ControlMdiArea.py index 28a4411..322ec53 100644 --- a/pyforms/gui/Controls/ControlMdiArea.py +++ b/pyforms/gui/Controls/ControlMdiArea.py @@ -7,7 +7,7 @@ from AnyQt.QtWidgets import QMdiArea, QMdiSubWindow -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase logger = logging.getLogger(__name__) diff --git a/pyforms/gui/Controls/ControlNumber.py b/pyforms/gui/Controls/ControlNumber.py index e3b5b1b..8a070f3 100644 --- a/pyforms/gui/Controls/ControlNumber.py +++ b/pyforms/gui/Controls/ControlNumber.py @@ -8,7 +8,7 @@ from AnyQt import uic -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase class ControlNumber(ControlBase): diff --git a/pyforms/gui/Controls/ControlOpenGL.py b/pyforms/gui/Controls/ControlOpenGL.py index 826b307..f78802a 100644 --- a/pyforms/gui/Controls/ControlOpenGL.py +++ b/pyforms/gui/Controls/ControlOpenGL.py @@ -7,7 +7,7 @@ logger = logging.getLogger(__name__) -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase from AnyQt.QtWidgets import QSizePolicy @@ -19,15 +19,15 @@ from AnyQt import _api if _api.USED_API == _api.QT_API_PYQT5: try: - from PyQt5.QtOpenGL import QGLWidget + from AnyQt.QtOpenGL import QGLWidget except: logger.debug("No OpenGL library available") import platform if platform.system() == 'Darwin': - from pyforms.gui.Controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + from pyforms.gui.controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget else: - from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget elif _api.USED_API == _api.QT_API_PYQT4: try: @@ -35,7 +35,7 @@ except: logger.debug("No OpenGL library available") - from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget class OpenglGLWidget(QGLWidget): diff --git a/pyforms/gui/Controls/ControlPlayer/VideoGLWidget.py b/pyforms/gui/Controls/ControlPlayer/VideoGLWidget.py deleted file mode 100644 index 9804e51..0000000 --- a/pyforms/gui/Controls/ControlPlayer/VideoGLWidget.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -""" pyforms.gui.Controls.ControlPlayer.VideoGLWidget - -""" - -from pyforms.gui.Controls.ControlPlayer.AbstractGLWidget import AbstractGLWidget - - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtOpenGL import QGLWidget -else: - from PyQt4.QtOpenGL import QGLWidget - -class VideoGLWidget(AbstractGLWidget, QGLWidget): pass \ No newline at end of file diff --git a/pyforms/gui/Controls/ControlProgress.py b/pyforms/gui/Controls/ControlProgress.py index a3d2a9a..d42f76c 100755 --- a/pyforms/gui/Controls/ControlProgress.py +++ b/pyforms/gui/Controls/ControlProgress.py @@ -2,19 +2,9 @@ # -*- coding: utf-8 -*- import os - -from pyforms.gui.Controls.ControlBase import ControlBase - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic - from PyQt5.QtWidgets import QApplication - -else: - from PyQt4 import uic - from PyQt4.QtGui import QApplication - +from pyforms.gui.controls.ControlBase import ControlBase +from AnyQt import uic +from AnyQt.QtWidgets import QApplication class ControlProgress(ControlBase): def __init__(self, label="%p%", default=0, min=0, max=100): diff --git a/pyforms/gui/Controls/ControlSlider.py b/pyforms/gui/Controls/ControlSlider.py index 43c8ae7..3a82d58 100755 --- a/pyforms/gui/Controls/ControlSlider.py +++ b/pyforms/gui/Controls/ControlSlider.py @@ -1,17 +1,10 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf - import pyforms.utils.tools as tools -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic - -else: - from PyQt4 import uic - -from pyforms.gui.Controls.ControlBase import ControlBase +from AnyQt import uic +from pyforms.gui.controls.ControlBase import ControlBase class ControlSlider(ControlBase): diff --git a/pyforms/gui/Controls/ControlText.py b/pyforms/gui/Controls/ControlText.py index 45b4516..610c2b5 100755 --- a/pyforms/gui/Controls/ControlText.py +++ b/pyforms/gui/Controls/ControlText.py @@ -10,18 +10,10 @@ @status: Development @lastEditedBy: Carlos Mão de Ferro (carlos.maodeferro@neuro.fchampalimaud.org) ''' - -from pyforms.gui.Controls.ControlBase import ControlBase import pyforms.utils.tools as tools - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QLineEdit - from PyQt5 import uic -else: - from PyQt4.QtGui import QLineEdit - from PyQt4 import uic +from pyforms.gui.controls.ControlBase import ControlBase +from AnyQt.QtWidgets import QLineEdit +from AnyQt import uic class ControlText(ControlBase): diff --git a/pyforms/gui/Controls/ControlTextArea.py b/pyforms/gui/Controls/ControlTextArea.py index b1f670d..2e76b17 100755 --- a/pyforms/gui/Controls/ControlTextArea.py +++ b/pyforms/gui/Controls/ControlTextArea.py @@ -1,14 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import pyforms.utils.tools as tools -from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic, QtGui -else: - from PyQt4 import uic, QtGui -from pyforms.gui.Controls.ControlBase import ControlBase - __author__ = "Ricardo Ribeiro" __credits__ = ["Ricardo Ribeiro"] __license__ = "MIT" @@ -17,6 +9,9 @@ __email__ = "ricardojvr@gmail.com" __status__ = "Development" +import pyforms.utils.tools as tools +from AnyQt import uic, QtGui +from pyforms.gui.controls.ControlBase import ControlBase class ControlTextArea(ControlBase): diff --git a/pyforms/gui/Controls/ControlToolBox.py b/pyforms/gui/Controls/ControlToolBox.py index 87ecbfb..c91be40 100644 --- a/pyforms/gui/Controls/ControlToolBox.py +++ b/pyforms/gui/Controls/ControlToolBox.py @@ -3,19 +3,13 @@ from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QToolBox - from PyQt5.QtWidgets import QFrame - from PyQt5.QtWidgets import QVBoxLayout - from PyQt5.QtWidgets import QHBoxLayout +from AnyQt import _api +from AnyQt.QtWidgets import QToolBox +from AnyQt.QtWidgets import QFrame +from AnyQt.QtWidgets import QVBoxLayout +from AnyQt.QtWidgets import QHBoxLayout -else: - from PyQt4.QtGui import QToolBox - from PyQt4.QtGui import QFrame - from PyQt4.QtGui import QVBoxLayout - from PyQt4.QtGui import QHBoxLayout - -from pyforms.gui.Controls.ControlBase import ControlBase +from pyforms.gui.controls.ControlBase import ControlBase class ControlToolBox(ControlBase): @@ -39,9 +33,9 @@ def value(self, value): widget = QFrame(self.form); layout = QVBoxLayout(); - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) widget.setLayout(layout) @@ -51,9 +45,9 @@ def value(self, value): hwidget = QFrame(self.form); hlayout = QHBoxLayout(); - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: hlayout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: hlayout.setMargin(0) hwidget.setLayout(hlayout) diff --git a/pyforms/gui/Controls/ControlTree.py b/pyforms/gui/Controls/ControlTree.py index e5c00a2..39223e4 100644 --- a/pyforms/gui/Controls/ControlTree.py +++ b/pyforms/gui/Controls/ControlTree.py @@ -1,19 +1,10 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf - -from pyforms.gui.Controls.ControlBase import ControlBase - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QTreeView, QAbstractItemView, QAction - from PyQt5.QtGui import QIcon, QKeySequence - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QTreeWidget, QTreeWidgetItem, QTreeView, QAbstractItemView, QAction, QKeySequence, QIcon - from PyQt4 import QtCore - +from pyforms.gui.controls.ControlBase import ControlBase +from AnyQt.QtWidgets import QTreeWidget, QTreeWidgetItem, QTreeView, QAbstractItemView, QAction +from AnyQt.QtGui import QIcon, QKeySequence +from AnyQt import QtCore class ControlTree(ControlBase, QTreeWidget): """This class represents a wrapper to the QTreeWidget""" diff --git a/pyforms/gui/Controls/ControlTreeView.py b/pyforms/gui/Controls/ControlTreeView.py index 1ac261c..2143501 100644 --- a/pyforms/gui/Controls/ControlTreeView.py +++ b/pyforms/gui/Controls/ControlTreeView.py @@ -1,16 +1,9 @@ # !/usr/bin/python # -*- coding: utf-8 -*- +from pyforms.gui.controls.ControlBase import ControlBase -from pysettings import conf - -from pyforms.gui.Controls.ControlBase import ControlBase - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QTreeView, QAbstractItemView - from PyQt5.QtGui import QStandardItem, QStandardItemModel - -else: - from PyQt4.QtGui import QTreeView, QAbstractItemView, QStandardItem, QStandardItemModel +from AnyQt.QtWidgets import QTreeView, QAbstractItemView +from AnyQt.QtGui import QStandardItem, QStandardItemModel class ControlTreeView(ControlBase, QTreeView): diff --git a/pyforms/gui/Controls/ControlVisVis.py b/pyforms/gui/Controls/ControlVisVis.py index a0d9577..fd4060d 100755 --- a/pyforms/gui/Controls/ControlVisVis.py +++ b/pyforms/gui/Controls/ControlVisVis.py @@ -9,20 +9,12 @@ __email__ = "ricardojvr@gmail.com" __status__ = "Development" +import visvis as vv, numpy as np -import pyforms.utils.tools as tools -from pyforms.gui.Controls.ControlBase import ControlBase - -from visvis import Point, Pointset -import visvis as vv -import numpy as np - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget, QVBoxLayout, QSizePolicy -else: - from PyQt4.QtGui import QWidget, QVBoxLayout, QSizePolicy +from visvis import Point, Pointset +from pyforms.gui.controls.ControlBase import ControlBase +from AnyQt import _api +from AnyQt.QtWidgets import QWidget, QVBoxLayout, QSizePolicy class ControlVisVis(ControlBase): @@ -31,7 +23,7 @@ def init_form(self): self._form = QtGui.QWidget() layout = QtGui.QVBoxLayout() - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) else: layout.setMargin(0) diff --git a/pyforms/gui/Controls/ControlVisVisVolume.py b/pyforms/gui/Controls/ControlVisVisVolume.py index d7709ee..3282e92 100755 --- a/pyforms/gui/Controls/ControlVisVisVolume.py +++ b/pyforms/gui/Controls/ControlVisVisVolume.py @@ -9,19 +9,11 @@ __email__ = "ricardojvr@gmail.com" __status__ = "Development" -import pyforms.utils.tools as tools -from pyforms.gui.Controls.ControlBase import ControlBase - -from visvis import Point, Pointset -import visvis as vv -import numpy as np - -from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget, QVBoxLayout, QSizePolicy -else: - from PyQt4.QtGui import QWidget, QVBoxLayout, QSizePolicy - +import visvis as vv, numpy as np +from pyforms.gui.controls.ControlBase import ControlBase +from visvis import Point, Pointset +from AnyQt import _api +from AnyQt.QtWidgets import QWidget, QVBoxLayout, QSizePolicy class ControlVisVisVolume(ControlBase): def init_form(self): @@ -29,9 +21,9 @@ def init_form(self): layout = QVBoxLayout() layout.setMargin(0) - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) self._form.setLayout(layout) diff --git a/pyforms/gui/Controls/ControlWeb.py b/pyforms/gui/Controls/ControlWeb.py index afe3247..a308cac 100644 --- a/pyforms/gui/Controls/ControlWeb.py +++ b/pyforms/gui/Controls/ControlWeb.py @@ -9,16 +9,9 @@ __email__ = "ricardojvr@gmail.com" __status__ = "Development" -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView - from PyQt5.QtCore import QUrl -else: - from PyQt4.QtCore import QUrl - from PyQt4.QtWebKit import QWebView - -from pyforms.gui.Controls.ControlBase import ControlBase +from AnyQt.QtWebEngineWidgets import QWebEngineView as QWebView +from AnyQt.QtCore import QUrl +from pyforms.gui.controls.ControlBase import ControlBase class ControlWeb(ControlBase, QWebView): diff --git a/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py b/pyforms/gui/Controls/control_event_timeline/ControlEventTimeline.py similarity index 93% rename from pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py rename to pyforms/gui/Controls/control_event_timeline/ControlEventTimeline.py index 16174d4..a95b33c 100755 --- a/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py +++ b/pyforms/gui/Controls/control_event_timeline/ControlEventTimeline.py @@ -1,31 +1,21 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import csv -import os +import csv, os -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget, QScrollArea, QColorDialog, QFileDialog, QMessageBox, QPushButton, QLabel, \ - QSlider, QHBoxLayout, QVBoxLayout - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QWidget, QScrollArea, QColorDialog, QFileDialog, QMessageBox, QPushButton, QLabel, QSlider, \ - QHBoxLayout, QVBoxLayout - from PyQt4 import QtCore - -from pyforms.gui.Controls.ControlEventTimeline.TimelineChart import TimelineChart -from pyforms.gui.Controls.ControlBase import ControlBase -from pyforms.gui.Controls.ControlEventTimeline.TimelineWidget import TimelineWidget -from pyforms.gui.Controls.ControlEventTimeline.TimelinePopupWindow import TimelinePopupWindow -from pyforms.gui.Controls.ControlEventTimeline.import_window import ImportWindow - -from pyforms.gui.Controls.ControlEventTimeline.graphs_graph2event import Graph2Event -from pyforms.gui.Controls.ControlEventTimeline.graphs_properties import GraphsProperties -from pyforms.gui.Controls.ControlEventTimeline.graphs_eventsgenerator import GraphsEventsGenerator +from pysettings import conf +from AnyQt.QtWidgets import QWidget, QScrollArea, QColorDialog, QFileDialog, QMessageBox +from AnyQt.QtWidgets import QPushButton, QLabel, QSlider, QHBoxLayout, QVBoxLayout +from AnyQt import QtCore +from pyforms.gui.controls.ControlBase import ControlBase +from pyforms.gui.controls.control_event_timeline.TimelineChart import TimelineChart +from pyforms.gui.controls.control_event_timeline.TimelineWidget import TimelineWidget +from pyforms.gui.controls.control_event_timeline.TimelinePopupWindow import TimelinePopupWindow +from pyforms.gui.controls.control_event_timeline.import_window import ImportWindow +from pyforms.gui.controls.control_event_timeline.graphs_graph2event import Graph2Event +from pyforms.gui.controls.control_event_timeline.graphs_properties import GraphsProperties +from pyforms.gui.controls.control_event_timeline.graphs_eventsgenerator import GraphsEventsGenerator class ControlEventTimeline(ControlBase, QWidget): @@ -90,10 +80,10 @@ def init_form(self): vlayout = QVBoxLayout() hlayout = QHBoxLayout() - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: hlayout.setContentsMargins(0,0,0,0) vlayout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: hlayout.setMargin(0) vlayout.setMargin(0) diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineChart.py b/pyforms/gui/Controls/control_event_timeline/TimelineChart.py similarity index 97% rename from pyforms/gui/Controls/ControlEventTimeline/TimelineChart.py rename to pyforms/gui/Controls/control_event_timeline/TimelineChart.py index 319cb19..292ff10 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelineChart.py +++ b/pyforms/gui/Controls/control_event_timeline/TimelineChart.py @@ -1,14 +1,6 @@ # !/usr/bin/python # -*- coding: utf-8 -*- - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtGui import QColor - -else: - from PyQt4.QtGui import QColor - +from AnyQt.QtGui import QColor class TimelineChart(object): """ diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py b/pyforms/gui/Controls/control_event_timeline/TimelineDelta.py similarity index 94% rename from pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py rename to pyforms/gui/Controls/control_event_timeline/TimelineDelta.py index 1ac8f5d..468a17d 100755 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py +++ b/pyforms/gui/Controls/control_event_timeline/TimelineDelta.py @@ -1,30 +1,17 @@ # !/usr/bin/python # -*- coding: utf-8 -*- - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QInputDialog - from PyQt5.QtGui import QColor - -else: - from PyQt4.QtGui import QColor, QInputDialog - -from pyforms.gui.Controls.ControlEventTimeline.Track import Track - -from pyforms import BaseWidget -from pyforms.Controls import ControlText, ControlNumber, ControlButton - +from pyforms.gui.controls.control_event_timeline.Track import Track +from pyforms import BaseWidget +from pyforms.controls import ControlText, ControlNumber, ControlButton +from AnyQt.QtWidgets import QInputDialog +from AnyQt.QtGui import QColor class DeltaEditWindow(BaseWidget): def __init__(self, parent_win, label, begin, end): BaseWidget.__init__(self, 'Edit frame', parent_win=parent_win) - if conf.PYFORMS_USE_QT5: - self.layout().setContentsMargins(5,5,5,5) - else: - self.layout().setMargin(5) + self.set_margin(5) self._label = ControlText('Label', label) self._begin = ControlNumber('Begin', begin, 0, 100000000000000) diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelinePointer.py b/pyforms/gui/Controls/control_event_timeline/TimelinePointer.py similarity index 91% rename from pyforms/gui/Controls/ControlEventTimeline/TimelinePointer.py rename to pyforms/gui/Controls/control_event_timeline/TimelinePointer.py index 22d7c9d..3f7007e 100755 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelinePointer.py +++ b/pyforms/gui/Controls/control_event_timeline/TimelinePointer.py @@ -1,16 +1,7 @@ # !/usr/bin/python # -*- coding: utf-8 -*- - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtGui import QColor - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QColor - from PyQt4 import QtCore - +from AnyQt.QtGui import QColor +from AnyQt import QtCore class TimelinePointer(object): def __init__(self, position, parent): diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelinePopupWindow.py b/pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.py similarity index 93% rename from pyforms/gui/Controls/ControlEventTimeline/TimelinePopupWindow.py rename to pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.py index 863d453..af27144 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelinePopupWindow.py +++ b/pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.py @@ -1,20 +1,12 @@ # !/usr/bin/python # -*- coding: utf-8 -*- - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QDialog, QInputDialog, QColorDialog - from PyQt5.QtGui import QColor, QPixmap, QFont, QPainter - from PyQt5 import uic - from PyQt5 import QtCore -else: - from PyQt4.QtGui import QDialog, QInputDialog, QColor, QPixmap, QColorDialog, QPainter, QFont - from PyQt4 import uic - from PyQt4 import QtCore - import pyforms.utils.tools as tools +from AnyQt.QtWidgets import QDialog, QInputDialog, QColorDialog +from AnyQt.QtGui import QColor, QPixmap, QFont, QPainter +from AnyQt import uic +from AnyQt import QtCore + class TimelinePopupWindow(QDialog): """ diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelinePopupWindow.ui b/pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.ui similarity index 100% rename from pyforms/gui/Controls/ControlEventTimeline/TimelinePopupWindow.ui rename to pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.ui diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py b/pyforms/gui/Controls/control_event_timeline/TimelineWidget.py similarity index 96% rename from pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py rename to pyforms/gui/Controls/control_event_timeline/TimelineWidget.py index 5e98ad0..518e4cb 100755 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py +++ b/pyforms/gui/Controls/control_event_timeline/TimelineWidget.py @@ -1,21 +1,13 @@ # !/usr/bin/python # -*- coding: utf-8 -*- - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget, QMessageBox - from PyQt5.QtGui import QColor, QPainter, QFont, QCursor - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QWidget, QColor, QMessageBox, QPainter, QFont, QCursor - from PyQt4 import QtCore - -from pyforms.gui.Controls.ControlEventTimeline.Track import Track -from pyforms.gui.Controls.ControlEventTimeline.TimelinePointer import TimelinePointer -from pyforms.gui.Controls.ControlEventTimeline.TimelineDelta import TimelineDelta -from pyforms.gui.Controls.ControlEventTimeline.TimelineChart import TimelineChart +from AnyQt.QtWidgets import QWidget, QMessageBox +from AnyQt.QtGui import QColor, QPainter, QFont, QCursor +from AnyQt import QtCore + +from pyforms.gui.controls.control_event_timeline.Track import Track +from pyforms.gui.controls.control_event_timeline.TimelinePointer import TimelinePointer +from pyforms.gui.controls.control_event_timeline.TimelineDelta import TimelineDelta +from pyforms.gui.controls.control_event_timeline.TimelineChart import TimelineChart class TimelineWidget(QWidget): diff --git a/pyforms/gui/Controls/ControlEventTimeline/Track.py b/pyforms/gui/Controls/control_event_timeline/Track.py similarity index 92% rename from pyforms/gui/Controls/ControlEventTimeline/Track.py rename to pyforms/gui/Controls/control_event_timeline/Track.py index 16b188e..ddb908a 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/Track.py +++ b/pyforms/gui/Controls/control_event_timeline/Track.py @@ -1,16 +1,7 @@ # !/usr/bin/python # -*- coding: utf-8 -*- - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtGui import QColor - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QColor - from PyQt4 import QtCore - +from AnyQt.QtGui import QColor +from AnyQt import QtCore class Track(object): """ diff --git a/pyforms/gui/Controls/ControlEventTimeline/__init__.py b/pyforms/gui/Controls/control_event_timeline/__init__.py similarity index 89% rename from pyforms/gui/Controls/ControlEventTimeline/__init__.py rename to pyforms/gui/Controls/control_event_timeline/__init__.py index 5a0c3bb..956e9c5 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/__init__.py +++ b/pyforms/gui/Controls/control_event_timeline/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -""" pyforms.gui.Controls.ControlEventTimeline.__init__ +""" pyforms.gui.controls.ControlEventTimeline.__init__ """ diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py b/pyforms/gui/Controls/control_event_timeline/graphs_eventsgenerator.py similarity index 83% rename from pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py rename to pyforms/gui/Controls/control_event_timeline/graphs_eventsgenerator.py index 9a55b45..cd10195 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_eventsgenerator.py +++ b/pyforms/gui/Controls/control_event_timeline/graphs_eventsgenerator.py @@ -1,26 +1,14 @@ -import csv, sys -from pyforms import BaseWidget -from pyforms.Controls import ControlProgress -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlList -from pyforms.Controls import ControlNumber -from pyforms.Controls import ControlSlider -from pyforms.Controls import ControlTextArea -from pyforms.Controls import ControlText -from pyforms.Controls import ControlNumber -from pyforms.Controls import ControlLabel - -import time -import datetime - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QMessageBox -else: - from PyQt4.QtGui import QMessageBox - - +from pyforms import BaseWidget +from pyforms.controls import ControlProgress +from pyforms.controls import ControlButton +from pyforms.controls import ControlList +from pyforms.controls import ControlNumber +from pyforms.controls import ControlSlider +from pyforms.controls import ControlTextArea +from pyforms.controls import ControlText +from pyforms.controls import ControlNumber +from pyforms.controls import ControlLabel +from AnyQt.QtWidgets import QMessageBox class GraphsEventsGenerator(BaseWidget): diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py b/pyforms/gui/Controls/control_event_timeline/graphs_graph2event.py similarity index 84% rename from pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py rename to pyforms/gui/Controls/control_event_timeline/graphs_graph2event.py index afc2793..d5f219b 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py +++ b/pyforms/gui/Controls/control_event_timeline/graphs_graph2event.py @@ -1,26 +1,14 @@ -import csv, sys -from pyforms import BaseWidget -from pyforms.Controls import ControlProgress -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlList -from pyforms.Controls import ControlNumber -from pyforms.Controls import ControlSlider -from pyforms.Controls import ControlTextArea -from pyforms.Controls import ControlText -from pyforms.Controls import ControlNumber -from pyforms.Controls import ControlLabel - -import time -import datetime - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QMessageBox -else: - from PyQt4.QtGui import QMessageBox - - +from pyforms import BaseWidget +from pyforms.controls import ControlProgress +from pyforms.controls import ControlButton +from pyforms.controls import ControlList +from pyforms.controls import ControlNumber +from pyforms.controls import ControlSlider +from pyforms.controls import ControlTextArea +from pyforms.controls import ControlText +from pyforms.controls import ControlNumber +from pyforms.controls import ControlLabel +from AnyQt.QtWidgets import QMessageBox class Graph2Event(BaseWidget): diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py b/pyforms/gui/Controls/control_event_timeline/graphs_properties.py similarity index 95% rename from pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py rename to pyforms/gui/Controls/control_event_timeline/graphs_properties.py index 0fe89e8..9af1487 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_properties.py +++ b/pyforms/gui/Controls/control_event_timeline/graphs_properties.py @@ -1,12 +1,12 @@ import csv, time, datetime, decimal, logging, sys, numpy as np from pyforms import BaseWidget -from pyforms.Controls import ControlProgress -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlList -from pyforms.Controls import ControlNumber -from pyforms.Controls import ControlSlider -from pyforms.Controls import ControlText -from pyforms.Controls import ControlLabel +from pyforms.controls import ControlProgress +from pyforms.controls import ControlButton +from pyforms.controls import ControlList +from pyforms.controls import ControlNumber +from pyforms.controls import ControlSlider +from pyforms.controls import ControlText +from pyforms.controls import ControlLabel logger = logging.getLogger(__name__) diff --git a/pyforms/gui/Controls/ControlEventTimeline/import_window.py b/pyforms/gui/Controls/control_event_timeline/import_window.py similarity index 95% rename from pyforms/gui/Controls/ControlEventTimeline/import_window.py rename to pyforms/gui/Controls/control_event_timeline/import_window.py index b76c53b..f4c4047 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/import_window.py +++ b/pyforms/gui/Controls/control_event_timeline/import_window.py @@ -1,11 +1,11 @@ import csv from pyforms import BaseWidget -from pyforms.Controls import ControlProgress -from pyforms.Controls import ControlCombo -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlEmptyWidget -from pyforms.Controls import ControlFile -from pyforms.Controls import ControlNumber +from pyforms.controls import ControlProgress +from pyforms.controls import ControlCombo +from pyforms.controls import ControlButton +from pyforms.controls import ControlEmptyWidget +from pyforms.controls import ControlFile +from pyforms.controls import ControlNumber import time diff --git a/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py b/pyforms/gui/Controls/control_events_graph/ControlEventsGraph.py similarity index 89% rename from pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py rename to pyforms/gui/Controls/control_events_graph/ControlEventsGraph.py index 072503a..e6440dd 100755 --- a/pyforms/gui/Controls/ControlEventsGraph/ControlEventsGraph.py +++ b/pyforms/gui/Controls/control_events_graph/ControlEventsGraph.py @@ -2,19 +2,10 @@ # -*- coding: utf-8 -*- import csv - -from pysettings import conf - -from pyforms.gui.Controls.ControlBase import ControlBase -from pyforms.gui.Controls.ControlEventsGraph.EventsWidget import EventsWidget - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog - from PyQt4 import QtCore +from pyforms.gui.controls.ControlBase import ControlBase +from pyforms.gui.controls.control_events_graph.EventsWidget import EventsWidget +from AnyQt.QtWidgets import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog +from AnyQt import QtCore class ControlEventsGraph(ControlBase, QWidget): @@ -38,9 +29,9 @@ def __init__(self, label="", default=0, min=0, max=100, **kwargs): def init_form(self): vlayout = QVBoxLayout() - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: vlayout.setContentsMargins(0,0,0,0) - else: + elif _api.USED_API == _api.QT_API_PYQT4: vlayout.setMargin(0) self.setLayout(vlayout) diff --git a/pyforms/gui/Controls/ControlEventsGraph/Event.py b/pyforms/gui/Controls/control_events_graph/Event.py similarity index 92% rename from pyforms/gui/Controls/ControlEventsGraph/Event.py rename to pyforms/gui/Controls/control_events_graph/Event.py index a8c577a..38af3c0 100644 --- a/pyforms/gui/Controls/ControlEventsGraph/Event.py +++ b/pyforms/gui/Controls/control_events_graph/Event.py @@ -1,15 +1,8 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtGui import QColor - -else: - from PyQt4.QtGui import QColor - -from pyforms.gui.Controls.ControlEventsGraph.Track import Track +from AnyQt.QtGui import QColor +from pyforms.gui.controls.control_events_graph.Track import Track class Event(object): diff --git a/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py b/pyforms/gui/Controls/control_events_graph/EventsWidget.py similarity index 94% rename from pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py rename to pyforms/gui/Controls/control_events_graph/EventsWidget.py index f5d82f4..3671d40 100755 --- a/pyforms/gui/Controls/ControlEventsGraph/EventsWidget.py +++ b/pyforms/gui/Controls/control_events_graph/EventsWidget.py @@ -2,21 +2,14 @@ # -*- coding: utf-8 -*- import sys - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QWidget - from PyQt5.QtGui import QColor, QPainter, QFont - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QWidget, QColor, QPainter, QFont - from PyQt4 import QtCore - -from pyforms.gui.Controls.ControlEventsGraph.Track import Track -from pyforms.gui.Controls.ControlEventsGraph.Pointer import Pointer -from pyforms.gui.Controls.ControlEventsGraph.Event import Event +from pysettings import conf +from AnyQt.QtWidgets import QWidget +from AnyQt.QtGui import QColor, QPainter, QFont +from AnyQt import QtCore + +from pyforms.gui.controls.control_events_graph.Track import Track +from pyforms.gui.controls.control_events_graph.Pointer import Pointer +from pyforms.gui.controls.control_events_graph.Event import Event class EventsWidget(QWidget): diff --git a/pyforms/gui/Controls/ControlEventsGraph/Pointer.py b/pyforms/gui/Controls/control_events_graph/Pointer.py similarity index 91% rename from pyforms/gui/Controls/ControlEventsGraph/Pointer.py rename to pyforms/gui/Controls/control_events_graph/Pointer.py index 771713c..548357f 100644 --- a/pyforms/gui/Controls/ControlEventsGraph/Pointer.py +++ b/pyforms/gui/Controls/control_events_graph/Pointer.py @@ -1,16 +1,8 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtGui import QColor - from PyQt5 import QtCore - -else: - from PyQt4.QtGui import QColor - from PyQt4 import QtCore - +from AnyQt.QtGui import QColor +from AnyQt import QtCore class Pointer(object): """ diff --git a/pyforms/gui/Controls/ControlEventsGraph/Track.py b/pyforms/gui/Controls/control_events_graph/Track.py similarity index 94% rename from pyforms/gui/Controls/ControlEventsGraph/Track.py rename to pyforms/gui/Controls/control_events_graph/Track.py index 028266a..2435321 100644 --- a/pyforms/gui/Controls/ControlEventsGraph/Track.py +++ b/pyforms/gui/Controls/control_events_graph/Track.py @@ -1,16 +1,8 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf - import bisect - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtGui import QColor - -else: - from PyQt4.QtGui import QColor - +from AnyQt.QtGui import QColor class Track(object): """ diff --git a/pyforms/gui/Controls/ControlEventsGraph/__init__.py b/pyforms/gui/Controls/control_events_graph/__init__.py similarity index 88% rename from pyforms/gui/Controls/ControlEventsGraph/__init__.py rename to pyforms/gui/Controls/control_events_graph/__init__.py index 161f236..b6df673 100644 --- a/pyforms/gui/Controls/ControlEventsGraph/__init__.py +++ b/pyforms/gui/Controls/control_events_graph/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -""" pyforms.gui.Controls.ControlEventTimeline.__init__ +""" pyforms.gui.controls.ControlEventTimeline.__init__ """ diff --git a/pyforms/gui/Controls/ControlPlayer/AbstractGLWidget.py b/pyforms/gui/Controls/control_player/AbstractGLWidget.py similarity index 95% rename from pyforms/gui/Controls/ControlPlayer/AbstractGLWidget.py rename to pyforms/gui/Controls/control_player/AbstractGLWidget.py index bdb8d14..699d0d5 100644 --- a/pyforms/gui/Controls/ControlPlayer/AbstractGLWidget.py +++ b/pyforms/gui/Controls/control_player/AbstractGLWidget.py @@ -1,38 +1,25 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -""" pyforms.gui.Controls.ControlPlayer.VideoGLWidget +""" pyforms.gui.controls.ControlPlayer.VideoGLWidget """ +import logging, cv2 -from pysettings import conf -import logging, math, pyforms.utils.tools as tools, time +from pysettings import conf +from AnyQt import QtGui, QtCore, _api +from AnyQt.QtWidgets import QApplication -if conf.PYFORMS_USE_QT5: - from PyQt5 import QtGui - from PyQt5 import QtCore - from PyQt5.QtWidgets import QApplication -else: - from PyQt4 import QtGui - from PyQt4 import QtCore - from PyQt4.QtGui import QApplication - -import OpenGL.GL as GL +import OpenGL.GL as GL import OpenGL.GLU as GLU -from pysettings import conf -try: - import cv2 -except: - print("Warning: was not possible to import cv2 in ControlPlayer") - -__author__ = "Ricardo Ribeiro" -__credits__ = ["Ricardo Ribeiro"] -__license__ = "MIT" -__version__ = "0.0" -__maintainer__ = "Ricardo Ribeiro" -__email__ = "ricardojvr@gmail.com" -__status__ = "Development" +__author__ = "Ricardo Ribeiro" +__credits__ = ["Ricardo Ribeiro"] +__license__ = "MIT" +__version__ = "0.0" +__maintainer__ = "Ricardo Ribeiro" +__email__ = "ricardojvr@gmail.com" +__status__ = "Development" class MouseEvent: @@ -351,10 +338,10 @@ def wheelEvent(self, event): self._mouseX = event.x() self._mouseY = event.y() - if conf.PYFORMS_USE_QT5: + if _api.USED_API == _api.QT_API_PYQT5: p = event.angleDelta() delta = p.y() - else: + elif _api.USED_API == _api.QT_API_PYQT4: delta = event.delta() zoom_factor = delta / float(1500) diff --git a/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py b/pyforms/gui/Controls/control_player/ControlPlayer.py similarity index 91% rename from pyforms/gui/Controls/ControlPlayer/ControlPlayer.py rename to pyforms/gui/Controls/control_player/ControlPlayer.py index ee0a3cb..f58ffe0 100755 --- a/pyforms/gui/Controls/ControlPlayer/ControlPlayer.py +++ b/pyforms/gui/Controls/control_player/ControlPlayer.py @@ -1,57 +1,38 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -""" pyforms.gui.Controls.ControlPlayer.ControlPlayer +""" pyforms.gui.controls.ControlPlayer.ControlPlayer """ +__author__ = "Ricardo Ribeiro" +__credits__ = ["Ricardo Ribeiro"] +__license__ = "MIT" +__version__ = "0.0" +__maintainer__ = "Ricardo Ribeiro" +__email__ = "ricardojvr@gmail.com" +__status__ = "Development" -import math -import os -import logging +import logging, platform, os, math, cv2 -from pysettings import conf -if conf.PYFORMS_USE_QT5: - from PyQt5 import uic - from PyQt5 import QtCore - from PyQt5.QtWidgets import QFrame - from PyQt5.QtWidgets import QApplication +from pysettings import conf +from AnyQt import uic, _api +from AnyQt import QtCore +from AnyQt.QtWidgets import QFrame +from AnyQt.QtWidgets import QApplication +from pyforms.gui.controls.ControlBase import ControlBase +if _api.USED_API == _api.QT_API_PYQT5: import platform - if platform.system() == 'Darwin': - from pyforms.gui.Controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + from pyforms.gui.controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget else: - from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget - -else: - from PyQt4.QtGui import QFrame - from PyQt4 import uic - from PyQt4 import QtCore - from PyQt4.QtGui import QApplication - from pyforms.gui.Controls.ControlPlayer.VideoGLWidget import VideoGLWidget - -from pyforms.gui.Controls.ControlBase import ControlBase -import pyforms.utils.tools as tools -from pysettings import conf - -try: - import cv2 -except: - print("Warning: was not possible to import cv2 in ControlPlayer") + from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget +elif _api.USED_API == _api.QT_API_PYQT4: + from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget - -__author__ = "Ricardo Ribeiro" -__credits__ = ["Ricardo Ribeiro"] -__license__ = "MIT" -__version__ = "0.0" -__maintainer__ = "Ricardo Ribeiro" -__email__ = "ricardojvr@gmail.com" -__status__ = "Development" - - class ControlPlayer(ControlBase, QFrame): _videoWidget = None diff --git a/pyforms/gui/Controls/control_player/VideoGLWidget.py b/pyforms/gui/Controls/control_player/VideoGLWidget.py new file mode 100644 index 0000000..9a3c22c --- /dev/null +++ b/pyforms/gui/Controls/control_player/VideoGLWidget.py @@ -0,0 +1,11 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" pyforms.gui.controls.ControlPlayer.VideoGLWidget + +""" + +from pyforms.gui.controls.ControlPlayer.AbstractGLWidget import AbstractGLWidget +from AnyQt.QtOpenGL import QGLWidget + +class VideoGLWidget(AbstractGLWidget, QGLWidget): pass \ No newline at end of file diff --git a/pyforms/gui/Controls/ControlPlayer/VideoQt5GLWidget.py b/pyforms/gui/Controls/control_player/VideoQt5GLWidget.py similarity index 88% rename from pyforms/gui/Controls/ControlPlayer/VideoQt5GLWidget.py rename to pyforms/gui/Controls/control_player/VideoQt5GLWidget.py index 5485d3f..c475272 100644 --- a/pyforms/gui/Controls/ControlPlayer/VideoQt5GLWidget.py +++ b/pyforms/gui/Controls/control_player/VideoQt5GLWidget.py @@ -1,9 +1,9 @@ -from pyforms.gui.Controls.ControlPlayer.AbstractGLWidget import AbstractGLWidget +from pyforms.gui.controls.ControlPlayer.AbstractGLWidget import AbstractGLWidget import math -from PyQt5 import QtGui -from PyQt5.QtWidgets import QOpenGLWidget -from PyQt5 import QtCore +from AnyQt import QtGui +from AnyQt.QtWidgets import QOpenGLWidget +from AnyQt import QtCore class VideoQt5GLWidget(AbstractGLWidget, QOpenGLWidget): diff --git a/pyforms/gui/Controls/ControlPlayer/__init__.py b/pyforms/gui/Controls/control_player/__init__.py similarity index 100% rename from pyforms/gui/Controls/ControlPlayer/__init__.py rename to pyforms/gui/Controls/control_player/__init__.py diff --git a/pyforms/gui/Controls/ControlPlayer/video.ui b/pyforms/gui/Controls/control_player/video.ui similarity index 100% rename from pyforms/gui/Controls/ControlPlayer/video.ui rename to pyforms/gui/Controls/control_player/video.ui diff --git a/pyforms/gui/Controls/dbquery.ui b/pyforms/gui/Controls/dbquery.ui deleted file mode 100755 index 67f380f..0000000 --- a/pyforms/gui/Controls/dbquery.ui +++ /dev/null @@ -1,52 +0,0 @@ - - - Form - - - - 0 - 0 - 471 - 168 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Form - - - - 0 - - - 0 - - - - - QAbstractItemView::SelectRows - - - - - - - - diff --git a/pyforms/gui/Controls/list_with_headers.ui b/pyforms/gui/Controls/list_with_headers.ui deleted file mode 100644 index 42ad4fd..0000000 --- a/pyforms/gui/Controls/list_with_headers.ui +++ /dev/null @@ -1,147 +0,0 @@ - - - Form - - - - 0 - 0 - 471 - 168 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Form - - - - 0 - - - 0 - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - false - - - Qt::NoPen - - - true - - - 100 - - - false - - - true - - - false - - - false - - - false - - - - column1 - - - - - column2 - - - - - - - - - 0 - - - 0 - - - - - - 16 - 16 - - - - + - - - - - - - - 16 - 16 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - diff --git a/pyforms/gui/Controls/table.ui b/pyforms/gui/Controls/table.ui deleted file mode 100644 index debb4f1..0000000 --- a/pyforms/gui/Controls/table.ui +++ /dev/null @@ -1,113 +0,0 @@ - - - Form - - - - 0 - 0 - 471 - 168 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Form - - - - 0 - - - 0 - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - false - - - - - - - - 0 - - - 0 - - - - - - 16 - 16 - - - - + - - - - - - - - 16 - 16 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - diff --git a/pyforms/gui/appmanager.py b/pyforms/gui/appmanager.py index 768ca5a..ed6d83f 100644 --- a/pyforms/gui/appmanager.py +++ b/pyforms/gui/appmanager.py @@ -1,68 +1,197 @@ -import sys, glob, os -import logging -import traceback -from PyQt4 import uic -from PyQt4 import QtGui, QtCore -import pyforms.utils.tools as tools - -class Container(object): +#!/usr/bin/python +# -*- coding: utf-8 -*- +from pyforms.gui.controls.ControlDockWidget import ControlDockWidget +from AnyQt.QtWidgets import QMainWindow, QDockWidget, QAction, QApplication +from AnyQt import QtCore, _api +from AnyQt.QtGui import QIcon + +from pysettings import conf +import sys, os, platform, logging + +logger = logging.getLogger(__name__) + +class StandAloneContainer(QMainWindow): def __init__(self, ClassObject): - - self.logger = logging.getLogger('pyforms') - - self._algorithm = ClassObject() - self._algorithm.init_form() - form_path = os.path.join(tools.get_object_class_path( Container ), 'mainWindow.ui') - self._form = uic.loadUi( form_path ) - self._form.verticalLayout.addWidget( self._algorithm ) - self._form.verticalLayout.setMargin(10) - self._form.verticalLayout.setSpacing(0) - - if conf.PYFORMS_USE_QT5: - self._form.verticalLayout.setContentsMargins(10,10,10,10) - else: - self._form.verticalLayout.setMargin(10) - - self._form.actionExit.triggered.connect( self.actionExit_triggered ) - self._form.show() - self._form.setWindowTitle( self._algorithm.title ) - self._form.actionStop.setEnabled(False) - self._form.actionStop.triggered.connect( self.actionStop_triggered ) - - try: - getattr(self._algorithm, 'execute') - self._form.actionRun.triggered.connect( self.actionRun_triggered ) - except: - self._form.menuAlgorithm.setEnabled(False) - self._form.actionRun.setEnabled(False) - self._form.menuAlgorithm.setVisible(False) - self._form.actionRun.setVisible(False) - - - def actionExit_triggered(self): exit() - def actionRun_triggered(self): - self._algorithm.stop = False - self._form.actionRun.setEnabled(False) - self._form.actionStop.setEnabled(True) - try: - self._algorithm.execute() - except Exception as err: - self.logger.warning("Error", exc_info=True) - self.actionStop_triggered() - - def actionStop_triggered(self): - self._algorithm.stop = True - self._form.actionRun.setEnabled(True) - self._form.actionStop.setEnabled(False) - - - -def start_app(ClassObject): + super(QMainWindow, self).__init__() + + w = ClassObject() + w.app_main_window = self + self._widget = w + + if len(w.mainmenu) > 0: + w._mainmenu = self.__initMainMenu(w.mainmenu) + + w.init_form() + + if _api.USED_API == _api.QT_API_PYQT5: + self.layout().setContentsMargins(conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN) + elif _api.USED_API == _api.QT_API_PYQT4: + self.layout().setMargin(conf.PYFORMS_MAINWINDOW_MARGIN) + + self.setCentralWidget(w) + self.setWindowTitle(w.title) + + docks = {} + for name, item in w.controls.items(): + if isinstance(item, ControlDockWidget): + if item.side not in docks: + docks[item.side] = [] + docks[item.side].append((name, item)) + + for key, widgets in docks.items(): + side = QtCore.Qt.RightDockWidgetArea + if key == 'left': + side = QtCore.Qt.LeftDockWidgetArea + elif key == 'right': + side = QtCore.Qt.RightDockWidgetArea + elif key == 'top': + side = QtCore.Qt.TopDockWidgetArea + elif key == 'bottom': + side = QtCore.Qt.BottomDockWidgetArea + else: + side = QtCore.Qt.LeftDockWidgetArea + + if isinstance(widgets, list): + widgets = sorted(widgets, key=lambda x: x[1].order) + + for name, widget in widgets: + dock = QDockWidget(self) + dock.setFeatures( + QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) + dock.setObjectName(name) + + if _api.USED_API == _api.QT_API_PYQT5: + dock.setContentsMargins(0,0,0,0) + widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) + elif _api.USED_API == _api.QT_API_PYQT4: + dock.setMargin(0) + widget.form.layout().setMargin(widget.margin) + + # print dock.objectName(),1 + dock.setWidget(widget.form) + dock.setWindowTitle(widget.label) + widget.dock = dock + if not widget._show: dock.hide() + + self.addDockWidget(side, dock) + else: + dock = QDockWidget(self) + dock.setFeatures( + QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) + # dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) + + if _api.USED_API == _api.QT_API_PYQT5: + widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) + elif _api.USED_API == _api.QT_API_PYQT5: + widget.form.layout().setMargin(widget.margin) + + # print dock.objectName(), 2 + dock.setObjectName(name) + dock.setWidget(widget.form) + self.addDockWidget(side, dock) + dock.setWindowTitle(widget.label) + widget.dock = dock + if not widget._show: dock.hide() + + if conf.PYFORMS_STYLESHEET: + stylesheet_files = [conf.PYFORMS_STYLESHEET] + + p = platform.system() + if p == 'Windows' and conf.PYFORMS_STYLESHEET_WINDOWS: + stylesheet_files.append(conf.PYFORMS_STYLESHEET_WINDOWS) + elif p == 'Darwin' and conf.PYFORMS_STYLESHEET_DARWIN: + stylesheet_files.append(conf.PYFORMS_STYLESHEET_DARWIN) + elif p == 'Linux' and conf.PYFORMS_STYLESHEET_LINUX: + stylesheet_files.append(conf.PYFORMS_STYLESHEET_LINUX) + + logger.debug('Import stylesheets: {0}'.format(stylesheet_files)) + self.loadStyleSheetFile(stylesheet_files) + + def closeEvent(self, event): + self._widget.closeEvent(event) + + def __initMainMenu(self, options, keys={}): + menubar = self.menuBar() + for menuIndex, m in enumerate(options): + for key, menus in m.items(): + menu = menubar.addMenu(key) + for subMenuIndex, m1 in enumerate(menus): + if isinstance(m1, str) and m1 == "-": + menu.addSeparator() + else: + for text, func in m1.items(): + if text != 'icon': + action = QAction(text, self) + if 'icon' in m1.keys(): + action.setIconVisibleInMenu(True) + action.setIcon(QIcon(m1['icon'])) + if func: + action.triggered.connect(func) + menu.addAction(action) + options[menuIndex][key][subMenuIndex][text] = action + break + return options + + def loadStyleSheetFile(self, files): + content = '' + for filename in files: + infile = open(filename, 'r') + content += infile.read() + '\n' + infile.close() + + self.setStyleSheet(content) + + +def execute_test_file(myapp): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("test_file", help="File with the tests script") + args = parser.parse_args() + + with open(args.test_file) as f: + global_vars = globals() + local_vars = locals() + code = compile(f.read(), args.test_file, 'exec') + exec(code, global_vars, local_vars) + + +def start_app(ClassObject, geometry=None): from pysettings import conf - app = QtGui.QApplication(sys.argv) + app = QApplication(sys.argv) conf += 'pyforms.gui.settings' - container = Container(ClassObject) - app.exec_() \ No newline at end of file + mainwindow = StandAloneContainer(ClassObject) + + myapp = mainwindow.centralWidget() + + if geometry is not None: + mainwindow.show() + mainwindow.setGeometry(*geometry) + else: + mainwindow.showMaximized() + + if conf.PYFORMS_QUALITY_TESTS_PATH is not None: + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("--test", help="File with the tests script") + args = parser.parse_args() + + if args.test: + TEST_PATH = os.path.join(conf.PYFORMS_QUALITY_TESTS_PATH, args.test) + TEST_FILE_PATH = os.path.join(TEST_PATH, args.test + '.py') + DATA_PATH = os.path.join(TEST_PATH, 'data', sys.platform) + INPUT_DATA_PATH = os.path.join(DATA_PATH, 'input-data') + OUTPUT_DATA_PATH = os.path.join(DATA_PATH, 'output-data') + EXPECTED_DATA_PATH = os.path.join(DATA_PATH, 'expected-data') + + with open(TEST_FILE_PATH) as f: + global_vars = {} # globals() + local_vars = locals() + code = compile(f.read(), TEST_FILE_PATH, 'exec') + + exec(code, global_vars, local_vars) + + app.exec_() + return myapp diff --git a/pyforms/gui/dialogs/csv_parser.py b/pyforms/gui/dialogs/csv_parser.py index 65be78e..c770170 100644 --- a/pyforms/gui/dialogs/csv_parser.py +++ b/pyforms/gui/dialogs/csv_parser.py @@ -1,10 +1,10 @@ import csv from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlFile -from pyforms.Controls import ControlList -from pyforms.Controls import ControlNumber +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlFile +from pyforms.controls import ControlList +from pyforms.controls import ControlNumber class CsvParserDialog(BaseWidget): diff --git a/pyforms/gui/dialogs/generic_csv_parser.py b/pyforms/gui/dialogs/generic_csv_parser.py index 418cc19..02ab52a 100644 --- a/pyforms/gui/dialogs/generic_csv_parser.py +++ b/pyforms/gui/dialogs/generic_csv_parser.py @@ -1,10 +1,10 @@ import csv from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlFile -from pyforms.Controls import ControlList -from pyforms.Controls import ControlNumber +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlFile +from pyforms.controls import ControlList +from pyforms.controls import ControlNumber class GenericCsvParserDialog(BaseWidget): diff --git a/pyforms/gui/mainWindow.ui b/pyforms/gui/mainWindow.ui deleted file mode 100755 index cae4f72..0000000 --- a/pyforms/gui/mainWindow.ui +++ /dev/null @@ -1,76 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 767 - 597 - - - - MainWindow - - - - - 0 - - - 0 - - - - - 0 - - - - - - - - - 0 - 0 - 767 - 25 - - - - - File - - - - - - Algorithm - - - - - - - - - - Quit - - - - - Run - - - - - Stop - - - - - - diff --git a/pyforms/gui/settings.py b/pyforms/gui/settings.py index 89ab5e8..95ade7a 100644 --- a/pyforms/gui/settings.py +++ b/pyforms/gui/settings.py @@ -2,20 +2,12 @@ # -*- coding: utf-8 -*- import os - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QStyle, qApp - from PyQt5.QtGui import QIcon, QPixmap - -else: - from PyQt4.QtGui import QStyle, qApp, QIcon, QPixmap +from AnyQt.QtGui import QIcon, QPixmap +from AnyQt.QtWidgets import QStyle, qApp def path(filename): - """ - + """ :param filename: :return: """ diff --git a/pyforms/gui/standaloneManager.py b/pyforms/gui/standaloneManager.py deleted file mode 100644 index 4e6ba0a..0000000 --- a/pyforms/gui/standaloneManager.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - - -import sys -import os, types -import inspect, platform -import logging - -from pysettings import conf - -from pysettings import conf - -if conf.PYFORMS_USE_QT5: - from PyQt5.QtWidgets import QMainWindow - from PyQt5.QtWidgets import QDockWidget - from PyQt5.QtWidgets import QAction - from PyQt5.QtWidgets import QApplication - from PyQt5 import QtCore - from PyQt5.QtGui import QIcon -else: - from PyQt4.QtGui import QMainWindow - from PyQt4.QtGui import QDockWidget - from PyQt4.QtGui import QAction - from PyQt4.QtGui import QIcon - from PyQt4.QtGui import QApplication - from PyQt4 import QtCore - -from pyforms.gui.Controls.ControlDockWidget import ControlDockWidget - -logger = logging.getLogger(__name__) - - -class StandAloneContainer(QMainWindow): - def __init__(self, ClassObject): - super(QMainWindow, self).__init__() - - w = ClassObject() - w.app_main_window = self - self._widget = w - - if len(w.mainmenu) > 0: - w._mainmenu = self.__initMainMenu(w.mainmenu) - - w.init_form() - - if conf.PYFORMS_USE_QT5: - self.layout().setContentsMargins(conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN) - else: - self.layout().setMargin(conf.PYFORMS_MAINWINDOW_MARGIN) - - self.setCentralWidget(w) - self.setWindowTitle(w.title) - - docks = {} - for name, item in w.controls.items(): - if isinstance(item, ControlDockWidget): - if item.side not in docks: - docks[item.side] = [] - docks[item.side].append((name, item)) - - for key, widgets in docks.items(): - side = QtCore.Qt.RightDockWidgetArea - if key == 'left': - side = QtCore.Qt.LeftDockWidgetArea - elif key == 'right': - side = QtCore.Qt.RightDockWidgetArea - elif key == 'top': - side = QtCore.Qt.TopDockWidgetArea - elif key == 'bottom': - side = QtCore.Qt.BottomDockWidgetArea - else: - side = QtCore.Qt.LeftDockWidgetArea - - if isinstance(widgets, list): - widgets = sorted(widgets, key=lambda x: x[1].order) - - for name, widget in widgets: - dock = QDockWidget(self) - dock.setFeatures( - QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) - dock.setObjectName(name) - - if conf.PYFORMS_USE_QT5: - dock.setContentsMargins(0,0,0,0) - widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) - else: - dock.setMargin(0) - widget.form.layout().setMargin(widget.margin) - - # print dock.objectName(),1 - dock.setWidget(widget.form) - dock.setWindowTitle(widget.label) - widget.dock = dock - if not widget._show: dock.hide() - - self.addDockWidget(side, dock) - else: - dock = QDockWidget(self) - dock.setFeatures( - QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) - # dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) - - if conf.PYFORMS_USE_QT5: - widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) - else: - widget.form.layout().setMargin(widget.margin) - - # print dock.objectName(), 2 - dock.setObjectName(name) - dock.setWidget(widget.form) - self.addDockWidget(side, dock) - dock.setWindowTitle(widget.label) - widget.dock = dock - if not widget._show: dock.hide() - - if conf.PYFORMS_STYLESHEET: - stylesheet_files = [conf.PYFORMS_STYLESHEET] - - p = platform.system() - if p == 'Windows' and conf.PYFORMS_STYLESHEET_WINDOWS: - stylesheet_files.append(conf.PYFORMS_STYLESHEET_WINDOWS) - elif p == 'Darwin' and conf.PYFORMS_STYLESHEET_DARWIN: - stylesheet_files.append(conf.PYFORMS_STYLESHEET_DARWIN) - elif p == 'Linux' and conf.PYFORMS_STYLESHEET_LINUX: - stylesheet_files.append(conf.PYFORMS_STYLESHEET_LINUX) - - logger.debug('Import stylesheets: {0}'.format(stylesheet_files)) - self.loadStyleSheetFile(stylesheet_files) - - def closeEvent(self, event): - self._widget.closeEvent(event) - - def __initMainMenu(self, options, keys={}): - menubar = self.menuBar() - for menuIndex, m in enumerate(options): - for key, menus in m.items(): - menu = menubar.addMenu(key) - for subMenuIndex, m1 in enumerate(menus): - if isinstance(m1, str) and m1 == "-": - menu.addSeparator() - else: - for text, func in m1.items(): - if text != 'icon': - action = QAction(text, self) - if 'icon' in m1.keys(): - action.setIconVisibleInMenu(True) - action.setIcon(QIcon(m1['icon'])) - if func: - action.triggered.connect(func) - menu.addAction(action) - options[menuIndex][key][subMenuIndex][text] = action - break - return options - - def loadStyleSheetFile(self, files): - content = '' - for filename in files: - infile = open(filename, 'r') - content += infile.read() + '\n' - infile.close() - - self.setStyleSheet(content) - - -def execute_test_file(myapp): - import argparse - parser = argparse.ArgumentParser() - parser.add_argument("test_file", help="File with the tests script") - args = parser.parse_args() - - with open(args.test_file) as f: - global_vars = globals() - local_vars = locals() - code = compile(f.read(), args.test_file, 'exec') - exec(code, global_vars, local_vars) - - -def start_app(ClassObject, geometry=None): - from pysettings import conf - - app = QApplication(sys.argv) - - conf += 'pyforms.gui.settings' - - mainwindow = StandAloneContainer(ClassObject) - - myapp = mainwindow.centralWidget() - - if geometry is not None: - mainwindow.show() - mainwindow.setGeometry(*geometry) - else: - mainwindow.showMaximized() - - if conf.PYFORMS_QUALITY_TESTS_PATH is not None: - import argparse - parser = argparse.ArgumentParser() - parser.add_argument("--test", help="File with the tests script") - args = parser.parse_args() - - if args.test: - TEST_PATH = os.path.join(conf.PYFORMS_QUALITY_TESTS_PATH, args.test) - TEST_FILE_PATH = os.path.join(TEST_PATH, args.test + '.py') - DATA_PATH = os.path.join(TEST_PATH, 'data', sys.platform) - INPUT_DATA_PATH = os.path.join(DATA_PATH, 'input-data') - OUTPUT_DATA_PATH = os.path.join(DATA_PATH, 'output-data') - EXPECTED_DATA_PATH = os.path.join(DATA_PATH, 'expected-data') - - with open(TEST_FILE_PATH) as f: - global_vars = {} # globals() - local_vars = locals() - code = compile(f.read(), TEST_FILE_PATH, 'exec') - - exec(code, global_vars, local_vars) - - app.exec_() - return myapp diff --git a/pyforms/settings.py b/pyforms/settings.py index 0441907..92b5a3f 100644 --- a/pyforms/settings.py +++ b/pyforms/settings.py @@ -28,9 +28,8 @@ # See pyforms.utils.plugins_finder.find_class() PYFORMS_SILENT_PLUGINS_FINDER = True -PYFORMS_USE_QT5 = True - -PYFORMS_MATPLOTLIB_ENABLED = True -PYFORMS_WEB_ENABLED = True -PYFORMS_GL_ENABLED = True -PYFORMS_VISVIS_ENABLED = True +PYFORMS_QSCINTILLA_ENABLED = True +PYFORMS_MATPLOTLIB_ENABLED = True +PYFORMS_WEB_ENABLED = True +PYFORMS_GL_ENABLED = True +PYFORMS_VISVIS_ENABLED = True diff --git a/pyforms/terminal/BaseWidget.py b/pyforms/terminal/BaseWidget.py index 97fc159..cdea3db 100755 --- a/pyforms/terminal/BaseWidget.py +++ b/pyforms/terminal/BaseWidget.py @@ -1,4 +1,4 @@ -from pyforms.Controls import ControlFile, ControlSlider, ControlText, ControlCombo, ControlCheckBox, ControlBase, ControlDir, ControlNumber +from pyforms.controls import ControlFile, ControlSlider, ControlText, ControlCombo, ControlCheckBox, ControlBase, ControlDir, ControlNumber from datetime import datetime, timedelta import argparse, uuid, os, shutil, time, sys, subprocess diff --git a/setup.py b/setup.py index 6ea86f8..1f7cec3 100644 --- a/setup.py +++ b/setup.py @@ -22,21 +22,10 @@ install_requires=[ "anyqt", ], - packages=[ - 'pyforms', - 'pyforms.utils', - 'pyforms.terminal', - 'pyforms.terminal.Controls', - 'pyforms.gui', - 'pyforms.gui.dialogs', - 'pyforms.gui.Controls', - 'pyforms.gui.Controls.ControlEventTimeline', - 'pyforms.gui.Controls.ControlEventsGraph', - 'pyforms.gui.Controls.ControlPlayer'], - + packages=find_packages(), package_data={'pyforms': [ - 'gui/Controls/uipics/*.png', - 'gui/mainWindow.ui', 'gui/Controls/*.ui', 'gui/Controls/ControlPlayer/*.ui', - 'gui/Controls/ControlEventTimeline/*.ui'] + 'gui/controls/uipics/*.png', + 'gui/mainWindow.ui', 'gui/controls/*.ui', 'gui/controls/control_player/*.ui', + 'gui/controls/control_events_timeline/*.ui'] }, ) diff --git a/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/__init__.py b/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/__init__.py index 0ca0ca9..31685a5 100644 --- a/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/__init__.py +++ b/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/__init__.py @@ -11,10 +11,10 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlSlider -from pyforms.Controls import ControlFile -from pyforms.Controls import ControlPlayer +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlSlider +from pyforms.controls import ControlFile +from pyforms.controls import ControlPlayer import pyforms \ No newline at end of file diff --git a/tutorials/1.SimpleExamples/SimpleExample1/__init__.py b/tutorials/1.SimpleExamples/SimpleExample1/__init__.py index a543081..540aab2 100644 --- a/tutorials/1.SimpleExamples/SimpleExample1/__init__.py +++ b/tutorials/1.SimpleExamples/SimpleExample1/__init__.py @@ -11,7 +11,7 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlMatplotlib +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlMatplotlib import pyforms \ No newline at end of file diff --git a/tutorials/1.SimpleExamples/SimpleExample2/__init__.py b/tutorials/1.SimpleExamples/SimpleExample2/__init__.py index b36dd67..6725787 100644 --- a/tutorials/1.SimpleExamples/SimpleExample2/__init__.py +++ b/tutorials/1.SimpleExamples/SimpleExample2/__init__.py @@ -10,7 +10,7 @@ __status__ = "Development" from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton import pyforms \ No newline at end of file diff --git a/tutorials/1.SimpleExamples/SimpleExample3/__init__.py b/tutorials/1.SimpleExamples/SimpleExample3/__init__.py index 60246a6..274f2e3 100644 --- a/tutorials/1.SimpleExamples/SimpleExample3/__init__.py +++ b/tutorials/1.SimpleExamples/SimpleExample3/__init__.py @@ -1,6 +1,6 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton import pyforms \ No newline at end of file diff --git a/tutorials/1.SimpleExamples/SimpleExample4/__init__.py b/tutorials/1.SimpleExamples/SimpleExample4/__init__.py index 60246a6..274f2e3 100644 --- a/tutorials/1.SimpleExamples/SimpleExample4/__init__.py +++ b/tutorials/1.SimpleExamples/SimpleExample4/__init__.py @@ -1,6 +1,6 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton import pyforms \ No newline at end of file diff --git a/tutorials/1.SimpleExamples/SimpleExample5/__init__.py b/tutorials/1.SimpleExamples/SimpleExample5/__init__.py index 60246a6..274f2e3 100644 --- a/tutorials/1.SimpleExamples/SimpleExample5/__init__.py +++ b/tutorials/1.SimpleExamples/SimpleExample5/__init__.py @@ -1,6 +1,6 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton import pyforms \ No newline at end of file diff --git a/tutorials/1.SimpleExamples/SimpleExample6/__init__.py b/tutorials/1.SimpleExamples/SimpleExample6/__init__.py index c093436..486a386 100644 --- a/tutorials/1.SimpleExamples/SimpleExample6/__init__.py +++ b/tutorials/1.SimpleExamples/SimpleExample6/__init__.py @@ -1,6 +1,6 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton import pyforms \ No newline at end of file diff --git a/tutorials/2.ControlsExamples/__init__.py b/tutorials/2.ControlsExamples/__init__.py index 32d5a79..7717b87 100644 --- a/tutorials/2.ControlsExamples/__init__.py +++ b/tutorials/2.ControlsExamples/__init__.py @@ -10,25 +10,25 @@ __status__ = "Development" from pyforms import BaseWidget -from pyforms.Controls import ControlBoundingSlider -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlCheckBox -from pyforms.Controls import ControlCheckBoxList -from pyforms.Controls import ControlCombo -from pyforms.Controls import ControlDir -from pyforms.Controls import ControlDockWidget -from pyforms.Controls import ControlEmptyWidget -from pyforms.Controls import ControlFile -from pyforms.Controls import ControlFilesTree -from pyforms.Controls import ControlImage -from pyforms.Controls import ControlList -from pyforms.Controls import ControlPlayer -from pyforms.Controls import ControlProgress -from pyforms.Controls import ControlSlider -from pyforms.Controls import ControlVisVis -from pyforms.Controls import ControlVisVisVolume -from pyforms.Controls import ControlEventTimeline -from pyforms.Controls import ControlCodeEditor +from pyforms.controls import ControlBoundingSlider +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlCheckBox +from pyforms.controls import ControlCheckBoxList +from pyforms.controls import ControlCombo +from pyforms.controls import ControlDir +from pyforms.controls import ControlDockWidget +from pyforms.controls import ControlEmptyWidget +from pyforms.controls import ControlFile +from pyforms.controls import ControlFilesTree +from pyforms.controls import ControlImage +from pyforms.controls import ControlList +from pyforms.controls import ControlPlayer +from pyforms.controls import ControlProgress +from pyforms.controls import ControlSlider +from pyforms.controls import ControlVisVis +from pyforms.controls import ControlVisVisVolume +from pyforms.controls import ControlEventTimeline +from pyforms.controls import ControlCodeEditor import pyforms \ No newline at end of file diff --git a/tutorials/3.CodeOrganization/PeopleWindow.py b/tutorials/3.CodeOrganization/PeopleWindow.py index 1854124..913d10f 100644 --- a/tutorials/3.CodeOrganization/PeopleWindow.py +++ b/tutorials/3.CodeOrganization/PeopleWindow.py @@ -3,7 +3,7 @@ from PersonWindow import PersonWindow from AddMenuFuntionality import AddMenuFuntionality -from pyforms.Controls import ControlDockWidget +from pyforms.controls import ControlDockWidget class PeopleWindow(AddMenuFuntionality, People, BaseWidget): diff --git a/tutorials/3.CodeOrganization/PersonWindow.py b/tutorials/3.CodeOrganization/PersonWindow.py index 4b98edc..05118f5 100644 --- a/tutorials/3.CodeOrganization/PersonWindow.py +++ b/tutorials/3.CodeOrganization/PersonWindow.py @@ -4,8 +4,8 @@ import pyforms from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton from Person import Person diff --git a/tutorials/3.CodeOrganization/__init__.py b/tutorials/3.CodeOrganization/__init__.py index 5ff2a7b..e712839 100644 --- a/tutorials/3.CodeOrganization/__init__.py +++ b/tutorials/3.CodeOrganization/__init__.py @@ -11,9 +11,9 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlList +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlList import pyforms diff --git a/tutorials/4.MdiApplication/Core/BaseWindow.py b/tutorials/4.MdiApplication/Core/BaseWindow.py index 78425ed..eb2cdac 100644 --- a/tutorials/4.MdiApplication/Core/BaseWindow.py +++ b/tutorials/4.MdiApplication/Core/BaseWindow.py @@ -1,10 +1,10 @@ import pyforms from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlDockWidget -from pyforms.Controls import ControlMdiArea +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlDockWidget +from pyforms.controls import ControlMdiArea from Core.SimpleExample1 import SimpleExample1 from Core.Controllers.ProjectTree import ProjectTree diff --git a/tutorials/4.MdiApplication/Core/Controllers/ProjectTree.py b/tutorials/4.MdiApplication/Core/Controllers/ProjectTree.py index c0a7a56..1b1aa28 100644 --- a/tutorials/4.MdiApplication/Core/Controllers/ProjectTree.py +++ b/tutorials/4.MdiApplication/Core/Controllers/ProjectTree.py @@ -3,9 +3,9 @@ from PyQt4 import QtGui, QtCore -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton -from pyforms.Controls import ControlTree +from pyforms.controls import ControlText +from pyforms.controls import ControlButton +from pyforms.controls import ControlTree class ProjectTree(BaseWidget): diff --git a/tutorials/4.MdiApplication/Core/SimpleExample1.py b/tutorials/4.MdiApplication/Core/SimpleExample1.py index f162d2e..4bc0078 100644 --- a/tutorials/4.MdiApplication/Core/SimpleExample1.py +++ b/tutorials/4.MdiApplication/Core/SimpleExample1.py @@ -12,8 +12,8 @@ from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton diff --git a/tutorials/Controls4Docs/__init__.py b/tutorials/Controls4Docs/__init__.py index a0df076..fa42181 100644 --- a/tutorials/Controls4Docs/__init__.py +++ b/tutorials/Controls4Docs/__init__.py @@ -11,5 +11,5 @@ from pyforms import BaseWidget -from pyforms.Controls import * +from pyforms.controls import * import pyforms \ No newline at end of file From ebb828545917e2348c06d02286e714fd1d40b0d6 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 23 Jan 2018 23:55:06 +0000 Subject: [PATCH 21/66] Fix some bugs with identation and imports --- pyforms/gui/BaseWidget.py | 90 +++++++++---------- pyforms/gui/Controls/ControlBoundingSlider.py | 8 +- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/BaseWidget.py index 75057a9..39655ce 100644 --- a/pyforms/gui/BaseWidget.py +++ b/pyforms/gui/BaseWidget.py @@ -3,7 +3,7 @@ import json -from pysettings import conf +from pysettings import conf from AnyQt.QtWidgets import QFrame from AnyQt.QtWidgets import QVBoxLayout from AnyQt.QtWidgets import QTabWidget @@ -12,10 +12,10 @@ from AnyQt.QtWidgets import QSpacerItem from AnyQt.QtWidgets import QSizePolicy from AnyQt.QtWidgets import QLabel -from AnyQt.QtGui import QFont +from AnyQt.QtGui import QFont from AnyQt.QtWidgets import QFileDialog from AnyQt.QtWidgets import QApplication -from AnyQt import QtCore, _api +from AnyQt import QtCore, _api from pyforms.gui.controls.ControlBase import ControlBase @@ -35,15 +35,15 @@ def __init__(self, *args, **kwargs): QFrame.__init__(self) if parent_win is None else QFrame.__init__(self, parent_win, win_flag) - layout = QVBoxLayout() - self.setLayout(layout) - - if _api.USED_API == _api.QT_API_PYQT5: - layout.setContentsMargins(0,0,0,0) - elif _api.USED_API == _api.QT_API_PYQT4: - layout.setMargin(0) + layout = QVBoxLayout() + self.setLayout(layout) + + if _api.USED_API == _api.QT_API_PYQT5: + layout.setContentsMargins(0,0,0,0) + elif _api.USED_API == _api.QT_API_PYQT4: + layout.setMargin(0) - self.title = title + self.title = title self.title = title self.has_progress = False @@ -67,23 +67,23 @@ def init_form(self): """ if not self._formLoaded: - - if self._formset is not None: - control = self.generate_panel(self._formset) - self.layout().addWidget(control) - else: - allparams = self.controls - for key, param in allparams.items(): - param.parent = self - param.name = key - self.layout().addWidget(param.form) - self._formLoaded = True - - def set_margin(self, margin): - if _api.USED_API == _api.QT_API_PYQT5: - self.layout().setContentsMargins(margin,margin,margin,margin) - elif _api.USED_API == _api.QT_API_PYQT4: - self.layout().setMargin(margin) + + if self._formset is not None: + control = self.generate_panel(self._formset) + self.layout().addWidget(control) + else: + allparams = self.controls + for key, param in allparams.items(): + param.parent = self + param.name = key + self.layout().addWidget(param.form) + self._formLoaded = True + + def set_margin(self, margin): + if _api.USED_API == _api.QT_API_PYQT5: + self.layout().setContentsMargins(margin,margin,margin,margin) + elif _api.USED_API == _api.QT_API_PYQT4: + self.layout().setMargin(margin) def generate_tabs(self, formsetdict): @@ -288,19 +288,19 @@ def generate_panel(self, formset): label.setToolTip(label.text()) - layout.addWidget(label) - else: - param.parent = self - param.name = row - layout.addWidget(param.form) - - if _api.USED_API == _api.QT_API_PYQT5: - layout.setContentsMargins(0,0,0,0) - elif _api.USED_API == _api.QT_API_PYQT4: - layout.setMargin(0) - - control.setLayout(layout) - return control + layout.addWidget(label) + else: + param.parent = self + param.name = row + layout.addWidget(param.form) + + if _api.USED_API == _api.QT_API_PYQT5: + layout.setContentsMargins(0,0,0,0) + elif _api.USED_API == _api.QT_API_PYQT4: + layout.setMargin(0) + + control.setLayout(layout) + return control def show(self): self.init_form() @@ -423,10 +423,10 @@ def form_has_loaded(self): - - @property - def visible(self): - return self.isVisible() + + @property + def visible(self): + return self.isVisible() @property def mainmenu(self): diff --git a/pyforms/gui/Controls/ControlBoundingSlider.py b/pyforms/gui/Controls/ControlBoundingSlider.py index 0cf8ac6..aaec0f3 100644 --- a/pyforms/gui/Controls/ControlBoundingSlider.py +++ b/pyforms/gui/Controls/ControlBoundingSlider.py @@ -277,10 +277,10 @@ def init_form(self): hlayout = QVBoxLayout() - if _api.USED_API == _api.QT_API_PYQT5: - hlayout.setContentsMargins(0,0,0,0) - elif _api.USED_API == _api.QT_API_PYQT4: - hlayout.setMargin(0) + if _api.USED_API == _api.QT_API_PYQT5: + hlayout.setContentsMargins(0,0,0,0) + elif _api.USED_API == _api.QT_API_PYQT4: + hlayout.setMargin(0) hwidget.setLayout(hlayout) From 8497384e2314d1208d5957b7c4f06d5066377f98 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 26 Jan 2018 22:53:11 +0000 Subject: [PATCH 22/66] . --- pyforms/Controls.py | 10 +++++----- pyforms/gui/appmanager.py | 1 + pyforms/settings.py | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pyforms/Controls.py b/pyforms/Controls.py index 67e6680..288c642 100644 --- a/pyforms/Controls.py +++ b/pyforms/Controls.py @@ -33,14 +33,14 @@ from pyforms.gui.controls.ControlMatplotlib import ControlMatplotlib except: logger.warning("Matplot lib not installed or not working properly") - logger.warning(traceback.format_exc()) + logger.debug(traceback.format_exc()) if conf.PYFORMS_WEB_ENABLED: try: from pyforms.gui.controls.ControlWeb import ControlWeb except: logger.warning("QtWebKit lib not installed or not working properly") - logger.warning(traceback.format_exc()) + logger.debug(traceback.format_exc()) if conf.PYFORMS_GL_ENABLED: try: @@ -49,7 +49,7 @@ from pyforms.gui.controls.control_player.ControlPlayer import ControlPlayer except: logger.warning("GL widgets or Opencv not installed") - logger.warning(traceback.format_exc()) + logger.debug(traceback.format_exc()) if conf.PYFORMS_VISVIS_ENABLED: try: @@ -57,13 +57,13 @@ from pyforms.gui.controls.ControlVisVisVolume import ControlVisVisVolume except: logger.warning("VisVis not installed") - logger.warning(traceback.format_exc()) + logger.debug(traceback.format_exc()) if conf.PYFORMS_QSCINTILLA_ENABLED: try: from pyforms.gui.controls.ControlCodeEditor import ControlCodeEditor except: - logger.debug("QScintilla2 not installed") + logger.warning("QScintilla2 not installed") logger.debug(traceback.format_exc()) diff --git a/pyforms/gui/appmanager.py b/pyforms/gui/appmanager.py index ed6d83f..1a1e080 100644 --- a/pyforms/gui/appmanager.py +++ b/pyforms/gui/appmanager.py @@ -107,6 +107,7 @@ def __init__(self, ClassObject): logger.debug('Import stylesheets: {0}'.format(stylesheet_files)) self.loadStyleSheetFile(stylesheet_files) + def closeEvent(self, event): self._widget.closeEvent(event) diff --git a/pyforms/settings.py b/pyforms/settings.py index 3fecb13..f350bca 100644 --- a/pyforms/settings.py +++ b/pyforms/settings.py @@ -11,7 +11,7 @@ PYFORMS_LOG_FILENAME = 'pyforms.log' -PYFORMS_LOG_HANDLER_FILE_LEVEL = logging.DEBUG +PYFORMS_LOG_HANDLER_FILE_LEVEL = logging.INFO PYFORMS_LOG_HANDLER_CONSOLE_LEVEL = logging.INFO PYFORMS_CONTROL_CODE_EDITOR_DEFAULT_FONT_SIZE = '12' From c51fc00348e655b9e3f0585ef6fa62fa5568814b Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 26 Jan 2018 23:13:20 +0000 Subject: [PATCH 23/66] . --- docs/api-documentation/controls.md | 43 +++++++++++++++++++++++ pyforms/gui/Controls/ControlCodeEditor.py | 4 +-- pyforms/gui/Controls/ControlCombo.py | 4 +-- pyforms/gui/Controls/ControlDockWidget.py | 10 +++--- pyforms/gui/Controls/ControlFile.py | 4 +-- pyforms/gui/Controls/ControlLabel.py | 3 -- pyforms/gui/Controls/ControlMatplotlib.py | 9 ++--- pyforms/gui/Controls/ControlMdiArea.py | 4 +-- pyforms/gui/Controls/ControlTree.py | 4 +-- pyforms/gui/Controls/ControlTreeView.py | 4 +-- 10 files changed, 62 insertions(+), 27 deletions(-) diff --git a/docs/api-documentation/controls.md b/docs/api-documentation/controls.md index cdd5bbe..fae83f5 100644 --- a/docs/api-documentation/controls.md +++ b/docs/api-documentation/controls.md @@ -831,6 +831,49 @@ Returns and sets the readonly flag for the control. +## ControlMatplotlib +*************************** + +![Docs updated](https://img.shields.io/badge/UNITARY%20TESTS-OK-green.svg "Screen") + +![Control image](https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/master/tutorials/Controls4Docs/ControlMatplotlib.png?raw=true "Screen") + +### **Functions** +*************************** + +#### draw() + +Draw the graph. + +### **Properties** +*************************** + +#### value + +Sets and gets a function called to draw the graph. This functions receives a matplotlib figure as parameter. + + +Usage: +```python + +def on_draw(figure): + """ Redraws the figure + """ + x = range(len(self.value)) + + #self._axes = self._fig.add_subplot(111) + + #self._axes.bar(left=x, height=self.data) + #self.canvas.draw() + + axes = figure.add_subplot(111, projection='3d') + axes.clear(); + pts = axes.scatter(x, x, x, c=x) + figure.colorbar(pts) + + +obj.value = on_draw +``` diff --git a/pyforms/gui/Controls/ControlCodeEditor.py b/pyforms/gui/Controls/ControlCodeEditor.py index 5a595c7..3cece18 100644 --- a/pyforms/gui/Controls/ControlCodeEditor.py +++ b/pyforms/gui/Controls/ControlCodeEditor.py @@ -29,7 +29,7 @@ class ControlCodeEditor(ControlBase): ARROW_MARKER_NUM = 8 - def __init__(self, label='', default='', helptext='', read_only=True): + def __init__(self, *args, **kwargs): """ :param label: @@ -38,7 +38,7 @@ def __init__(self, label='', default='', helptext='', read_only=True): """ self._read_only = read_only - super(ControlCodeEditor, self).__init__(label, default, helptext) + super(ControlCodeEditor, self).__init__(*args, **kwargs) self._changed_func = None diff --git a/pyforms/gui/Controls/ControlCombo.py b/pyforms/gui/Controls/ControlCombo.py index 9fc30a7..6965f67 100644 --- a/pyforms/gui/Controls/ControlCombo.py +++ b/pyforms/gui/Controls/ControlCombo.py @@ -14,9 +14,9 @@ class ControlCombo(ControlBase, QWidget): """This class represents a wrapper to the combo box""" - def __init__(self, label='', default=None, helptext=None): + def __init__(self, *args, **kwargs): QWidget.__init__(self) - ControlBase.__init__(self, label, default, helptext) + ControlBase.__init__(self, *args, **kwargs) ########################################################################## ############ Functions ################################################### diff --git a/pyforms/gui/Controls/ControlDockWidget.py b/pyforms/gui/Controls/ControlDockWidget.py index 0d967a8..8d81a21 100644 --- a/pyforms/gui/Controls/ControlDockWidget.py +++ b/pyforms/gui/Controls/ControlDockWidget.py @@ -11,11 +11,11 @@ class ControlDockWidget(ControlEmptyWidget): SIDE_BOTTOM = 'bottom' SIDE_DETACHED = 'detached' - def __init__(self, label='', default=None, side='left', order=0, margin=0): - ControlEmptyWidget.__init__(self, label) - self.side = side - self.order = order - self.margin = margin + def __init__(self, *args, **kwargs): + ControlEmptyWidget.__init__(self, *args, **kwargs) + self.side = kwargs.get('side', 'left') + self.order = kwargs.get('order',0) + self.margin = kwargs.get('margin', 0) if default is not None: self.value = default self._show = True diff --git a/pyforms/gui/Controls/ControlFile.py b/pyforms/gui/Controls/ControlFile.py index d7cb245..14c0ffb 100644 --- a/pyforms/gui/Controls/ControlFile.py +++ b/pyforms/gui/Controls/ControlFile.py @@ -13,9 +13,9 @@ class ControlFile(ControlText): - def __init__(self, label='', default=None, helptext=None, use_save_dialog=False): + def __init__(self, *args, **kwargs): super(ControlFile, self).__init__(label, default, helptext) - self.use_save_dialog = use_save_dialog + self.use_save_dialog = kwargs.get('use_save_dialog', False) def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "fileInput.ui") diff --git a/pyforms/gui/Controls/ControlLabel.py b/pyforms/gui/Controls/ControlLabel.py index 7aadbb3..8dce8e9 100644 --- a/pyforms/gui/Controls/ControlLabel.py +++ b/pyforms/gui/Controls/ControlLabel.py @@ -22,9 +22,6 @@ class ControlLabel(ControlBase): - def __init__(self, label=''): - super(ControlLabel, self).__init__(label=label, default=label) - def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "label.ui") self._form = uic.loadUi(control_path) diff --git a/pyforms/gui/Controls/ControlMatplotlib.py b/pyforms/gui/Controls/ControlMatplotlib.py index 797bb6d..b892f7f 100644 --- a/pyforms/gui/Controls/ControlMatplotlib.py +++ b/pyforms/gui/Controls/ControlMatplotlib.py @@ -33,9 +33,9 @@ class ControlMatplotlib(ControlBase, QWidget): - def __init__(self, label = ""): + def __init__(self, *args, **kwargs): QWidget.__init__(self) - ControlBase.__init__(self, label) + ControlBase.__init__(self, *args, **kwargs) def init_form(self): @@ -81,11 +81,6 @@ def on_draw(self, figure): ############ Properties #################################################### ############################################################################ - @property - def axes(self): return self._axes - @axes.setter - def axes(self, value): self._axes = value - @property def fig(self): return self._fig @fig.setter diff --git a/pyforms/gui/Controls/ControlMdiArea.py b/pyforms/gui/Controls/ControlMdiArea.py index 322ec53..eb6b114 100644 --- a/pyforms/gui/Controls/ControlMdiArea.py +++ b/pyforms/gui/Controls/ControlMdiArea.py @@ -18,9 +18,9 @@ class ControlMdiArea(ControlBase, QMdiArea): an area in which MDI windows are displayed. """ - def __init__(self, label=""): + def __init__(self, *args, **kwargs): QMdiArea.__init__(self) - ControlBase.__init__(self, label) + ControlBase.__init__(self, *args, **kwargs) self._showCloseButton = True self.logger = logging.getLogger(__name__) diff --git a/pyforms/gui/Controls/ControlTree.py b/pyforms/gui/Controls/ControlTree.py index 39223e4..07ce514 100644 --- a/pyforms/gui/Controls/ControlTree.py +++ b/pyforms/gui/Controls/ControlTree.py @@ -9,9 +9,9 @@ class ControlTree(ControlBase, QTreeWidget): """This class represents a wrapper to the QTreeWidget""" - def __init__(self, label='', default=''): + def __init__(self, *args, **kwargs): QTreeWidget.__init__(self) - ControlBase.__init__(self, label, default) + ControlBase.__init__(self, *args, **kwargs) def init_form(self): self.setSelectionBehavior(QAbstractItemView.SelectRows) diff --git a/pyforms/gui/Controls/ControlTreeView.py b/pyforms/gui/Controls/ControlTreeView.py index 2143501..a164265 100644 --- a/pyforms/gui/Controls/ControlTreeView.py +++ b/pyforms/gui/Controls/ControlTreeView.py @@ -7,9 +7,9 @@ class ControlTreeView(ControlBase, QTreeView): - def __init__(self, title='untitled'): + def __init__(self, *args, **kwargs): QTreeView.__init__(self) - ControlBase.__init__(self, title) + ControlBase.__init__(self, *args, **kwargs) def init_form(self): self.setSelectionBehavior(QAbstractItemView.SelectRows) From efb52fddc17d742d66ddb1da4d479758ff701d74 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 26 Jan 2018 23:32:38 +0000 Subject: [PATCH 24/66] . --- docs/api-documentation/controls.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/api-documentation/controls.md b/docs/api-documentation/controls.md index fae83f5..e9b296c 100644 --- a/docs/api-documentation/controls.md +++ b/docs/api-documentation/controls.md @@ -856,16 +856,9 @@ Sets and gets a function called to draw the graph. This functions receives a mat Usage: ```python -def on_draw(figure): - """ Redraws the figure - """ +def on_draw(figure: x = range(len(self.value)) - #self._axes = self._fig.add_subplot(111) - - #self._axes.bar(left=x, height=self.data) - #self.canvas.draw() - axes = figure.add_subplot(111, projection='3d') axes.clear(); pts = axes.scatter(x, x, x, c=x) From dcac500d7442e70031e3f170d7b0c2a384c05f5e Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Mon, 29 Jan 2018 11:01:35 +0000 Subject: [PATCH 25/66] Update CSV importer --- pyforms/gui/BaseWidget.py | 6 +- .../ControlEventTimeline/import_window.py | 373 +++++++++++------- pyforms/gui/dialogs/generic_csv_parser.py | 48 ++- 3 files changed, 270 insertions(+), 157 deletions(-) diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/BaseWidget.py index 11740b2..704f98d 100644 --- a/pyforms/gui/BaseWidget.py +++ b/pyforms/gui/BaseWidget.py @@ -27,6 +27,8 @@ from pyforms.gui.Controls.ControlBase import ControlBase from pyforms.gui.Controls.ControlProgress import ControlProgress +from AnyQt.QtWidgets import QMessageBox + class BaseWidget(QFrame): """ @@ -365,7 +367,9 @@ def load_window(self): def close(self): super(BaseWidget, self).close() - def message(self, msg, title=None, msg_type=None): pass + def message(self, msg, title=None, msg_type=''): + QMessageBox.information( self, title if title else msg_type, msg) + def success(self, msg, title=None): self.message(msg, title, msg_type='success') def info(self, msg, title=None): self.message(msg, title, msg_type='info') def warning(self, msg, title=None): self.message(msg, title, msg_type='warning'); diff --git a/pyforms/gui/Controls/ControlEventTimeline/import_window.py b/pyforms/gui/Controls/ControlEventTimeline/import_window.py index b76c53b..b0a1eca 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/import_window.py +++ b/pyforms/gui/Controls/ControlEventTimeline/import_window.py @@ -7,157 +7,246 @@ from pyforms.Controls import ControlFile from pyforms.Controls import ControlNumber - + import time import datetime - +import dateutil.parser class BonsaiImportFileDlg(BaseWidget): - def __init__(self, timeline=None): - super(BonsaiImportFileDlg, self).__init__('Import file') + def __init__(self, timeline=None): + super(BonsaiImportFileDlg, self).__init__('Import file') - self._file = ControlFile('File to import') - self._fps = ControlNumber('Video FPS', 30) + self._file = ControlFile('File to import') + self._fps = ControlNumber('Video FPS', 30) - self._formset = [('_fps', '_file')] + self._formset = [('_fps', '_file')] - #self._file.value = '/home/ricardo/Desktop/rat1e2.csv' + #self._file.value = '/home/ricardo/Desktop/rat1e2.csv' class ImportWindow(BaseWidget): - def __init__(self, timeline=None): - super(ImportWindow, self).__init__('Import file', parent_win=timeline) - self.setContentsMargins(10, 10, 10, 10) - self._timeline = timeline - - # Definition of the forms fields - self._filetype = ControlCombo('Please select the type of file you would like to import:') - self._importButton = ControlButton('Import') - self._panel = ControlEmptyWidget('Panel') - self._file = ControlFile('File to import') - - self._panel.value = self._file - self._filetype.add_item('Events file', 0) - self._filetype.add_item('Graph file', 1) - self._filetype.add_item('Bonsai events file', 2) - - self._formset = [ - ('_filetype', ' '), - '_panel', - (' ', '_importButton'), ' '] - - self._filetype.changed_event = self.__fileTypeChanged - self._importButton.value = self.__importData - - from pyforms.gui.dialogs.csv_parser import CsvParserDialog - self._graphCsvParserDlg = CsvParserDialog() - self._graphCsvParserDlg.xField.label = "Value column" - self._graphCsvParserDlg.yField.hide() - self._graphCsvParserDlg.zField.hide() - self._graphCsvParserDlg.loadButton.hide() - - self._bonsaiImportDlg = BonsaiImportFileDlg() - - def __fileTypeChanged(self): - if self._filetype.value == 0: - self._panel.value = self._file - - elif self._filetype.value == 1: - self._panel.value = self._graphCsvParserDlg - - elif self._filetype.value == 2: - self._panel.value = self._bonsaiImportDlg - - def __importData(self): - if self._filetype.value == 0: - separator = ',' - with open(self._file.value, 'rU') as csvfile: - line = csvfile.readline() - if ";" in line: - separator = ';' - with open(self._file.value, 'rU') as csvfile: - csvfile = csv.reader(csvfile, delimiter=separator) - self._timeline._time.import_csv(csvfile) - - elif self._filetype.value == 1: - self._timeline._time.importchart_csv(self._graphCsvParserDlg) - self._timeline.show_graphs_properties() - - elif self._filetype.value == 2: - with open(self._bonsaiImportDlg._file.value, 'rU') as csvfile: - values = [] - pointEventValues = [] - csvfile = csv.reader(csvfile, delimiter=' ') - for row in csvfile: # strip Start/End word from all events names which are not PointEven - try: - timestr = row[1].rstrip('0') - cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S.%f") - except: - timestr = row[1] - cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S") - - seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() - frame = int(round(self._bonsaiImportDlg._fps.value * seconds)) - - if row[2] == "PointEvent": - eventtype = row[0] - pointEventValues.append([eventtype, frame, row[2]]) - else: - if row[0].startswith('Start'): - eventtype = row[0][len('Start'):] # strip Start word from the beginning - else: - eventtype = row[0][len('End'):] # strip End word from the beginning - values.append([eventtype, frame, row[2]]) - - values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) - pointEventValues = sorted(pointEventValues, key=lambda x: (x[0].capitalize(), x[1])) - ntracks = len(set([x[0] for x in values])) + 1 - - # collapse - events = [] - eventsTypes = {} # Events names - currentTrack = 0 - for index in range(0, len(pointEventValues)): - pointEventValue = pointEventValues[index] - eventsTypes[pointEventValue[0]] = currentTrack - self._timeline.addPeriod([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], track=currentTrack) - - currentTrack = 1 - - for index in range(0, len(values), 2): - row0 = values[index] - row1 = values[index + 1] - - if row0[0] not in eventsTypes: - eventsTypes[row0[0]] = currentTrack - track = currentTrack - currentTrack += 1 - else: - track = eventsTypes[row0[0]] - - self._timeline.addPeriod([row0[1], row1[1], row0[0]], track=track) - - self._timeline.repaint() - self._timeline._time.repaint() - self.close() # pylint: disable=no-member - - - def import_chart(self, filename, frame_col=0, val_col=1): - self._filetype.value = 1 - self._graphCsvParserDlg.filename = filename - self._graphCsvParserDlg.frameColumn = frame_col - self._graphCsvParserDlg.xColumn = val_col - - - - -################################################################################################################## -################################################################################################################## -################################################################################################################## - -# Execute the application -if __name__ == "__main__": - import pyforms - pyforms.start_app(ImportWindow, geometry=(0, 0, 600, 400)) + def __init__(self, timeline=None): + super(ImportWindow, self).__init__('Import file', parent_win=timeline) + self.setContentsMargins(10, 10, 10, 10) + self._timeline = timeline + + # Definition of the forms fields + self._filetype = ControlCombo('Please select the type of file you would like to import:') + self._importButton = ControlButton('Import') + self._panel = ControlEmptyWidget('Panel') + self._file = ControlFile('File to import') + + self._panel.value = self._file + self._filetype.add_item('Events file', 0) + self._filetype.add_item('Graph file', 1) + self._filetype.add_item('Bonsai events file', 2) + self._filetype.add_item('Bonsai events file (old format)', 3) + + self._formset = [ + ('_filetype', ' '), + '_panel', + (' ', '_importButton'), ' '] + + self._filetype.changed_event = self.__fileTypeChanged + self._importButton.value = self.__importData + + from pyforms.gui.dialogs.csv_parser import CsvParserDialog + self._graphCsvParserDlg = CsvParserDialog() + self._graphCsvParserDlg.xField.label = "Value column" + self._graphCsvParserDlg.yField.hide() + self._graphCsvParserDlg.zField.hide() + self._graphCsvParserDlg.loadButton.hide() + + self._bonsai_import_dlg = BonsaiImportFileDlg() + + def __fileTypeChanged(self): + if self._filetype.value == 0: + self._panel.value = self._file + + elif self._filetype.value == 1: + self._panel.value = self._graphCsvParserDlg + + elif self._filetype.value in [2, 3]: + self._panel.value = self._bonsai_import_dlg + + + + + + + + + + + + + + def __importData(self): + if self._filetype.value == 0: + separator = ',' + with open(self._file.value, 'rU') as csvfile: + line = csvfile.readline() + if ";" in line: + separator = ';' + with open(self._file.value, 'rU') as csvfile: + csvfile = csv.reader(csvfile, delimiter=separator) + self._timeline._time.import_csv(csvfile) + + elif self._filetype.value == 1: + self._timeline._time.importchart_csv(self._graphCsvParserDlg) + self._timeline.show_graphs_properties() + + elif self._filetype.value == 2: + self.__import_bonsai_events() + elif self._filetype.value == 3: + self.__import_bonsai_events_oldformat() + + self._timeline.repaint() + self._timeline._time.repaint() + self.close() # pylint: disable=no-member + + + def import_chart(self, filename, frame_col=0, val_col=1): + self._filetype.value = 1 + self._graphCsvParserDlg.filename = filename + self._graphCsvParserDlg.frameColumn = frame_col + self._graphCsvParserDlg.xColumn = val_col + + + + def __import_bonsai_events(self): + + with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: + values = [] + pointEventValues = [] + csvfile = csv.reader(csvfile, delimiter=' ') + for row in csvfile: # strip Start/End word from all events names which are not PointEven + + try: + timestr = row[1].rstrip('0') + cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S.%f") + except: + timestr = row[1] + try: + print(timestr) + cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S") + except: + timestr = timestr.replace('T', ' ') + print(timestr) + cvttime = dateutil.parser.parse(timestr) + + seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() + frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) + + if row[2] == "PointEvent": + eventtype = row[0] + pointEventValues.append([eventtype, frame, row[2]]) + else: + if row[0].startswith('Start'): + eventtype = row[0][len('Start'):] # strip Start word from the beginning + else: + eventtype = row[0][len('End'):] # strip End word from the beginning + values.append([eventtype, frame, row[2]]) + + values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) + pointEventValues = sorted(pointEventValues, key=lambda x: (x[0].capitalize(), x[1])) + ntracks = len(set([x[0] for x in values])) + 1 + + # collapse + events = [] + eventsTypes = {} # Events names + currentTrack = 0 + for index in range(0, len(pointEventValues)): + pointEventValue = pointEventValues[index] + eventsTypes[pointEventValue[0]] = currentTrack + self._timeline.addPeriod([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], track=currentTrack) + + currentTrack = 1 + + for index in range(0, len(values), 2): + row0 = values[index] + row1 = values[index + 1] + + if row0[0] not in eventsTypes: + eventsTypes[row0[0]] = currentTrack + track = currentTrack + currentTrack += 1 + else: + track = eventsTypes[row0[0]] + + self._timeline.addPeriod([row0[1], row1[1], row0[0]], track=track) + + + + + def __import_bonsai_events_oldformat(self): + + with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: + windows_events = [] + points_events = [] + + for row in csvfile: + row = row[:-1] #remove the newline character + + if row.startswith('start'): + eventtype = 'start' + timestr = row[-33:] + eventname = row[:-33] + elif row.startswith('end'): + split = row.rfind(' ') + #eventtype = row[-split:] + eventtype = 'end' + timestr = row[-33-split:-split] + eventname = row[:-33-split] + else: + split = row.rfind(' ') + eventtype = row[split+1:] + timestr = row[split-33:split] + eventname = row[:-33-split] + + print(split) + print(eventtype) + print(timestr) + print(eventname) + + cvttime = dateutil.parser.parse(timestr.replace('T', ' ')) + seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() + frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) + + if eventtype=='PointEvent': + points_events.append([eventtype, frame, eventname]) + else: + if eventtype=='start': + windows_events.append( [[eventtype, frame, eventname]] ) + elif eventtype=='end': + windows_events[-1].append( [eventtype, frame, eventname] ) + + windows_events = sorted(windows_events, key=lambda x: (x[0][0].capitalize(), x[0][1])) + points_events = sorted(points_events, key=lambda x: (x[0].capitalize(), x[1])) + ntracks = len(set([x[0][1] for x in windows_events])) + 1 + + # collapse + events = [] + events_types = {} # Events names + current_track = 0 + for index in range(0, len(points_events)): + eventtype, frame, eventname = points_events[index] + events_types[eventname] = current_track + self._timeline.addPeriod([frame, frame + 50, eventname], track=current_track) + + current_track = 1 + + for start, end in windows_events: + eventtype, frame_begin, eventname = start + _, frame_end, _ = end + + if eventname not in events_types: + events_types[eventname] = current_track + track = current_track + current_track += 1 + else: + track = events_types[eventname] + + self._timeline.addPeriod([frame_begin, frame_end, eventname], track=track) \ No newline at end of file diff --git a/pyforms/gui/dialogs/generic_csv_parser.py b/pyforms/gui/dialogs/generic_csv_parser.py index d19d2b2..61f769d 100644 --- a/pyforms/gui/dialogs/generic_csv_parser.py +++ b/pyforms/gui/dialogs/generic_csv_parser.py @@ -5,6 +5,7 @@ from pyforms.Controls import ControlFile from pyforms.Controls import ControlList from pyforms.Controls import ControlNumber +from pyforms.Controls import ControlCombo class GenericCsvParserDialog(BaseWidget): @@ -17,15 +18,15 @@ def __init__(self, columns, parent=None): self._rownum = 0 # Definition of the forms fields - self._filename = ControlFile('CSV File') - self._separator = ControlText('Separator', default='auto') - self._startingrow = ControlNumber('Starting row', default=0) + self._filename = ControlFile('CSV File') + self._separator = ControlCombo('Separator', default='auto') + self._startingrow = ControlNumber('Starting row', default=0) for index, column in enumerate(columns): setattr(self, '_col_{0}'.format(index), ControlNumber(column, default=index, minimum=-1, maximum=1000)) self._filePreview = ControlList('Preview') - self._loadButton = ControlButton('Load') + self._loadButton = ControlButton('Load') form_row = ['_separator'] + ['_col_{0}'.format(index) for index, column in enumerate(columns)] + ['_loadButton'] @@ -41,6 +42,13 @@ def __init__(self, columns, parent=None): self._load_event = None + self._separator.add_item('auto', 'auto') + self._separator.add_item(';', ';') + self._separator.add_item(',', ',') + self._separator.add_item('TAB', '\t') + self._separator.add_item('Excel', csv.excel) + self._separator.add_item('Excel TAB', csv.excel_tab) + @property def load_file_event(self): return self._load_event @@ -53,12 +61,16 @@ def __iter__(self): if self._filename.value != None and self._filename.value != '': csvfile = open(self._filename.value, 'U') - if self._separator.value in ['auto']: - dialect = csv.Sniffer().sniff(csvfile.read(1024)) - csvfile.seek(0) - self._spamreader = csv.reader(csvfile, dialect) + if self.delimiter in ['auto', csv.excel, csv.excel_tab]: + try: + dialect = csv.Sniffer().sniff(csvfile.read(1024)) + csvfile.seek(0) + self._spamreader = csv.reader(csvfile, dialect) + except: + self._spamreader = None + return self else: - self._spamreader = csv.reader(csvfile, delimiter=self._separator.value) + self._spamreader = csv.reader(csvfile, delimiter=self.delimiter) for i in range(int(self._startingrow.value)): next(self._spamreader, None) # skip the headers else: self._spamreader = None @@ -91,12 +103,16 @@ def next(self): def __refreshPreview(self): if self._filename.value != None and self._filename.value != '': with open(self._filename.value, 'U') as csvfile: - if self._separator.value in ['auto']: - dialect = csv.Sniffer().sniff(csvfile.read(1024)) - csvfile.seek(0) - spamreader = csv.reader(csvfile, dialect) + if self.delimiter in ['auto', csv.excel, csv.excel_tab]: + try: + dialect = csv.Sniffer().sniff(csvfile.read(1024)) + csvfile.seek(0) + spamreader = csv.reader(csvfile, dialect) + except: + self.message('Error when reading the file.') + return else: - spamreader = csv.reader(csvfile, delimiter=self._separator.value) + spamreader = csv.reader(csvfile, delimiter=self.delimiter) for i in range(int(self._startingrow.value)): next(spamreader, None) # skip the headers self._filePreview.value = [] @@ -106,6 +122,10 @@ def __refreshPreview(self): if i >= 10: break + @property + def delimiter(self): + return self._separator.value + def load(self): self.__refreshPreview() self._columns_indexes = [] From 70696ddd7e8d89d92662d4f00f2280537e6b38d1 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 30 Jan 2018 13:03:12 +0000 Subject: [PATCH 26/66] Fix bugs --- docs/getting-started/the-basic.md | 8 ++++---- pyforms/gui/Controls/ControlDockWidget.py | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/getting-started/the-basic.md b/docs/getting-started/the-basic.md index a6a9013..fb0b632 100644 --- a/docs/getting-started/the-basic.md +++ b/docs/getting-started/the-basic.md @@ -16,8 +16,8 @@ Import the pyforms library, the BaseWidget and the Controls classes that you wil ```python import pyforms from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton ``` ### Create your application class. @@ -70,8 +70,8 @@ The final code should look like: ```python import pyforms from pyforms import BaseWidget -from pyforms.Controls import ControlText -from pyforms.Controls import ControlButton +from pyforms.controls import ControlText +from pyforms.controls import ControlButton class SimpleExample1(BaseWidget): diff --git a/pyforms/gui/Controls/ControlDockWidget.py b/pyforms/gui/Controls/ControlDockWidget.py index 8d81a21..35c2b48 100644 --- a/pyforms/gui/Controls/ControlDockWidget.py +++ b/pyforms/gui/Controls/ControlDockWidget.py @@ -16,6 +16,8 @@ def __init__(self, *args, **kwargs): self.side = kwargs.get('side', 'left') self.order = kwargs.get('order',0) self.margin = kwargs.get('margin', 0) + + default = kwargs.get('default', None) if default is not None: self.value = default self._show = True From cf66b8a8ee139ef8ef2de53061268fc62b0846a7 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 30 Jan 2018 13:08:17 +0000 Subject: [PATCH 27/66] Add form property to the basewidget --- pyforms/gui/BaseWidget.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/BaseWidget.py index 39655ce..357cee0 100644 --- a/pyforms/gui/BaseWidget.py +++ b/pyforms/gui/BaseWidget.py @@ -422,7 +422,9 @@ def form_has_loaded(self): return self._formLoaded - + @property + def form(self): + return self @property def visible(self): From 58b4a03fda0adadddb6c67a23b124dc6fd29bae0 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 30 Jan 2018 18:26:15 +0000 Subject: [PATCH 28/66] . --- pyforms/gui/Controls/ControlMdiArea.py | 1 + pyforms/utils/BioradWriter.py | 0 pyforms/utils/ImageBlobTools.py | 0 pyforms/utils/timeit.py | 0 pyforms/utils/tools.py | 0 5 files changed, 1 insertion(+) mode change 100644 => 100755 pyforms/utils/BioradWriter.py mode change 100644 => 100755 pyforms/utils/ImageBlobTools.py mode change 100644 => 100755 pyforms/utils/timeit.py mode change 100644 => 100755 pyforms/utils/tools.py diff --git a/pyforms/gui/Controls/ControlMdiArea.py b/pyforms/gui/Controls/ControlMdiArea.py index eb6b114..cf6037e 100644 --- a/pyforms/gui/Controls/ControlMdiArea.py +++ b/pyforms/gui/Controls/ControlMdiArea.py @@ -22,6 +22,7 @@ def __init__(self, *args, **kwargs): QMdiArea.__init__(self) ControlBase.__init__(self, *args, **kwargs) self._showCloseButton = True + self._openWindows = [] self.logger = logging.getLogger(__name__) diff --git a/pyforms/utils/BioradWriter.py b/pyforms/utils/BioradWriter.py old mode 100644 new mode 100755 diff --git a/pyforms/utils/ImageBlobTools.py b/pyforms/utils/ImageBlobTools.py old mode 100644 new mode 100755 diff --git a/pyforms/utils/timeit.py b/pyforms/utils/timeit.py old mode 100644 new mode 100755 diff --git a/pyforms/utils/tools.py b/pyforms/utils/tools.py old mode 100644 new mode 100755 From 0ecba57902bc08aa12b1c793bc5bbdbcbf763f8f Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 30 Jan 2018 18:33:59 +0000 Subject: [PATCH 29/66] rename to lowercase --- pyforms/{Controls.py => controls_.py} | 0 pyforms/gui/{BaseWidget.py => basewidget_.py} | 0 pyforms/gui/{Controls => controls_}/ControlBase.py | 0 .../ControlBoundingSlider.py | 0 .../gui/{Controls => controls_}/ControlButton.py | 0 .../gui/{Controls => controls_}/ControlCheckBox.py | 0 .../{Controls => controls_}/ControlCheckBoxList.py | 0 .../{Controls => controls_}/ControlCodeEditor.py | 0 pyforms/gui/{Controls => controls_}/ControlCombo.py | 0 pyforms/gui/{Controls => controls_}/ControlDir.py | 0 .../{Controls => controls_}/ControlDockWidget.py | 0 .../{Controls => controls_}/ControlEmptyWidget.py | 0 pyforms/gui/{Controls => controls_}/ControlFile.py | 0 .../gui/{Controls => controls_}/ControlFilesTree.py | 0 pyforms/gui/{Controls => controls_}/ControlImage.py | 0 pyforms/gui/{Controls => controls_}/ControlLabel.py | 0 pyforms/gui/{Controls => controls_}/ControlList.py | 0 .../{Controls => controls_}/ControlMatplotlib.py | 0 .../gui/{Controls => controls_}/ControlMdiArea.py | 0 .../gui/{Controls => controls_}/ControlNumber.py | 0 .../gui/{Controls => controls_}/ControlOpenGL.py | 0 .../gui/{Controls => controls_}/ControlProgress.py | 0 .../gui/{Controls => controls_}/ControlSlider.py | 0 pyforms/gui/{Controls => controls_}/ControlText.py | 0 .../gui/{Controls => controls_}/ControlTextArea.py | 0 .../gui/{Controls => controls_}/ControlToolBox.py | 0 pyforms/gui/{Controls => controls_}/ControlTree.py | 0 .../gui/{Controls => controls_}/ControlTreeView.py | 0 .../gui/{Controls => controls_}/ControlVisVis.py | 0 .../{Controls => controls_}/ControlVisVisVolume.py | 0 pyforms/gui/{Controls => controls_}/ControlWeb.py | 0 pyforms/gui/{Controls => controls_}/__init__.py | 0 pyforms/gui/{Controls => controls_}/button.ui | 0 pyforms/gui/{Controls => controls_}/checkbox.ui | 0 pyforms/gui/{Controls => controls_}/code_editor.ui | 0 .../control_event_timeline/ControlEventTimeline.py | 0 .../control_event_timeline/TimelineChart.py | 0 .../control_event_timeline/TimelineDelta.py | 0 .../control_event_timeline/TimelinePointer.py | 0 .../control_event_timeline/TimelinePopupWindow.py | 0 .../control_event_timeline/TimelinePopupWindow.ui | 0 .../control_event_timeline/TimelineWidget.py | 0 .../control_event_timeline/Track.py | 0 .../control_event_timeline/__init__.py | 0 .../graphs_eventsgenerator.py | 0 .../control_event_timeline/graphs_graph2event.py | 0 .../control_event_timeline/graphs_properties.py | 0 .../control_event_timeline/import_window.py | 0 .../control_events_graph/ControlEventsGraph.py | 0 .../control_events_graph/Event.py | 0 .../control_events_graph/EventsWidget.py | 0 .../control_events_graph/Pointer.py | 0 .../control_events_graph/Track.py | 0 .../control_events_graph/__init__.py | 0 .../control_player/AbstractGLWidget.py | 0 .../control_player/ControlPlayer.py | 0 .../control_player/VideoGLWidget.py | 0 .../control_player/VideoQt5GLWidget.py | 0 .../control_player/__init__.py | 0 .../{Controls => controls_}/control_player/video.ui | 0 pyforms/gui/{Controls => controls_}/fileInput.ui | 0 pyforms/gui/{Controls => controls_}/image.ui | 0 pyforms/gui/{Controls => controls_}/label.ui | 0 pyforms/gui/{Controls => controls_}/list.ui | 0 pyforms/gui/{Controls => controls_}/number.ui | 0 .../gui/{Controls => controls_}/progressInput.ui | 0 pyforms/gui/{Controls => controls_}/sliderInput.ui | 0 pyforms/gui/{Controls => controls_}/textArea.ui | 0 pyforms/gui/{Controls => controls_}/textInput.ui | 0 pyforms/gui/{Controls => controls_}/tree.ui | 0 pyforms/gui/{Controls => controls_}/uipics/add.png | Bin pyforms/gui/{Controls => controls_}/uipics/film.png | Bin .../{Controls => controls_}/uipics/film_edit.png | Bin .../gui/{Controls => controls_}/uipics/graph.png | Bin .../uipics/page_white_get.png | Bin .../uipics/page_white_put.png | Bin .../gui/{Controls => controls_}/uipics/refresh.png | Bin .../gui/{Controls => controls_}/uipics/remove.png | Bin .../gui/{Controls => controls_}/uipics/timeline.png | Bin .../gui/{Controls => controls_}/uipics/zoom_in.png | Bin .../gui/{Controls => controls_}/uipics/zoom_out.png | Bin pyforms/terminal/{BaseWidget.py => basewidget_.py} | 0 .../terminal/{Controls => controls_}/ControlBase.py | 0 .../ControlBoundingSlider.py | 0 .../{Controls => controls_}/ControlButton.py | 0 .../{Controls => controls_}/ControlCheckBox.py | 0 .../{Controls => controls_}/ControlCheckBoxList.py | 0 .../{Controls => controls_}/ControlCombo.py | 0 .../terminal/{Controls => controls_}/ControlDir.py | 0 .../{Controls => controls_}/ControlEmptyWidget.py | 0 .../terminal/{Controls => controls_}/ControlFile.py | 0 .../{Controls => controls_}/ControlImage.py | 0 .../{Controls => controls_}/ControlLabel.py | 0 .../terminal/{Controls => controls_}/ControlList.py | 0 .../{Controls => controls_}/ControlNumber.py | 0 .../{Controls => controls_}/ControlPlayer.py | 0 .../{Controls => controls_}/ControlProgress.py | 0 .../{Controls => controls_}/ControlSlider.py | 0 .../terminal/{Controls => controls_}/ControlText.py | 0 .../{Controls => controls_}/ControlTextArea.py | 0 .../{Controls => controls_}/ControlToolBox.py | 0 .../terminal/{Controls => controls_}/ControlTree.py | 0 .../terminal/{Controls => controls_}/__init__.py | 0 103 files changed, 0 insertions(+), 0 deletions(-) rename pyforms/{Controls.py => controls_.py} (100%) rename pyforms/gui/{BaseWidget.py => basewidget_.py} (100%) rename pyforms/gui/{Controls => controls_}/ControlBase.py (100%) rename pyforms/gui/{Controls => controls_}/ControlBoundingSlider.py (100%) rename pyforms/gui/{Controls => controls_}/ControlButton.py (100%) rename pyforms/gui/{Controls => controls_}/ControlCheckBox.py (100%) rename pyforms/gui/{Controls => controls_}/ControlCheckBoxList.py (100%) rename pyforms/gui/{Controls => controls_}/ControlCodeEditor.py (100%) rename pyforms/gui/{Controls => controls_}/ControlCombo.py (100%) rename pyforms/gui/{Controls => controls_}/ControlDir.py (100%) rename pyforms/gui/{Controls => controls_}/ControlDockWidget.py (100%) rename pyforms/gui/{Controls => controls_}/ControlEmptyWidget.py (100%) rename pyforms/gui/{Controls => controls_}/ControlFile.py (100%) rename pyforms/gui/{Controls => controls_}/ControlFilesTree.py (100%) rename pyforms/gui/{Controls => controls_}/ControlImage.py (100%) rename pyforms/gui/{Controls => controls_}/ControlLabel.py (100%) rename pyforms/gui/{Controls => controls_}/ControlList.py (100%) rename pyforms/gui/{Controls => controls_}/ControlMatplotlib.py (100%) rename pyforms/gui/{Controls => controls_}/ControlMdiArea.py (100%) rename pyforms/gui/{Controls => controls_}/ControlNumber.py (100%) rename pyforms/gui/{Controls => controls_}/ControlOpenGL.py (100%) rename pyforms/gui/{Controls => controls_}/ControlProgress.py (100%) rename pyforms/gui/{Controls => controls_}/ControlSlider.py (100%) rename pyforms/gui/{Controls => controls_}/ControlText.py (100%) rename pyforms/gui/{Controls => controls_}/ControlTextArea.py (100%) rename pyforms/gui/{Controls => controls_}/ControlToolBox.py (100%) rename pyforms/gui/{Controls => controls_}/ControlTree.py (100%) rename pyforms/gui/{Controls => controls_}/ControlTreeView.py (100%) rename pyforms/gui/{Controls => controls_}/ControlVisVis.py (100%) rename pyforms/gui/{Controls => controls_}/ControlVisVisVolume.py (100%) rename pyforms/gui/{Controls => controls_}/ControlWeb.py (100%) rename pyforms/gui/{Controls => controls_}/__init__.py (100%) rename pyforms/gui/{Controls => controls_}/button.ui (100%) rename pyforms/gui/{Controls => controls_}/checkbox.ui (100%) rename pyforms/gui/{Controls => controls_}/code_editor.ui (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/ControlEventTimeline.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/TimelineChart.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/TimelineDelta.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/TimelinePointer.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/TimelinePopupWindow.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/TimelinePopupWindow.ui (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/TimelineWidget.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/Track.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/__init__.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/graphs_eventsgenerator.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/graphs_graph2event.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/graphs_properties.py (100%) rename pyforms/gui/{Controls => controls_}/control_event_timeline/import_window.py (100%) rename pyforms/gui/{Controls => controls_}/control_events_graph/ControlEventsGraph.py (100%) rename pyforms/gui/{Controls => controls_}/control_events_graph/Event.py (100%) rename pyforms/gui/{Controls => controls_}/control_events_graph/EventsWidget.py (100%) rename pyforms/gui/{Controls => controls_}/control_events_graph/Pointer.py (100%) rename pyforms/gui/{Controls => controls_}/control_events_graph/Track.py (100%) rename pyforms/gui/{Controls => controls_}/control_events_graph/__init__.py (100%) rename pyforms/gui/{Controls => controls_}/control_player/AbstractGLWidget.py (100%) rename pyforms/gui/{Controls => controls_}/control_player/ControlPlayer.py (100%) rename pyforms/gui/{Controls => controls_}/control_player/VideoGLWidget.py (100%) rename pyforms/gui/{Controls => controls_}/control_player/VideoQt5GLWidget.py (100%) rename pyforms/gui/{Controls => controls_}/control_player/__init__.py (100%) rename pyforms/gui/{Controls => controls_}/control_player/video.ui (100%) rename pyforms/gui/{Controls => controls_}/fileInput.ui (100%) rename pyforms/gui/{Controls => controls_}/image.ui (100%) rename pyforms/gui/{Controls => controls_}/label.ui (100%) rename pyforms/gui/{Controls => controls_}/list.ui (100%) rename pyforms/gui/{Controls => controls_}/number.ui (100%) rename pyforms/gui/{Controls => controls_}/progressInput.ui (100%) rename pyforms/gui/{Controls => controls_}/sliderInput.ui (100%) rename pyforms/gui/{Controls => controls_}/textArea.ui (100%) rename pyforms/gui/{Controls => controls_}/textInput.ui (100%) rename pyforms/gui/{Controls => controls_}/tree.ui (100%) rename pyforms/gui/{Controls => controls_}/uipics/add.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/film.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/film_edit.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/graph.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/page_white_get.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/page_white_put.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/refresh.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/remove.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/timeline.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/zoom_in.png (100%) rename pyforms/gui/{Controls => controls_}/uipics/zoom_out.png (100%) rename pyforms/terminal/{BaseWidget.py => basewidget_.py} (100%) rename pyforms/terminal/{Controls => controls_}/ControlBase.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlBoundingSlider.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlButton.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlCheckBox.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlCheckBoxList.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlCombo.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlDir.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlEmptyWidget.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlFile.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlImage.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlLabel.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlList.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlNumber.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlPlayer.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlProgress.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlSlider.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlText.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlTextArea.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlToolBox.py (100%) rename pyforms/terminal/{Controls => controls_}/ControlTree.py (100%) rename pyforms/terminal/{Controls => controls_}/__init__.py (100%) diff --git a/pyforms/Controls.py b/pyforms/controls_.py similarity index 100% rename from pyforms/Controls.py rename to pyforms/controls_.py diff --git a/pyforms/gui/BaseWidget.py b/pyforms/gui/basewidget_.py similarity index 100% rename from pyforms/gui/BaseWidget.py rename to pyforms/gui/basewidget_.py diff --git a/pyforms/gui/Controls/ControlBase.py b/pyforms/gui/controls_/ControlBase.py similarity index 100% rename from pyforms/gui/Controls/ControlBase.py rename to pyforms/gui/controls_/ControlBase.py diff --git a/pyforms/gui/Controls/ControlBoundingSlider.py b/pyforms/gui/controls_/ControlBoundingSlider.py similarity index 100% rename from pyforms/gui/Controls/ControlBoundingSlider.py rename to pyforms/gui/controls_/ControlBoundingSlider.py diff --git a/pyforms/gui/Controls/ControlButton.py b/pyforms/gui/controls_/ControlButton.py similarity index 100% rename from pyforms/gui/Controls/ControlButton.py rename to pyforms/gui/controls_/ControlButton.py diff --git a/pyforms/gui/Controls/ControlCheckBox.py b/pyforms/gui/controls_/ControlCheckBox.py similarity index 100% rename from pyforms/gui/Controls/ControlCheckBox.py rename to pyforms/gui/controls_/ControlCheckBox.py diff --git a/pyforms/gui/Controls/ControlCheckBoxList.py b/pyforms/gui/controls_/ControlCheckBoxList.py similarity index 100% rename from pyforms/gui/Controls/ControlCheckBoxList.py rename to pyforms/gui/controls_/ControlCheckBoxList.py diff --git a/pyforms/gui/Controls/ControlCodeEditor.py b/pyforms/gui/controls_/ControlCodeEditor.py similarity index 100% rename from pyforms/gui/Controls/ControlCodeEditor.py rename to pyforms/gui/controls_/ControlCodeEditor.py diff --git a/pyforms/gui/Controls/ControlCombo.py b/pyforms/gui/controls_/ControlCombo.py similarity index 100% rename from pyforms/gui/Controls/ControlCombo.py rename to pyforms/gui/controls_/ControlCombo.py diff --git a/pyforms/gui/Controls/ControlDir.py b/pyforms/gui/controls_/ControlDir.py similarity index 100% rename from pyforms/gui/Controls/ControlDir.py rename to pyforms/gui/controls_/ControlDir.py diff --git a/pyforms/gui/Controls/ControlDockWidget.py b/pyforms/gui/controls_/ControlDockWidget.py similarity index 100% rename from pyforms/gui/Controls/ControlDockWidget.py rename to pyforms/gui/controls_/ControlDockWidget.py diff --git a/pyforms/gui/Controls/ControlEmptyWidget.py b/pyforms/gui/controls_/ControlEmptyWidget.py similarity index 100% rename from pyforms/gui/Controls/ControlEmptyWidget.py rename to pyforms/gui/controls_/ControlEmptyWidget.py diff --git a/pyforms/gui/Controls/ControlFile.py b/pyforms/gui/controls_/ControlFile.py similarity index 100% rename from pyforms/gui/Controls/ControlFile.py rename to pyforms/gui/controls_/ControlFile.py diff --git a/pyforms/gui/Controls/ControlFilesTree.py b/pyforms/gui/controls_/ControlFilesTree.py similarity index 100% rename from pyforms/gui/Controls/ControlFilesTree.py rename to pyforms/gui/controls_/ControlFilesTree.py diff --git a/pyforms/gui/Controls/ControlImage.py b/pyforms/gui/controls_/ControlImage.py similarity index 100% rename from pyforms/gui/Controls/ControlImage.py rename to pyforms/gui/controls_/ControlImage.py diff --git a/pyforms/gui/Controls/ControlLabel.py b/pyforms/gui/controls_/ControlLabel.py similarity index 100% rename from pyforms/gui/Controls/ControlLabel.py rename to pyforms/gui/controls_/ControlLabel.py diff --git a/pyforms/gui/Controls/ControlList.py b/pyforms/gui/controls_/ControlList.py similarity index 100% rename from pyforms/gui/Controls/ControlList.py rename to pyforms/gui/controls_/ControlList.py diff --git a/pyforms/gui/Controls/ControlMatplotlib.py b/pyforms/gui/controls_/ControlMatplotlib.py similarity index 100% rename from pyforms/gui/Controls/ControlMatplotlib.py rename to pyforms/gui/controls_/ControlMatplotlib.py diff --git a/pyforms/gui/Controls/ControlMdiArea.py b/pyforms/gui/controls_/ControlMdiArea.py similarity index 100% rename from pyforms/gui/Controls/ControlMdiArea.py rename to pyforms/gui/controls_/ControlMdiArea.py diff --git a/pyforms/gui/Controls/ControlNumber.py b/pyforms/gui/controls_/ControlNumber.py similarity index 100% rename from pyforms/gui/Controls/ControlNumber.py rename to pyforms/gui/controls_/ControlNumber.py diff --git a/pyforms/gui/Controls/ControlOpenGL.py b/pyforms/gui/controls_/ControlOpenGL.py similarity index 100% rename from pyforms/gui/Controls/ControlOpenGL.py rename to pyforms/gui/controls_/ControlOpenGL.py diff --git a/pyforms/gui/Controls/ControlProgress.py b/pyforms/gui/controls_/ControlProgress.py similarity index 100% rename from pyforms/gui/Controls/ControlProgress.py rename to pyforms/gui/controls_/ControlProgress.py diff --git a/pyforms/gui/Controls/ControlSlider.py b/pyforms/gui/controls_/ControlSlider.py similarity index 100% rename from pyforms/gui/Controls/ControlSlider.py rename to pyforms/gui/controls_/ControlSlider.py diff --git a/pyforms/gui/Controls/ControlText.py b/pyforms/gui/controls_/ControlText.py similarity index 100% rename from pyforms/gui/Controls/ControlText.py rename to pyforms/gui/controls_/ControlText.py diff --git a/pyforms/gui/Controls/ControlTextArea.py b/pyforms/gui/controls_/ControlTextArea.py similarity index 100% rename from pyforms/gui/Controls/ControlTextArea.py rename to pyforms/gui/controls_/ControlTextArea.py diff --git a/pyforms/gui/Controls/ControlToolBox.py b/pyforms/gui/controls_/ControlToolBox.py similarity index 100% rename from pyforms/gui/Controls/ControlToolBox.py rename to pyforms/gui/controls_/ControlToolBox.py diff --git a/pyforms/gui/Controls/ControlTree.py b/pyforms/gui/controls_/ControlTree.py similarity index 100% rename from pyforms/gui/Controls/ControlTree.py rename to pyforms/gui/controls_/ControlTree.py diff --git a/pyforms/gui/Controls/ControlTreeView.py b/pyforms/gui/controls_/ControlTreeView.py similarity index 100% rename from pyforms/gui/Controls/ControlTreeView.py rename to pyforms/gui/controls_/ControlTreeView.py diff --git a/pyforms/gui/Controls/ControlVisVis.py b/pyforms/gui/controls_/ControlVisVis.py similarity index 100% rename from pyforms/gui/Controls/ControlVisVis.py rename to pyforms/gui/controls_/ControlVisVis.py diff --git a/pyforms/gui/Controls/ControlVisVisVolume.py b/pyforms/gui/controls_/ControlVisVisVolume.py similarity index 100% rename from pyforms/gui/Controls/ControlVisVisVolume.py rename to pyforms/gui/controls_/ControlVisVisVolume.py diff --git a/pyforms/gui/Controls/ControlWeb.py b/pyforms/gui/controls_/ControlWeb.py similarity index 100% rename from pyforms/gui/Controls/ControlWeb.py rename to pyforms/gui/controls_/ControlWeb.py diff --git a/pyforms/gui/Controls/__init__.py b/pyforms/gui/controls_/__init__.py similarity index 100% rename from pyforms/gui/Controls/__init__.py rename to pyforms/gui/controls_/__init__.py diff --git a/pyforms/gui/Controls/button.ui b/pyforms/gui/controls_/button.ui similarity index 100% rename from pyforms/gui/Controls/button.ui rename to pyforms/gui/controls_/button.ui diff --git a/pyforms/gui/Controls/checkbox.ui b/pyforms/gui/controls_/checkbox.ui similarity index 100% rename from pyforms/gui/Controls/checkbox.ui rename to pyforms/gui/controls_/checkbox.ui diff --git a/pyforms/gui/Controls/code_editor.ui b/pyforms/gui/controls_/code_editor.ui similarity index 100% rename from pyforms/gui/Controls/code_editor.ui rename to pyforms/gui/controls_/code_editor.ui diff --git a/pyforms/gui/Controls/control_event_timeline/ControlEventTimeline.py b/pyforms/gui/controls_/control_event_timeline/ControlEventTimeline.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/ControlEventTimeline.py rename to pyforms/gui/controls_/control_event_timeline/ControlEventTimeline.py diff --git a/pyforms/gui/Controls/control_event_timeline/TimelineChart.py b/pyforms/gui/controls_/control_event_timeline/TimelineChart.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/TimelineChart.py rename to pyforms/gui/controls_/control_event_timeline/TimelineChart.py diff --git a/pyforms/gui/Controls/control_event_timeline/TimelineDelta.py b/pyforms/gui/controls_/control_event_timeline/TimelineDelta.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/TimelineDelta.py rename to pyforms/gui/controls_/control_event_timeline/TimelineDelta.py diff --git a/pyforms/gui/Controls/control_event_timeline/TimelinePointer.py b/pyforms/gui/controls_/control_event_timeline/TimelinePointer.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/TimelinePointer.py rename to pyforms/gui/controls_/control_event_timeline/TimelinePointer.py diff --git a/pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.py b/pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.py rename to pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.py diff --git a/pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.ui b/pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.ui similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/TimelinePopupWindow.ui rename to pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.ui diff --git a/pyforms/gui/Controls/control_event_timeline/TimelineWidget.py b/pyforms/gui/controls_/control_event_timeline/TimelineWidget.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/TimelineWidget.py rename to pyforms/gui/controls_/control_event_timeline/TimelineWidget.py diff --git a/pyforms/gui/Controls/control_event_timeline/Track.py b/pyforms/gui/controls_/control_event_timeline/Track.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/Track.py rename to pyforms/gui/controls_/control_event_timeline/Track.py diff --git a/pyforms/gui/Controls/control_event_timeline/__init__.py b/pyforms/gui/controls_/control_event_timeline/__init__.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/__init__.py rename to pyforms/gui/controls_/control_event_timeline/__init__.py diff --git a/pyforms/gui/Controls/control_event_timeline/graphs_eventsgenerator.py b/pyforms/gui/controls_/control_event_timeline/graphs_eventsgenerator.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/graphs_eventsgenerator.py rename to pyforms/gui/controls_/control_event_timeline/graphs_eventsgenerator.py diff --git a/pyforms/gui/Controls/control_event_timeline/graphs_graph2event.py b/pyforms/gui/controls_/control_event_timeline/graphs_graph2event.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/graphs_graph2event.py rename to pyforms/gui/controls_/control_event_timeline/graphs_graph2event.py diff --git a/pyforms/gui/Controls/control_event_timeline/graphs_properties.py b/pyforms/gui/controls_/control_event_timeline/graphs_properties.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/graphs_properties.py rename to pyforms/gui/controls_/control_event_timeline/graphs_properties.py diff --git a/pyforms/gui/Controls/control_event_timeline/import_window.py b/pyforms/gui/controls_/control_event_timeline/import_window.py similarity index 100% rename from pyforms/gui/Controls/control_event_timeline/import_window.py rename to pyforms/gui/controls_/control_event_timeline/import_window.py diff --git a/pyforms/gui/Controls/control_events_graph/ControlEventsGraph.py b/pyforms/gui/controls_/control_events_graph/ControlEventsGraph.py similarity index 100% rename from pyforms/gui/Controls/control_events_graph/ControlEventsGraph.py rename to pyforms/gui/controls_/control_events_graph/ControlEventsGraph.py diff --git a/pyforms/gui/Controls/control_events_graph/Event.py b/pyforms/gui/controls_/control_events_graph/Event.py similarity index 100% rename from pyforms/gui/Controls/control_events_graph/Event.py rename to pyforms/gui/controls_/control_events_graph/Event.py diff --git a/pyforms/gui/Controls/control_events_graph/EventsWidget.py b/pyforms/gui/controls_/control_events_graph/EventsWidget.py similarity index 100% rename from pyforms/gui/Controls/control_events_graph/EventsWidget.py rename to pyforms/gui/controls_/control_events_graph/EventsWidget.py diff --git a/pyforms/gui/Controls/control_events_graph/Pointer.py b/pyforms/gui/controls_/control_events_graph/Pointer.py similarity index 100% rename from pyforms/gui/Controls/control_events_graph/Pointer.py rename to pyforms/gui/controls_/control_events_graph/Pointer.py diff --git a/pyforms/gui/Controls/control_events_graph/Track.py b/pyforms/gui/controls_/control_events_graph/Track.py similarity index 100% rename from pyforms/gui/Controls/control_events_graph/Track.py rename to pyforms/gui/controls_/control_events_graph/Track.py diff --git a/pyforms/gui/Controls/control_events_graph/__init__.py b/pyforms/gui/controls_/control_events_graph/__init__.py similarity index 100% rename from pyforms/gui/Controls/control_events_graph/__init__.py rename to pyforms/gui/controls_/control_events_graph/__init__.py diff --git a/pyforms/gui/Controls/control_player/AbstractGLWidget.py b/pyforms/gui/controls_/control_player/AbstractGLWidget.py similarity index 100% rename from pyforms/gui/Controls/control_player/AbstractGLWidget.py rename to pyforms/gui/controls_/control_player/AbstractGLWidget.py diff --git a/pyforms/gui/Controls/control_player/ControlPlayer.py b/pyforms/gui/controls_/control_player/ControlPlayer.py similarity index 100% rename from pyforms/gui/Controls/control_player/ControlPlayer.py rename to pyforms/gui/controls_/control_player/ControlPlayer.py diff --git a/pyforms/gui/Controls/control_player/VideoGLWidget.py b/pyforms/gui/controls_/control_player/VideoGLWidget.py similarity index 100% rename from pyforms/gui/Controls/control_player/VideoGLWidget.py rename to pyforms/gui/controls_/control_player/VideoGLWidget.py diff --git a/pyforms/gui/Controls/control_player/VideoQt5GLWidget.py b/pyforms/gui/controls_/control_player/VideoQt5GLWidget.py similarity index 100% rename from pyforms/gui/Controls/control_player/VideoQt5GLWidget.py rename to pyforms/gui/controls_/control_player/VideoQt5GLWidget.py diff --git a/pyforms/gui/Controls/control_player/__init__.py b/pyforms/gui/controls_/control_player/__init__.py similarity index 100% rename from pyforms/gui/Controls/control_player/__init__.py rename to pyforms/gui/controls_/control_player/__init__.py diff --git a/pyforms/gui/Controls/control_player/video.ui b/pyforms/gui/controls_/control_player/video.ui similarity index 100% rename from pyforms/gui/Controls/control_player/video.ui rename to pyforms/gui/controls_/control_player/video.ui diff --git a/pyforms/gui/Controls/fileInput.ui b/pyforms/gui/controls_/fileInput.ui similarity index 100% rename from pyforms/gui/Controls/fileInput.ui rename to pyforms/gui/controls_/fileInput.ui diff --git a/pyforms/gui/Controls/image.ui b/pyforms/gui/controls_/image.ui similarity index 100% rename from pyforms/gui/Controls/image.ui rename to pyforms/gui/controls_/image.ui diff --git a/pyforms/gui/Controls/label.ui b/pyforms/gui/controls_/label.ui similarity index 100% rename from pyforms/gui/Controls/label.ui rename to pyforms/gui/controls_/label.ui diff --git a/pyforms/gui/Controls/list.ui b/pyforms/gui/controls_/list.ui similarity index 100% rename from pyforms/gui/Controls/list.ui rename to pyforms/gui/controls_/list.ui diff --git a/pyforms/gui/Controls/number.ui b/pyforms/gui/controls_/number.ui similarity index 100% rename from pyforms/gui/Controls/number.ui rename to pyforms/gui/controls_/number.ui diff --git a/pyforms/gui/Controls/progressInput.ui b/pyforms/gui/controls_/progressInput.ui similarity index 100% rename from pyforms/gui/Controls/progressInput.ui rename to pyforms/gui/controls_/progressInput.ui diff --git a/pyforms/gui/Controls/sliderInput.ui b/pyforms/gui/controls_/sliderInput.ui similarity index 100% rename from pyforms/gui/Controls/sliderInput.ui rename to pyforms/gui/controls_/sliderInput.ui diff --git a/pyforms/gui/Controls/textArea.ui b/pyforms/gui/controls_/textArea.ui similarity index 100% rename from pyforms/gui/Controls/textArea.ui rename to pyforms/gui/controls_/textArea.ui diff --git a/pyforms/gui/Controls/textInput.ui b/pyforms/gui/controls_/textInput.ui similarity index 100% rename from pyforms/gui/Controls/textInput.ui rename to pyforms/gui/controls_/textInput.ui diff --git a/pyforms/gui/Controls/tree.ui b/pyforms/gui/controls_/tree.ui similarity index 100% rename from pyforms/gui/Controls/tree.ui rename to pyforms/gui/controls_/tree.ui diff --git a/pyforms/gui/Controls/uipics/add.png b/pyforms/gui/controls_/uipics/add.png similarity index 100% rename from pyforms/gui/Controls/uipics/add.png rename to pyforms/gui/controls_/uipics/add.png diff --git a/pyforms/gui/Controls/uipics/film.png b/pyforms/gui/controls_/uipics/film.png similarity index 100% rename from pyforms/gui/Controls/uipics/film.png rename to pyforms/gui/controls_/uipics/film.png diff --git a/pyforms/gui/Controls/uipics/film_edit.png b/pyforms/gui/controls_/uipics/film_edit.png similarity index 100% rename from pyforms/gui/Controls/uipics/film_edit.png rename to pyforms/gui/controls_/uipics/film_edit.png diff --git a/pyforms/gui/Controls/uipics/graph.png b/pyforms/gui/controls_/uipics/graph.png similarity index 100% rename from pyforms/gui/Controls/uipics/graph.png rename to pyforms/gui/controls_/uipics/graph.png diff --git a/pyforms/gui/Controls/uipics/page_white_get.png b/pyforms/gui/controls_/uipics/page_white_get.png similarity index 100% rename from pyforms/gui/Controls/uipics/page_white_get.png rename to pyforms/gui/controls_/uipics/page_white_get.png diff --git a/pyforms/gui/Controls/uipics/page_white_put.png b/pyforms/gui/controls_/uipics/page_white_put.png similarity index 100% rename from pyforms/gui/Controls/uipics/page_white_put.png rename to pyforms/gui/controls_/uipics/page_white_put.png diff --git a/pyforms/gui/Controls/uipics/refresh.png b/pyforms/gui/controls_/uipics/refresh.png similarity index 100% rename from pyforms/gui/Controls/uipics/refresh.png rename to pyforms/gui/controls_/uipics/refresh.png diff --git a/pyforms/gui/Controls/uipics/remove.png b/pyforms/gui/controls_/uipics/remove.png similarity index 100% rename from pyforms/gui/Controls/uipics/remove.png rename to pyforms/gui/controls_/uipics/remove.png diff --git a/pyforms/gui/Controls/uipics/timeline.png b/pyforms/gui/controls_/uipics/timeline.png similarity index 100% rename from pyforms/gui/Controls/uipics/timeline.png rename to pyforms/gui/controls_/uipics/timeline.png diff --git a/pyforms/gui/Controls/uipics/zoom_in.png b/pyforms/gui/controls_/uipics/zoom_in.png similarity index 100% rename from pyforms/gui/Controls/uipics/zoom_in.png rename to pyforms/gui/controls_/uipics/zoom_in.png diff --git a/pyforms/gui/Controls/uipics/zoom_out.png b/pyforms/gui/controls_/uipics/zoom_out.png similarity index 100% rename from pyforms/gui/Controls/uipics/zoom_out.png rename to pyforms/gui/controls_/uipics/zoom_out.png diff --git a/pyforms/terminal/BaseWidget.py b/pyforms/terminal/basewidget_.py similarity index 100% rename from pyforms/terminal/BaseWidget.py rename to pyforms/terminal/basewidget_.py diff --git a/pyforms/terminal/Controls/ControlBase.py b/pyforms/terminal/controls_/ControlBase.py similarity index 100% rename from pyforms/terminal/Controls/ControlBase.py rename to pyforms/terminal/controls_/ControlBase.py diff --git a/pyforms/terminal/Controls/ControlBoundingSlider.py b/pyforms/terminal/controls_/ControlBoundingSlider.py similarity index 100% rename from pyforms/terminal/Controls/ControlBoundingSlider.py rename to pyforms/terminal/controls_/ControlBoundingSlider.py diff --git a/pyforms/terminal/Controls/ControlButton.py b/pyforms/terminal/controls_/ControlButton.py similarity index 100% rename from pyforms/terminal/Controls/ControlButton.py rename to pyforms/terminal/controls_/ControlButton.py diff --git a/pyforms/terminal/Controls/ControlCheckBox.py b/pyforms/terminal/controls_/ControlCheckBox.py similarity index 100% rename from pyforms/terminal/Controls/ControlCheckBox.py rename to pyforms/terminal/controls_/ControlCheckBox.py diff --git a/pyforms/terminal/Controls/ControlCheckBoxList.py b/pyforms/terminal/controls_/ControlCheckBoxList.py similarity index 100% rename from pyforms/terminal/Controls/ControlCheckBoxList.py rename to pyforms/terminal/controls_/ControlCheckBoxList.py diff --git a/pyforms/terminal/Controls/ControlCombo.py b/pyforms/terminal/controls_/ControlCombo.py similarity index 100% rename from pyforms/terminal/Controls/ControlCombo.py rename to pyforms/terminal/controls_/ControlCombo.py diff --git a/pyforms/terminal/Controls/ControlDir.py b/pyforms/terminal/controls_/ControlDir.py similarity index 100% rename from pyforms/terminal/Controls/ControlDir.py rename to pyforms/terminal/controls_/ControlDir.py diff --git a/pyforms/terminal/Controls/ControlEmptyWidget.py b/pyforms/terminal/controls_/ControlEmptyWidget.py similarity index 100% rename from pyforms/terminal/Controls/ControlEmptyWidget.py rename to pyforms/terminal/controls_/ControlEmptyWidget.py diff --git a/pyforms/terminal/Controls/ControlFile.py b/pyforms/terminal/controls_/ControlFile.py similarity index 100% rename from pyforms/terminal/Controls/ControlFile.py rename to pyforms/terminal/controls_/ControlFile.py diff --git a/pyforms/terminal/Controls/ControlImage.py b/pyforms/terminal/controls_/ControlImage.py similarity index 100% rename from pyforms/terminal/Controls/ControlImage.py rename to pyforms/terminal/controls_/ControlImage.py diff --git a/pyforms/terminal/Controls/ControlLabel.py b/pyforms/terminal/controls_/ControlLabel.py similarity index 100% rename from pyforms/terminal/Controls/ControlLabel.py rename to pyforms/terminal/controls_/ControlLabel.py diff --git a/pyforms/terminal/Controls/ControlList.py b/pyforms/terminal/controls_/ControlList.py similarity index 100% rename from pyforms/terminal/Controls/ControlList.py rename to pyforms/terminal/controls_/ControlList.py diff --git a/pyforms/terminal/Controls/ControlNumber.py b/pyforms/terminal/controls_/ControlNumber.py similarity index 100% rename from pyforms/terminal/Controls/ControlNumber.py rename to pyforms/terminal/controls_/ControlNumber.py diff --git a/pyforms/terminal/Controls/ControlPlayer.py b/pyforms/terminal/controls_/ControlPlayer.py similarity index 100% rename from pyforms/terminal/Controls/ControlPlayer.py rename to pyforms/terminal/controls_/ControlPlayer.py diff --git a/pyforms/terminal/Controls/ControlProgress.py b/pyforms/terminal/controls_/ControlProgress.py similarity index 100% rename from pyforms/terminal/Controls/ControlProgress.py rename to pyforms/terminal/controls_/ControlProgress.py diff --git a/pyforms/terminal/Controls/ControlSlider.py b/pyforms/terminal/controls_/ControlSlider.py similarity index 100% rename from pyforms/terminal/Controls/ControlSlider.py rename to pyforms/terminal/controls_/ControlSlider.py diff --git a/pyforms/terminal/Controls/ControlText.py b/pyforms/terminal/controls_/ControlText.py similarity index 100% rename from pyforms/terminal/Controls/ControlText.py rename to pyforms/terminal/controls_/ControlText.py diff --git a/pyforms/terminal/Controls/ControlTextArea.py b/pyforms/terminal/controls_/ControlTextArea.py similarity index 100% rename from pyforms/terminal/Controls/ControlTextArea.py rename to pyforms/terminal/controls_/ControlTextArea.py diff --git a/pyforms/terminal/Controls/ControlToolBox.py b/pyforms/terminal/controls_/ControlToolBox.py similarity index 100% rename from pyforms/terminal/Controls/ControlToolBox.py rename to pyforms/terminal/controls_/ControlToolBox.py diff --git a/pyforms/terminal/Controls/ControlTree.py b/pyforms/terminal/controls_/ControlTree.py similarity index 100% rename from pyforms/terminal/Controls/ControlTree.py rename to pyforms/terminal/controls_/ControlTree.py diff --git a/pyforms/terminal/Controls/__init__.py b/pyforms/terminal/controls_/__init__.py similarity index 100% rename from pyforms/terminal/Controls/__init__.py rename to pyforms/terminal/controls_/__init__.py From 96594a930f93b597b1e5ad911484fe9a531e11b1 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 30 Jan 2018 18:34:37 +0000 Subject: [PATCH 30/66] rename to lowercase --- pyforms/{controls_.py => controls.py} | 0 pyforms/gui/{basewidget_.py => basewidget.py} | 0 pyforms/gui/{controls_ => controls}/ControlBase.py | 0 .../ControlBoundingSlider.py | 0 .../gui/{controls_ => controls}/ControlButton.py | 0 .../gui/{controls_ => controls}/ControlCheckBox.py | 0 .../{controls_ => controls}/ControlCheckBoxList.py | 0 .../{controls_ => controls}/ControlCodeEditor.py | 0 pyforms/gui/{controls_ => controls}/ControlCombo.py | 0 pyforms/gui/{controls_ => controls}/ControlDir.py | 0 .../{controls_ => controls}/ControlDockWidget.py | 0 .../{controls_ => controls}/ControlEmptyWidget.py | 0 pyforms/gui/{controls_ => controls}/ControlFile.py | 0 .../gui/{controls_ => controls}/ControlFilesTree.py | 0 pyforms/gui/{controls_ => controls}/ControlImage.py | 0 pyforms/gui/{controls_ => controls}/ControlLabel.py | 0 pyforms/gui/{controls_ => controls}/ControlList.py | 0 .../{controls_ => controls}/ControlMatplotlib.py | 0 .../gui/{controls_ => controls}/ControlMdiArea.py | 0 .../gui/{controls_ => controls}/ControlNumber.py | 0 .../gui/{controls_ => controls}/ControlOpenGL.py | 0 .../gui/{controls_ => controls}/ControlProgress.py | 0 .../gui/{controls_ => controls}/ControlSlider.py | 0 pyforms/gui/{controls_ => controls}/ControlText.py | 0 .../gui/{controls_ => controls}/ControlTextArea.py | 0 .../gui/{controls_ => controls}/ControlToolBox.py | 0 pyforms/gui/{controls_ => controls}/ControlTree.py | 0 .../gui/{controls_ => controls}/ControlTreeView.py | 0 .../gui/{controls_ => controls}/ControlVisVis.py | 0 .../{controls_ => controls}/ControlVisVisVolume.py | 0 pyforms/gui/{controls_ => controls}/ControlWeb.py | 0 pyforms/gui/{controls_ => controls}/__init__.py | 0 pyforms/gui/{controls_ => controls}/button.ui | 0 pyforms/gui/{controls_ => controls}/checkbox.ui | 0 pyforms/gui/{controls_ => controls}/code_editor.ui | 0 .../control_event_timeline/ControlEventTimeline.py | 0 .../control_event_timeline/TimelineChart.py | 0 .../control_event_timeline/TimelineDelta.py | 0 .../control_event_timeline/TimelinePointer.py | 0 .../control_event_timeline/TimelinePopupWindow.py | 0 .../control_event_timeline/TimelinePopupWindow.ui | 0 .../control_event_timeline/TimelineWidget.py | 0 .../control_event_timeline/Track.py | 0 .../control_event_timeline/__init__.py | 0 .../graphs_eventsgenerator.py | 0 .../control_event_timeline/graphs_graph2event.py | 0 .../control_event_timeline/graphs_properties.py | 0 .../control_event_timeline/import_window.py | 0 .../control_events_graph/ControlEventsGraph.py | 0 .../control_events_graph/Event.py | 0 .../control_events_graph/EventsWidget.py | 0 .../control_events_graph/Pointer.py | 0 .../control_events_graph/Track.py | 0 .../control_events_graph/__init__.py | 0 .../control_player/AbstractGLWidget.py | 0 .../control_player/ControlPlayer.py | 0 .../control_player/VideoGLWidget.py | 0 .../control_player/VideoQt5GLWidget.py | 0 .../control_player/__init__.py | 0 .../{controls_ => controls}/control_player/video.ui | 0 pyforms/gui/{controls_ => controls}/fileInput.ui | 0 pyforms/gui/{controls_ => controls}/image.ui | 0 pyforms/gui/{controls_ => controls}/label.ui | 0 pyforms/gui/{controls_ => controls}/list.ui | 0 pyforms/gui/{controls_ => controls}/number.ui | 0 .../gui/{controls_ => controls}/progressInput.ui | 0 pyforms/gui/{controls_ => controls}/sliderInput.ui | 0 pyforms/gui/{controls_ => controls}/textArea.ui | 0 pyforms/gui/{controls_ => controls}/textInput.ui | 0 pyforms/gui/{controls_ => controls}/tree.ui | 0 pyforms/gui/{controls_ => controls}/uipics/add.png | Bin pyforms/gui/{controls_ => controls}/uipics/film.png | Bin .../{controls_ => controls}/uipics/film_edit.png | Bin .../gui/{controls_ => controls}/uipics/graph.png | Bin .../uipics/page_white_get.png | Bin .../uipics/page_white_put.png | Bin .../gui/{controls_ => controls}/uipics/refresh.png | Bin .../gui/{controls_ => controls}/uipics/remove.png | Bin .../gui/{controls_ => controls}/uipics/timeline.png | Bin .../gui/{controls_ => controls}/uipics/zoom_in.png | Bin .../gui/{controls_ => controls}/uipics/zoom_out.png | Bin pyforms/terminal/{basewidget_.py => basewidget.py} | 0 .../terminal/{controls_ => controls}/ControlBase.py | 0 .../ControlBoundingSlider.py | 0 .../{controls_ => controls}/ControlButton.py | 0 .../{controls_ => controls}/ControlCheckBox.py | 0 .../{controls_ => controls}/ControlCheckBoxList.py | 0 .../{controls_ => controls}/ControlCombo.py | 0 .../terminal/{controls_ => controls}/ControlDir.py | 0 .../{controls_ => controls}/ControlEmptyWidget.py | 0 .../terminal/{controls_ => controls}/ControlFile.py | 0 .../{controls_ => controls}/ControlImage.py | 0 .../{controls_ => controls}/ControlLabel.py | 0 .../terminal/{controls_ => controls}/ControlList.py | 0 .../{controls_ => controls}/ControlNumber.py | 0 .../{controls_ => controls}/ControlPlayer.py | 0 .../{controls_ => controls}/ControlProgress.py | 0 .../{controls_ => controls}/ControlSlider.py | 0 .../terminal/{controls_ => controls}/ControlText.py | 0 .../{controls_ => controls}/ControlTextArea.py | 0 .../{controls_ => controls}/ControlToolBox.py | 0 .../terminal/{controls_ => controls}/ControlTree.py | 0 .../terminal/{controls_ => controls}/__init__.py | 0 103 files changed, 0 insertions(+), 0 deletions(-) rename pyforms/{controls_.py => controls.py} (100%) rename pyforms/gui/{basewidget_.py => basewidget.py} (100%) rename pyforms/gui/{controls_ => controls}/ControlBase.py (100%) rename pyforms/gui/{controls_ => controls}/ControlBoundingSlider.py (100%) rename pyforms/gui/{controls_ => controls}/ControlButton.py (100%) rename pyforms/gui/{controls_ => controls}/ControlCheckBox.py (100%) rename pyforms/gui/{controls_ => controls}/ControlCheckBoxList.py (100%) rename pyforms/gui/{controls_ => controls}/ControlCodeEditor.py (100%) rename pyforms/gui/{controls_ => controls}/ControlCombo.py (100%) rename pyforms/gui/{controls_ => controls}/ControlDir.py (100%) rename pyforms/gui/{controls_ => controls}/ControlDockWidget.py (100%) rename pyforms/gui/{controls_ => controls}/ControlEmptyWidget.py (100%) rename pyforms/gui/{controls_ => controls}/ControlFile.py (100%) rename pyforms/gui/{controls_ => controls}/ControlFilesTree.py (100%) rename pyforms/gui/{controls_ => controls}/ControlImage.py (100%) rename pyforms/gui/{controls_ => controls}/ControlLabel.py (100%) rename pyforms/gui/{controls_ => controls}/ControlList.py (100%) rename pyforms/gui/{controls_ => controls}/ControlMatplotlib.py (100%) rename pyforms/gui/{controls_ => controls}/ControlMdiArea.py (100%) rename pyforms/gui/{controls_ => controls}/ControlNumber.py (100%) rename pyforms/gui/{controls_ => controls}/ControlOpenGL.py (100%) rename pyforms/gui/{controls_ => controls}/ControlProgress.py (100%) rename pyforms/gui/{controls_ => controls}/ControlSlider.py (100%) rename pyforms/gui/{controls_ => controls}/ControlText.py (100%) rename pyforms/gui/{controls_ => controls}/ControlTextArea.py (100%) rename pyforms/gui/{controls_ => controls}/ControlToolBox.py (100%) rename pyforms/gui/{controls_ => controls}/ControlTree.py (100%) rename pyforms/gui/{controls_ => controls}/ControlTreeView.py (100%) rename pyforms/gui/{controls_ => controls}/ControlVisVis.py (100%) rename pyforms/gui/{controls_ => controls}/ControlVisVisVolume.py (100%) rename pyforms/gui/{controls_ => controls}/ControlWeb.py (100%) rename pyforms/gui/{controls_ => controls}/__init__.py (100%) rename pyforms/gui/{controls_ => controls}/button.ui (100%) rename pyforms/gui/{controls_ => controls}/checkbox.ui (100%) rename pyforms/gui/{controls_ => controls}/code_editor.ui (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/ControlEventTimeline.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/TimelineChart.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/TimelineDelta.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/TimelinePointer.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/TimelinePopupWindow.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/TimelinePopupWindow.ui (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/TimelineWidget.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/Track.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/__init__.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/graphs_eventsgenerator.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/graphs_graph2event.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/graphs_properties.py (100%) rename pyforms/gui/{controls_ => controls}/control_event_timeline/import_window.py (100%) rename pyforms/gui/{controls_ => controls}/control_events_graph/ControlEventsGraph.py (100%) rename pyforms/gui/{controls_ => controls}/control_events_graph/Event.py (100%) rename pyforms/gui/{controls_ => controls}/control_events_graph/EventsWidget.py (100%) rename pyforms/gui/{controls_ => controls}/control_events_graph/Pointer.py (100%) rename pyforms/gui/{controls_ => controls}/control_events_graph/Track.py (100%) rename pyforms/gui/{controls_ => controls}/control_events_graph/__init__.py (100%) rename pyforms/gui/{controls_ => controls}/control_player/AbstractGLWidget.py (100%) rename pyforms/gui/{controls_ => controls}/control_player/ControlPlayer.py (100%) rename pyforms/gui/{controls_ => controls}/control_player/VideoGLWidget.py (100%) rename pyforms/gui/{controls_ => controls}/control_player/VideoQt5GLWidget.py (100%) rename pyforms/gui/{controls_ => controls}/control_player/__init__.py (100%) rename pyforms/gui/{controls_ => controls}/control_player/video.ui (100%) rename pyforms/gui/{controls_ => controls}/fileInput.ui (100%) rename pyforms/gui/{controls_ => controls}/image.ui (100%) rename pyforms/gui/{controls_ => controls}/label.ui (100%) rename pyforms/gui/{controls_ => controls}/list.ui (100%) rename pyforms/gui/{controls_ => controls}/number.ui (100%) rename pyforms/gui/{controls_ => controls}/progressInput.ui (100%) rename pyforms/gui/{controls_ => controls}/sliderInput.ui (100%) rename pyforms/gui/{controls_ => controls}/textArea.ui (100%) rename pyforms/gui/{controls_ => controls}/textInput.ui (100%) rename pyforms/gui/{controls_ => controls}/tree.ui (100%) rename pyforms/gui/{controls_ => controls}/uipics/add.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/film.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/film_edit.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/graph.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/page_white_get.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/page_white_put.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/refresh.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/remove.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/timeline.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/zoom_in.png (100%) rename pyforms/gui/{controls_ => controls}/uipics/zoom_out.png (100%) rename pyforms/terminal/{basewidget_.py => basewidget.py} (100%) rename pyforms/terminal/{controls_ => controls}/ControlBase.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlBoundingSlider.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlButton.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlCheckBox.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlCheckBoxList.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlCombo.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlDir.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlEmptyWidget.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlFile.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlImage.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlLabel.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlList.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlNumber.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlPlayer.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlProgress.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlSlider.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlText.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlTextArea.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlToolBox.py (100%) rename pyforms/terminal/{controls_ => controls}/ControlTree.py (100%) rename pyforms/terminal/{controls_ => controls}/__init__.py (100%) diff --git a/pyforms/controls_.py b/pyforms/controls.py similarity index 100% rename from pyforms/controls_.py rename to pyforms/controls.py diff --git a/pyforms/gui/basewidget_.py b/pyforms/gui/basewidget.py similarity index 100% rename from pyforms/gui/basewidget_.py rename to pyforms/gui/basewidget.py diff --git a/pyforms/gui/controls_/ControlBase.py b/pyforms/gui/controls/ControlBase.py similarity index 100% rename from pyforms/gui/controls_/ControlBase.py rename to pyforms/gui/controls/ControlBase.py diff --git a/pyforms/gui/controls_/ControlBoundingSlider.py b/pyforms/gui/controls/ControlBoundingSlider.py similarity index 100% rename from pyforms/gui/controls_/ControlBoundingSlider.py rename to pyforms/gui/controls/ControlBoundingSlider.py diff --git a/pyforms/gui/controls_/ControlButton.py b/pyforms/gui/controls/ControlButton.py similarity index 100% rename from pyforms/gui/controls_/ControlButton.py rename to pyforms/gui/controls/ControlButton.py diff --git a/pyforms/gui/controls_/ControlCheckBox.py b/pyforms/gui/controls/ControlCheckBox.py similarity index 100% rename from pyforms/gui/controls_/ControlCheckBox.py rename to pyforms/gui/controls/ControlCheckBox.py diff --git a/pyforms/gui/controls_/ControlCheckBoxList.py b/pyforms/gui/controls/ControlCheckBoxList.py similarity index 100% rename from pyforms/gui/controls_/ControlCheckBoxList.py rename to pyforms/gui/controls/ControlCheckBoxList.py diff --git a/pyforms/gui/controls_/ControlCodeEditor.py b/pyforms/gui/controls/ControlCodeEditor.py similarity index 100% rename from pyforms/gui/controls_/ControlCodeEditor.py rename to pyforms/gui/controls/ControlCodeEditor.py diff --git a/pyforms/gui/controls_/ControlCombo.py b/pyforms/gui/controls/ControlCombo.py similarity index 100% rename from pyforms/gui/controls_/ControlCombo.py rename to pyforms/gui/controls/ControlCombo.py diff --git a/pyforms/gui/controls_/ControlDir.py b/pyforms/gui/controls/ControlDir.py similarity index 100% rename from pyforms/gui/controls_/ControlDir.py rename to pyforms/gui/controls/ControlDir.py diff --git a/pyforms/gui/controls_/ControlDockWidget.py b/pyforms/gui/controls/ControlDockWidget.py similarity index 100% rename from pyforms/gui/controls_/ControlDockWidget.py rename to pyforms/gui/controls/ControlDockWidget.py diff --git a/pyforms/gui/controls_/ControlEmptyWidget.py b/pyforms/gui/controls/ControlEmptyWidget.py similarity index 100% rename from pyforms/gui/controls_/ControlEmptyWidget.py rename to pyforms/gui/controls/ControlEmptyWidget.py diff --git a/pyforms/gui/controls_/ControlFile.py b/pyforms/gui/controls/ControlFile.py similarity index 100% rename from pyforms/gui/controls_/ControlFile.py rename to pyforms/gui/controls/ControlFile.py diff --git a/pyforms/gui/controls_/ControlFilesTree.py b/pyforms/gui/controls/ControlFilesTree.py similarity index 100% rename from pyforms/gui/controls_/ControlFilesTree.py rename to pyforms/gui/controls/ControlFilesTree.py diff --git a/pyforms/gui/controls_/ControlImage.py b/pyforms/gui/controls/ControlImage.py similarity index 100% rename from pyforms/gui/controls_/ControlImage.py rename to pyforms/gui/controls/ControlImage.py diff --git a/pyforms/gui/controls_/ControlLabel.py b/pyforms/gui/controls/ControlLabel.py similarity index 100% rename from pyforms/gui/controls_/ControlLabel.py rename to pyforms/gui/controls/ControlLabel.py diff --git a/pyforms/gui/controls_/ControlList.py b/pyforms/gui/controls/ControlList.py similarity index 100% rename from pyforms/gui/controls_/ControlList.py rename to pyforms/gui/controls/ControlList.py diff --git a/pyforms/gui/controls_/ControlMatplotlib.py b/pyforms/gui/controls/ControlMatplotlib.py similarity index 100% rename from pyforms/gui/controls_/ControlMatplotlib.py rename to pyforms/gui/controls/ControlMatplotlib.py diff --git a/pyforms/gui/controls_/ControlMdiArea.py b/pyforms/gui/controls/ControlMdiArea.py similarity index 100% rename from pyforms/gui/controls_/ControlMdiArea.py rename to pyforms/gui/controls/ControlMdiArea.py diff --git a/pyforms/gui/controls_/ControlNumber.py b/pyforms/gui/controls/ControlNumber.py similarity index 100% rename from pyforms/gui/controls_/ControlNumber.py rename to pyforms/gui/controls/ControlNumber.py diff --git a/pyforms/gui/controls_/ControlOpenGL.py b/pyforms/gui/controls/ControlOpenGL.py similarity index 100% rename from pyforms/gui/controls_/ControlOpenGL.py rename to pyforms/gui/controls/ControlOpenGL.py diff --git a/pyforms/gui/controls_/ControlProgress.py b/pyforms/gui/controls/ControlProgress.py similarity index 100% rename from pyforms/gui/controls_/ControlProgress.py rename to pyforms/gui/controls/ControlProgress.py diff --git a/pyforms/gui/controls_/ControlSlider.py b/pyforms/gui/controls/ControlSlider.py similarity index 100% rename from pyforms/gui/controls_/ControlSlider.py rename to pyforms/gui/controls/ControlSlider.py diff --git a/pyforms/gui/controls_/ControlText.py b/pyforms/gui/controls/ControlText.py similarity index 100% rename from pyforms/gui/controls_/ControlText.py rename to pyforms/gui/controls/ControlText.py diff --git a/pyforms/gui/controls_/ControlTextArea.py b/pyforms/gui/controls/ControlTextArea.py similarity index 100% rename from pyforms/gui/controls_/ControlTextArea.py rename to pyforms/gui/controls/ControlTextArea.py diff --git a/pyforms/gui/controls_/ControlToolBox.py b/pyforms/gui/controls/ControlToolBox.py similarity index 100% rename from pyforms/gui/controls_/ControlToolBox.py rename to pyforms/gui/controls/ControlToolBox.py diff --git a/pyforms/gui/controls_/ControlTree.py b/pyforms/gui/controls/ControlTree.py similarity index 100% rename from pyforms/gui/controls_/ControlTree.py rename to pyforms/gui/controls/ControlTree.py diff --git a/pyforms/gui/controls_/ControlTreeView.py b/pyforms/gui/controls/ControlTreeView.py similarity index 100% rename from pyforms/gui/controls_/ControlTreeView.py rename to pyforms/gui/controls/ControlTreeView.py diff --git a/pyforms/gui/controls_/ControlVisVis.py b/pyforms/gui/controls/ControlVisVis.py similarity index 100% rename from pyforms/gui/controls_/ControlVisVis.py rename to pyforms/gui/controls/ControlVisVis.py diff --git a/pyforms/gui/controls_/ControlVisVisVolume.py b/pyforms/gui/controls/ControlVisVisVolume.py similarity index 100% rename from pyforms/gui/controls_/ControlVisVisVolume.py rename to pyforms/gui/controls/ControlVisVisVolume.py diff --git a/pyforms/gui/controls_/ControlWeb.py b/pyforms/gui/controls/ControlWeb.py similarity index 100% rename from pyforms/gui/controls_/ControlWeb.py rename to pyforms/gui/controls/ControlWeb.py diff --git a/pyforms/gui/controls_/__init__.py b/pyforms/gui/controls/__init__.py similarity index 100% rename from pyforms/gui/controls_/__init__.py rename to pyforms/gui/controls/__init__.py diff --git a/pyforms/gui/controls_/button.ui b/pyforms/gui/controls/button.ui similarity index 100% rename from pyforms/gui/controls_/button.ui rename to pyforms/gui/controls/button.ui diff --git a/pyforms/gui/controls_/checkbox.ui b/pyforms/gui/controls/checkbox.ui similarity index 100% rename from pyforms/gui/controls_/checkbox.ui rename to pyforms/gui/controls/checkbox.ui diff --git a/pyforms/gui/controls_/code_editor.ui b/pyforms/gui/controls/code_editor.ui similarity index 100% rename from pyforms/gui/controls_/code_editor.ui rename to pyforms/gui/controls/code_editor.ui diff --git a/pyforms/gui/controls_/control_event_timeline/ControlEventTimeline.py b/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/ControlEventTimeline.py rename to pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py diff --git a/pyforms/gui/controls_/control_event_timeline/TimelineChart.py b/pyforms/gui/controls/control_event_timeline/TimelineChart.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/TimelineChart.py rename to pyforms/gui/controls/control_event_timeline/TimelineChart.py diff --git a/pyforms/gui/controls_/control_event_timeline/TimelineDelta.py b/pyforms/gui/controls/control_event_timeline/TimelineDelta.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/TimelineDelta.py rename to pyforms/gui/controls/control_event_timeline/TimelineDelta.py diff --git a/pyforms/gui/controls_/control_event_timeline/TimelinePointer.py b/pyforms/gui/controls/control_event_timeline/TimelinePointer.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/TimelinePointer.py rename to pyforms/gui/controls/control_event_timeline/TimelinePointer.py diff --git a/pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.py b/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.py rename to pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py diff --git a/pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.ui b/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.ui similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/TimelinePopupWindow.ui rename to pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.ui diff --git a/pyforms/gui/controls_/control_event_timeline/TimelineWidget.py b/pyforms/gui/controls/control_event_timeline/TimelineWidget.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/TimelineWidget.py rename to pyforms/gui/controls/control_event_timeline/TimelineWidget.py diff --git a/pyforms/gui/controls_/control_event_timeline/Track.py b/pyforms/gui/controls/control_event_timeline/Track.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/Track.py rename to pyforms/gui/controls/control_event_timeline/Track.py diff --git a/pyforms/gui/controls_/control_event_timeline/__init__.py b/pyforms/gui/controls/control_event_timeline/__init__.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/__init__.py rename to pyforms/gui/controls/control_event_timeline/__init__.py diff --git a/pyforms/gui/controls_/control_event_timeline/graphs_eventsgenerator.py b/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/graphs_eventsgenerator.py rename to pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py diff --git a/pyforms/gui/controls_/control_event_timeline/graphs_graph2event.py b/pyforms/gui/controls/control_event_timeline/graphs_graph2event.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/graphs_graph2event.py rename to pyforms/gui/controls/control_event_timeline/graphs_graph2event.py diff --git a/pyforms/gui/controls_/control_event_timeline/graphs_properties.py b/pyforms/gui/controls/control_event_timeline/graphs_properties.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/graphs_properties.py rename to pyforms/gui/controls/control_event_timeline/graphs_properties.py diff --git a/pyforms/gui/controls_/control_event_timeline/import_window.py b/pyforms/gui/controls/control_event_timeline/import_window.py similarity index 100% rename from pyforms/gui/controls_/control_event_timeline/import_window.py rename to pyforms/gui/controls/control_event_timeline/import_window.py diff --git a/pyforms/gui/controls_/control_events_graph/ControlEventsGraph.py b/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py similarity index 100% rename from pyforms/gui/controls_/control_events_graph/ControlEventsGraph.py rename to pyforms/gui/controls/control_events_graph/ControlEventsGraph.py diff --git a/pyforms/gui/controls_/control_events_graph/Event.py b/pyforms/gui/controls/control_events_graph/Event.py similarity index 100% rename from pyforms/gui/controls_/control_events_graph/Event.py rename to pyforms/gui/controls/control_events_graph/Event.py diff --git a/pyforms/gui/controls_/control_events_graph/EventsWidget.py b/pyforms/gui/controls/control_events_graph/EventsWidget.py similarity index 100% rename from pyforms/gui/controls_/control_events_graph/EventsWidget.py rename to pyforms/gui/controls/control_events_graph/EventsWidget.py diff --git a/pyforms/gui/controls_/control_events_graph/Pointer.py b/pyforms/gui/controls/control_events_graph/Pointer.py similarity index 100% rename from pyforms/gui/controls_/control_events_graph/Pointer.py rename to pyforms/gui/controls/control_events_graph/Pointer.py diff --git a/pyforms/gui/controls_/control_events_graph/Track.py b/pyforms/gui/controls/control_events_graph/Track.py similarity index 100% rename from pyforms/gui/controls_/control_events_graph/Track.py rename to pyforms/gui/controls/control_events_graph/Track.py diff --git a/pyforms/gui/controls_/control_events_graph/__init__.py b/pyforms/gui/controls/control_events_graph/__init__.py similarity index 100% rename from pyforms/gui/controls_/control_events_graph/__init__.py rename to pyforms/gui/controls/control_events_graph/__init__.py diff --git a/pyforms/gui/controls_/control_player/AbstractGLWidget.py b/pyforms/gui/controls/control_player/AbstractGLWidget.py similarity index 100% rename from pyforms/gui/controls_/control_player/AbstractGLWidget.py rename to pyforms/gui/controls/control_player/AbstractGLWidget.py diff --git a/pyforms/gui/controls_/control_player/ControlPlayer.py b/pyforms/gui/controls/control_player/ControlPlayer.py similarity index 100% rename from pyforms/gui/controls_/control_player/ControlPlayer.py rename to pyforms/gui/controls/control_player/ControlPlayer.py diff --git a/pyforms/gui/controls_/control_player/VideoGLWidget.py b/pyforms/gui/controls/control_player/VideoGLWidget.py similarity index 100% rename from pyforms/gui/controls_/control_player/VideoGLWidget.py rename to pyforms/gui/controls/control_player/VideoGLWidget.py diff --git a/pyforms/gui/controls_/control_player/VideoQt5GLWidget.py b/pyforms/gui/controls/control_player/VideoQt5GLWidget.py similarity index 100% rename from pyforms/gui/controls_/control_player/VideoQt5GLWidget.py rename to pyforms/gui/controls/control_player/VideoQt5GLWidget.py diff --git a/pyforms/gui/controls_/control_player/__init__.py b/pyforms/gui/controls/control_player/__init__.py similarity index 100% rename from pyforms/gui/controls_/control_player/__init__.py rename to pyforms/gui/controls/control_player/__init__.py diff --git a/pyforms/gui/controls_/control_player/video.ui b/pyforms/gui/controls/control_player/video.ui similarity index 100% rename from pyforms/gui/controls_/control_player/video.ui rename to pyforms/gui/controls/control_player/video.ui diff --git a/pyforms/gui/controls_/fileInput.ui b/pyforms/gui/controls/fileInput.ui similarity index 100% rename from pyforms/gui/controls_/fileInput.ui rename to pyforms/gui/controls/fileInput.ui diff --git a/pyforms/gui/controls_/image.ui b/pyforms/gui/controls/image.ui similarity index 100% rename from pyforms/gui/controls_/image.ui rename to pyforms/gui/controls/image.ui diff --git a/pyforms/gui/controls_/label.ui b/pyforms/gui/controls/label.ui similarity index 100% rename from pyforms/gui/controls_/label.ui rename to pyforms/gui/controls/label.ui diff --git a/pyforms/gui/controls_/list.ui b/pyforms/gui/controls/list.ui similarity index 100% rename from pyforms/gui/controls_/list.ui rename to pyforms/gui/controls/list.ui diff --git a/pyforms/gui/controls_/number.ui b/pyforms/gui/controls/number.ui similarity index 100% rename from pyforms/gui/controls_/number.ui rename to pyforms/gui/controls/number.ui diff --git a/pyforms/gui/controls_/progressInput.ui b/pyforms/gui/controls/progressInput.ui similarity index 100% rename from pyforms/gui/controls_/progressInput.ui rename to pyforms/gui/controls/progressInput.ui diff --git a/pyforms/gui/controls_/sliderInput.ui b/pyforms/gui/controls/sliderInput.ui similarity index 100% rename from pyforms/gui/controls_/sliderInput.ui rename to pyforms/gui/controls/sliderInput.ui diff --git a/pyforms/gui/controls_/textArea.ui b/pyforms/gui/controls/textArea.ui similarity index 100% rename from pyforms/gui/controls_/textArea.ui rename to pyforms/gui/controls/textArea.ui diff --git a/pyforms/gui/controls_/textInput.ui b/pyforms/gui/controls/textInput.ui similarity index 100% rename from pyforms/gui/controls_/textInput.ui rename to pyforms/gui/controls/textInput.ui diff --git a/pyforms/gui/controls_/tree.ui b/pyforms/gui/controls/tree.ui similarity index 100% rename from pyforms/gui/controls_/tree.ui rename to pyforms/gui/controls/tree.ui diff --git a/pyforms/gui/controls_/uipics/add.png b/pyforms/gui/controls/uipics/add.png similarity index 100% rename from pyforms/gui/controls_/uipics/add.png rename to pyforms/gui/controls/uipics/add.png diff --git a/pyforms/gui/controls_/uipics/film.png b/pyforms/gui/controls/uipics/film.png similarity index 100% rename from pyforms/gui/controls_/uipics/film.png rename to pyforms/gui/controls/uipics/film.png diff --git a/pyforms/gui/controls_/uipics/film_edit.png b/pyforms/gui/controls/uipics/film_edit.png similarity index 100% rename from pyforms/gui/controls_/uipics/film_edit.png rename to pyforms/gui/controls/uipics/film_edit.png diff --git a/pyforms/gui/controls_/uipics/graph.png b/pyforms/gui/controls/uipics/graph.png similarity index 100% rename from pyforms/gui/controls_/uipics/graph.png rename to pyforms/gui/controls/uipics/graph.png diff --git a/pyforms/gui/controls_/uipics/page_white_get.png b/pyforms/gui/controls/uipics/page_white_get.png similarity index 100% rename from pyforms/gui/controls_/uipics/page_white_get.png rename to pyforms/gui/controls/uipics/page_white_get.png diff --git a/pyforms/gui/controls_/uipics/page_white_put.png b/pyforms/gui/controls/uipics/page_white_put.png similarity index 100% rename from pyforms/gui/controls_/uipics/page_white_put.png rename to pyforms/gui/controls/uipics/page_white_put.png diff --git a/pyforms/gui/controls_/uipics/refresh.png b/pyforms/gui/controls/uipics/refresh.png similarity index 100% rename from pyforms/gui/controls_/uipics/refresh.png rename to pyforms/gui/controls/uipics/refresh.png diff --git a/pyforms/gui/controls_/uipics/remove.png b/pyforms/gui/controls/uipics/remove.png similarity index 100% rename from pyforms/gui/controls_/uipics/remove.png rename to pyforms/gui/controls/uipics/remove.png diff --git a/pyforms/gui/controls_/uipics/timeline.png b/pyforms/gui/controls/uipics/timeline.png similarity index 100% rename from pyforms/gui/controls_/uipics/timeline.png rename to pyforms/gui/controls/uipics/timeline.png diff --git a/pyforms/gui/controls_/uipics/zoom_in.png b/pyforms/gui/controls/uipics/zoom_in.png similarity index 100% rename from pyforms/gui/controls_/uipics/zoom_in.png rename to pyforms/gui/controls/uipics/zoom_in.png diff --git a/pyforms/gui/controls_/uipics/zoom_out.png b/pyforms/gui/controls/uipics/zoom_out.png similarity index 100% rename from pyforms/gui/controls_/uipics/zoom_out.png rename to pyforms/gui/controls/uipics/zoom_out.png diff --git a/pyforms/terminal/basewidget_.py b/pyforms/terminal/basewidget.py similarity index 100% rename from pyforms/terminal/basewidget_.py rename to pyforms/terminal/basewidget.py diff --git a/pyforms/terminal/controls_/ControlBase.py b/pyforms/terminal/controls/ControlBase.py similarity index 100% rename from pyforms/terminal/controls_/ControlBase.py rename to pyforms/terminal/controls/ControlBase.py diff --git a/pyforms/terminal/controls_/ControlBoundingSlider.py b/pyforms/terminal/controls/ControlBoundingSlider.py similarity index 100% rename from pyforms/terminal/controls_/ControlBoundingSlider.py rename to pyforms/terminal/controls/ControlBoundingSlider.py diff --git a/pyforms/terminal/controls_/ControlButton.py b/pyforms/terminal/controls/ControlButton.py similarity index 100% rename from pyforms/terminal/controls_/ControlButton.py rename to pyforms/terminal/controls/ControlButton.py diff --git a/pyforms/terminal/controls_/ControlCheckBox.py b/pyforms/terminal/controls/ControlCheckBox.py similarity index 100% rename from pyforms/terminal/controls_/ControlCheckBox.py rename to pyforms/terminal/controls/ControlCheckBox.py diff --git a/pyforms/terminal/controls_/ControlCheckBoxList.py b/pyforms/terminal/controls/ControlCheckBoxList.py similarity index 100% rename from pyforms/terminal/controls_/ControlCheckBoxList.py rename to pyforms/terminal/controls/ControlCheckBoxList.py diff --git a/pyforms/terminal/controls_/ControlCombo.py b/pyforms/terminal/controls/ControlCombo.py similarity index 100% rename from pyforms/terminal/controls_/ControlCombo.py rename to pyforms/terminal/controls/ControlCombo.py diff --git a/pyforms/terminal/controls_/ControlDir.py b/pyforms/terminal/controls/ControlDir.py similarity index 100% rename from pyforms/terminal/controls_/ControlDir.py rename to pyforms/terminal/controls/ControlDir.py diff --git a/pyforms/terminal/controls_/ControlEmptyWidget.py b/pyforms/terminal/controls/ControlEmptyWidget.py similarity index 100% rename from pyforms/terminal/controls_/ControlEmptyWidget.py rename to pyforms/terminal/controls/ControlEmptyWidget.py diff --git a/pyforms/terminal/controls_/ControlFile.py b/pyforms/terminal/controls/ControlFile.py similarity index 100% rename from pyforms/terminal/controls_/ControlFile.py rename to pyforms/terminal/controls/ControlFile.py diff --git a/pyforms/terminal/controls_/ControlImage.py b/pyforms/terminal/controls/ControlImage.py similarity index 100% rename from pyforms/terminal/controls_/ControlImage.py rename to pyforms/terminal/controls/ControlImage.py diff --git a/pyforms/terminal/controls_/ControlLabel.py b/pyforms/terminal/controls/ControlLabel.py similarity index 100% rename from pyforms/terminal/controls_/ControlLabel.py rename to pyforms/terminal/controls/ControlLabel.py diff --git a/pyforms/terminal/controls_/ControlList.py b/pyforms/terminal/controls/ControlList.py similarity index 100% rename from pyforms/terminal/controls_/ControlList.py rename to pyforms/terminal/controls/ControlList.py diff --git a/pyforms/terminal/controls_/ControlNumber.py b/pyforms/terminal/controls/ControlNumber.py similarity index 100% rename from pyforms/terminal/controls_/ControlNumber.py rename to pyforms/terminal/controls/ControlNumber.py diff --git a/pyforms/terminal/controls_/ControlPlayer.py b/pyforms/terminal/controls/ControlPlayer.py similarity index 100% rename from pyforms/terminal/controls_/ControlPlayer.py rename to pyforms/terminal/controls/ControlPlayer.py diff --git a/pyforms/terminal/controls_/ControlProgress.py b/pyforms/terminal/controls/ControlProgress.py similarity index 100% rename from pyforms/terminal/controls_/ControlProgress.py rename to pyforms/terminal/controls/ControlProgress.py diff --git a/pyforms/terminal/controls_/ControlSlider.py b/pyforms/terminal/controls/ControlSlider.py similarity index 100% rename from pyforms/terminal/controls_/ControlSlider.py rename to pyforms/terminal/controls/ControlSlider.py diff --git a/pyforms/terminal/controls_/ControlText.py b/pyforms/terminal/controls/ControlText.py similarity index 100% rename from pyforms/terminal/controls_/ControlText.py rename to pyforms/terminal/controls/ControlText.py diff --git a/pyforms/terminal/controls_/ControlTextArea.py b/pyforms/terminal/controls/ControlTextArea.py similarity index 100% rename from pyforms/terminal/controls_/ControlTextArea.py rename to pyforms/terminal/controls/ControlTextArea.py diff --git a/pyforms/terminal/controls_/ControlToolBox.py b/pyforms/terminal/controls/ControlToolBox.py similarity index 100% rename from pyforms/terminal/controls_/ControlToolBox.py rename to pyforms/terminal/controls/ControlToolBox.py diff --git a/pyforms/terminal/controls_/ControlTree.py b/pyforms/terminal/controls/ControlTree.py similarity index 100% rename from pyforms/terminal/controls_/ControlTree.py rename to pyforms/terminal/controls/ControlTree.py diff --git a/pyforms/terminal/controls_/__init__.py b/pyforms/terminal/controls/__init__.py similarity index 100% rename from pyforms/terminal/controls_/__init__.py rename to pyforms/terminal/controls/__init__.py From 6cf70c13a3e08df0fcd1acbc281dab27ff1fb1bf Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Wed, 31 Jan 2018 12:15:49 +0000 Subject: [PATCH 31/66] Fix bugs --- pyforms/controls.py | 20 +++---- pyforms/gui/basewidget.py | 65 ++++++++++++++++++++++- pyforms/gui/controls/ControlCodeEditor.py | 10 ++-- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/pyforms/controls.py b/pyforms/controls.py index 288c642..36c871a 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -31,40 +31,40 @@ if conf.PYFORMS_MATPLOTLIB_ENABLED: try: from pyforms.gui.controls.ControlMatplotlib import ControlMatplotlib - except: + except Exception as e: logger.warning("Matplot lib not installed or not working properly") - logger.debug(traceback.format_exc()) + logger.error(e) if conf.PYFORMS_WEB_ENABLED: try: from pyforms.gui.controls.ControlWeb import ControlWeb - except: + except Exception as e: logger.warning("QtWebKit lib not installed or not working properly") - logger.debug(traceback.format_exc()) + logger.error(e) if conf.PYFORMS_GL_ENABLED: try: from pyforms.gui.controls.ControlOpenGL import ControlOpenGL from pyforms.gui.controls.ControlImage import ControlImage from pyforms.gui.controls.control_player.ControlPlayer import ControlPlayer - except: + except Exception as e: logger.warning("GL widgets or Opencv not installed") - logger.debug(traceback.format_exc()) + logger.error(e) if conf.PYFORMS_VISVIS_ENABLED: try: from pyforms.gui.controls.ControlVisVis import ControlVisVis from pyforms.gui.controls.ControlVisVisVolume import ControlVisVisVolume - except: + except Exception as e: logger.warning("VisVis not installed") - logger.debug(traceback.format_exc()) + logger.error(e) if conf.PYFORMS_QSCINTILLA_ENABLED: try: from pyforms.gui.controls.ControlCodeEditor import ControlCodeEditor - except: + except Exception as e: logger.warning("QScintilla2 not installed") - logger.debug(traceback.format_exc()) + logger.error(e) elif conf.PYFORMS_MODE=='TERMINAL': diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index 357cee0..acd2b4e 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -1,9 +1,10 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import json +import json, AnyQt from pysettings import conf + from AnyQt.QtWidgets import QFrame from AnyQt.QtWidgets import QVBoxLayout from AnyQt.QtWidgets import QTabWidget @@ -437,6 +438,68 @@ def mainmenu(self): def mainmenu(self, value): self._mainmenu = value + + @property + def controls(self): + """ + Return all the form controls from the the module + """ + result = {} + for name, var in vars(self).items(): + try: + if isinstance(var, ControlBase): + result[name] = var + except: + pass + return result + + ############################################################################ + ############ GUI Properties ################################################ + ############################################################################ + + + @property + def form_has_loaded(self): + return self._formLoaded + + + + @property + def form(self): + return self + + @property + def title(self): + return self.windowTitle() + + @title.setter + def title(self, value): + self.setWindowTitle(value) + + + @property + def formset(self): + return self._formset + + @formset.setter + def formset(self, value): + self._formset = value + + @property + def uid(self): + return self._uid + + @uid.setter + def uid(self, value): + self._uid = value + + + @property + def visible(self): + return self.isVisible() + + + ########################################################################## ############ PRIVATE FUNCTIONS ########################################### ########################################################################## diff --git a/pyforms/gui/controls/ControlCodeEditor.py b/pyforms/gui/controls/ControlCodeEditor.py index 3cece18..c60cf55 100644 --- a/pyforms/gui/controls/ControlCodeEditor.py +++ b/pyforms/gui/controls/ControlCodeEditor.py @@ -14,7 +14,7 @@ from AnyQt.QtGui import QFontMetrics, QColor, QIcon, QFont if _api.USED_API == _api.QT_API_PYQT5: - from AnyQt.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs + from PyQt5.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs elif _api.USED_API == _api.QT_API_PYQT4: from PyQt4.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs @@ -36,11 +36,11 @@ def __init__(self, *args, **kwargs): :param default: :param helptext: """ - self._read_only = read_only - + self._read_only = kwargs.get('readonly', None) + self._changed_func = None super(ControlCodeEditor, self).__init__(*args, **kwargs) - self._changed_func = None + def init_form(self): """ @@ -235,7 +235,7 @@ def value(self): @value.setter def value(self, value): ControlBase.value.fset(self, value) - if len(value) > 0: + if value is not None and len(value) > 0: self._code_editor.setText(str(value)) self._code_editor.setModified(False) self._save_button.setEnabled(False) From ccfa390565b0fea21bf3ad27309086d0cd28e1f5 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Wed, 31 Jan 2018 13:37:28 +0000 Subject: [PATCH 32/66] Fix bug ControlCodeEditor --- pyforms/gui/controls/ControlCodeEditor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyforms/gui/controls/ControlCodeEditor.py b/pyforms/gui/controls/ControlCodeEditor.py index c60cf55..35033e4 100644 --- a/pyforms/gui/controls/ControlCodeEditor.py +++ b/pyforms/gui/controls/ControlCodeEditor.py @@ -36,7 +36,7 @@ def __init__(self, *args, **kwargs): :param default: :param helptext: """ - self._read_only = kwargs.get('readonly', None) + self._read_only = kwargs.get('readonly', False) self._changed_func = None super(ControlCodeEditor, self).__init__(*args, **kwargs) @@ -55,7 +55,7 @@ def init_form(self): self._save_button = self._form.save_button self._save_button.clicked[bool].connect(self.on_save_changes) - if not self._read_only: + if self._read_only: self._code_editor.setReadOnly(True) self._save_button.setVisible(False) From ecf4da455d23169af37a08e7895ebb27dd0dfca3 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 1 Feb 2018 10:37:19 +0000 Subject: [PATCH 33/66] Update ControlEventTimeline to import old format bonsai events files --- .../ControlEventTimeline.py | 4 +- .../ControlEventTimeline/TimelineDelta.py | 4 +- .../ControlEventTimeline/TimelineWidget.py | 14 +++--- .../graphs_graph2event.py | 4 +- .../ControlEventTimeline/import_window.py | 50 ++++++++++--------- 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py b/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py index 16174d4..c7d1a14 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py +++ b/pyforms/gui/Controls/ControlEventTimeline/ControlEventTimeline.py @@ -197,7 +197,7 @@ def add_period(self, value, row=0, color=None): :param color: :return: """ - self._time.addPeriod(value, track, color) + self._time.add_period(value, row, color) self._time.repaint() def add_graph(self, name, data): @@ -300,7 +300,7 @@ def __auto_adjust_tracks_evt(self): break def __add_track_2_bottom_evt(self): - self._time.addTrack() + self._time.add_track() def __remove_track_from_bottom_evt(self): if len(self._time.tracks) > 0: diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py b/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py index 2482d34..afb6ae5 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py +++ b/pyforms/gui/Controls/ControlEventTimeline/TimelineDelta.py @@ -113,7 +113,7 @@ def checkNumberOfTracks(self): """ if self.track >= (self._parent.numberoftracks - 1): for i in range(self._parent.numberoftracks - 1, self.track + 1): - self._parent.addTrack() + self._parent.add_track() def collide(self, x, y): """ @@ -329,7 +329,7 @@ def track(self, value): # Verify if the new track exists. In case not create it self._top = Track.whichTop(value) - if self.track >= len(self._parent._tracks): self._parent.addTrack() + if self.track >= len(self._parent._tracks): self._parent.add_track() # if do not exists in the track add it if self not in self._parent._tracks[self.track].periods: self._parent._tracks[self.track].periods.append(self) diff --git a/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py b/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py index 5e98ad0..6df5ef4 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py +++ b/pyforms/gui/Controls/ControlEventTimeline/TimelineWidget.py @@ -194,10 +194,10 @@ def import_csv(self, csvfileobject): for row in csvfileobject: if len(row) == 0: continue if row[0] == "T": - track = self.addTrack() + track = self.add_track() track.properties = row elif row[0] == "P": - period = self.addPeriod([0, 1, '-']) + period = self.add_period([0, 1, '-']) period.properties = row def export_csv(self, csvfileobject): @@ -275,16 +275,16 @@ def cleanLine(self, track_index=None): QMessageBox.about(self, "Error", "You must select a timebar first") return - def addTrack(self): + def add_track(self): t = Track(parent=self) self._tracks.append(t) self.setMinimumHeight(Track.whichTop(len(self._tracks))) return t - def addPeriod(self, value, track=0, color=None): + def add_period(self, value, row=0, color=None): """Adds an annotated interval.""" begin, end, title = value - period = TimelineDelta(begin, end, title=title, parent=self, top=Track.whichTop(track)) + period = TimelineDelta(begin, end, title=title, parent=self, top=Track.whichTop(row)) self._tracks[period.track].periods.append(period) return period @@ -429,7 +429,7 @@ def keyReleaseEvent(self, event): comment = "" if end > start: - self.addPeriod((start, end, comment), self._selected_track) + self.add_period((start, end, comment), self._selected_track) self.repaint() self._creating_event = False else: @@ -568,7 +568,7 @@ def numberoftracks(self, value): # self._n_tracks = value if value < len(self._tracks): for i in range(value, self._tracks + 1): - self.addTrack() + self.add_track() y = value * 34 + 20 if y + 40 > self.height(): self.setMinimumHeight(y + 40) diff --git a/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py b/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py index 00228f6..fb5adf1 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py +++ b/pyforms/gui/Controls/ControlEventTimeline/graphs_graph2event.py @@ -117,12 +117,12 @@ def __generage_events_evt(self): if last_value and not bool(value): if (i-1-last_index)>=self._mindiff.value: - self._timeline.addPeriod([last_index, i-1, self._eventname.value], int(self._rownumber.value) ) + self._timeline.add_period([last_index, i-1, self._eventname.value], int(self._rownumber.value) ) last_value = False last_index = None if last_value and (max_frame-last_index)>=self._mindiff.value: - self._timeline.addPeriod([last_index, max_frame, self._eventname.value], int(self._rownumber.value) ) + self._timeline.add_period([last_index, max_frame, self._eventname.value], int(self._rownumber.value) ) except Exception as e: traceback.print_exc() QMessageBox.warning( self, "Error!", str(e) ) diff --git a/pyforms/gui/Controls/ControlEventTimeline/import_window.py b/pyforms/gui/Controls/ControlEventTimeline/import_window.py index b0a1eca..098bdec 100644 --- a/pyforms/gui/Controls/ControlEventTimeline/import_window.py +++ b/pyforms/gui/Controls/ControlEventTimeline/import_window.py @@ -18,7 +18,7 @@ def __init__(self, timeline=None): super(BonsaiImportFileDlg, self).__init__('Import file') self._file = ControlFile('File to import') - self._fps = ControlNumber('Video FPS', 30) + self._fps = ControlNumber('Video FPS', default=30) self._formset = [('_fps', '_file')] @@ -161,7 +161,7 @@ def __import_bonsai_events(self): for index in range(0, len(pointEventValues)): pointEventValue = pointEventValues[index] eventsTypes[pointEventValue[0]] = currentTrack - self._timeline.addPeriod([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], track=currentTrack) + self._timeline.add_period([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], row=currentTrack) currentTrack = 1 @@ -176,7 +176,7 @@ def __import_bonsai_events(self): else: track = eventsTypes[row0[0]] - self._timeline.addPeriod([row0[1], row1[1], row0[0]], track=track) + self._timeline.add_period([row0[1], row1[1], row0[0]], row=track) @@ -186,42 +186,41 @@ def __import_bonsai_events_oldformat(self): with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: windows_events = [] points_events = [] + first_date = None for row in csvfile: row = row[:-1] #remove the newline character - if row.startswith('start'): - eventtype = 'start' - timestr = row[-33:] - eventname = row[:-33] - elif row.startswith('end'): + if row.endswith('WindowClosing'): split = row.rfind(' ') #eventtype = row[-split:] eventtype = 'end' - timestr = row[-33-split:-split] - eventname = row[:-33-split] - else: + timestr = row[split-33:split] + eventname = row[4:split-33] + elif row.endswith('PointEvent'): split = row.rfind(' ') eventtype = row[split+1:] timestr = row[split-33:split] - eventname = row[:-33-split] - - print(split) - print(eventtype) - print(timestr) - print(eventname) - + eventname = row[:split-33] + else: + eventtype = 'start' + timestr = row[-33:] + eventname = row[6:-33] + cvttime = dateutil.parser.parse(timestr.replace('T', ' ')) - seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() + cvttime = cvttime.replace(tzinfo=None) + if first_date is None: first_date = cvttime + + seconds = (cvttime - first_date).total_seconds() frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) if eventtype=='PointEvent': points_events.append([eventtype, frame, eventname]) else: if eventtype=='start': - windows_events.append( [[eventtype, frame, eventname]] ) + windows_events.append( [eventtype, frame, eventname] ) elif eventtype=='end': - windows_events[-1].append( [eventtype, frame, eventname] ) + windows_events.append( [eventtype, frame, eventname] ) windows_events = sorted(windows_events, key=lambda x: (x[0][0].capitalize(), x[0][1])) points_events = sorted(points_events, key=lambda x: (x[0].capitalize(), x[1])) @@ -234,11 +233,13 @@ def __import_bonsai_events_oldformat(self): for index in range(0, len(points_events)): eventtype, frame, eventname = points_events[index] events_types[eventname] = current_track - self._timeline.addPeriod([frame, frame + 50, eventname], track=current_track) + self._timeline.add_period([frame, frame+2, eventname], row=current_track) current_track = 1 - for start, end in windows_events: + for i in range(0, len(windows_events), 2): + start = windows_events[i] + end = windows_events[i+1] eventtype, frame_begin, eventname = start _, frame_end, _ = end @@ -249,4 +250,5 @@ def __import_bonsai_events_oldformat(self): else: track = events_types[eventname] - self._timeline.addPeriod([frame_begin, frame_end, eventname], track=track) \ No newline at end of file + print('add',eventname,track, frame_begin, frame_end) + self._timeline.add_period([frame_begin, frame_end, eventname], row=track) \ No newline at end of file From a1c5df8afca5511f8b53d167f7c78a82f58ccfee Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 1 Feb 2018 11:21:14 +0000 Subject: [PATCH 34/66] Update controls for the new syntax --- pyforms/controls.py | 10 +- pyforms/gui/controls/ControlBoundingSlider.py | 2 +- pyforms/gui/controls/ControlFile.py | 5 +- pyforms/gui/controls/ControlImage.py | 6 +- pyforms/gui/controls/ControlOpenGL.py | 6 +- .../ControlEventTimeline.py | 975 +++++++++--------- .../control_event_timeline/TimelineChart.py | 1 + .../control_event_timeline/TimelineDelta.py | 14 +- .../control_event_timeline/TimelinePointer.py | 4 +- .../TimelinePopupWindow.py | 12 +- .../control_event_timeline/TimelineWidget.py | 28 +- .../controls/control_event_timeline/Track.py | 3 +- .../graphs_eventsgenerator.py | 165 +-- .../graphs_properties.py | 25 +- .../control_event_timeline/import_window.py | 374 ++++--- .../controls/control_player/ControlPlayer.py | 6 +- .../controls/control_player/VideoGLWidget.py | 2 +- .../control_player/VideoQt5GLWidget.py | 2 +- setup.py | 2 +- 19 files changed, 892 insertions(+), 750 deletions(-) mode change 100755 => 100644 pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py mode change 100755 => 100644 pyforms/gui/controls/control_event_timeline/TimelinePointer.py mode change 100755 => 100644 pyforms/gui/controls/control_event_timeline/TimelineWidget.py diff --git a/pyforms/controls.py b/pyforms/controls.py index 36c871a..18ed926 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -33,14 +33,14 @@ from pyforms.gui.controls.ControlMatplotlib import ControlMatplotlib except Exception as e: logger.warning("Matplot lib not installed or not working properly") - logger.error(e) + logger.error(e, exc_info=True) if conf.PYFORMS_WEB_ENABLED: try: from pyforms.gui.controls.ControlWeb import ControlWeb except Exception as e: logger.warning("QtWebKit lib not installed or not working properly") - logger.error(e) + logger.error(e, exc_info=True) if conf.PYFORMS_GL_ENABLED: try: @@ -49,7 +49,7 @@ from pyforms.gui.controls.control_player.ControlPlayer import ControlPlayer except Exception as e: logger.warning("GL widgets or Opencv not installed") - logger.error(e) + logger.error(e, exc_info=True) if conf.PYFORMS_VISVIS_ENABLED: try: @@ -57,14 +57,14 @@ from pyforms.gui.controls.ControlVisVisVolume import ControlVisVisVolume except Exception as e: logger.warning("VisVis not installed") - logger.error(e) + logger.error(e, exc_info=True) if conf.PYFORMS_QSCINTILLA_ENABLED: try: from pyforms.gui.controls.ControlCodeEditor import ControlCodeEditor except Exception as e: logger.warning("QScintilla2 not installed") - logger.error(e) + logger.error(e, exc_info=True) elif conf.PYFORMS_MODE=='TERMINAL': diff --git a/pyforms/gui/controls/ControlBoundingSlider.py b/pyforms/gui/controls/ControlBoundingSlider.py index aaec0f3..dd29ea8 100644 --- a/pyforms/gui/controls/ControlBoundingSlider.py +++ b/pyforms/gui/controls/ControlBoundingSlider.py @@ -3,7 +3,7 @@ from pysettings import conf -from AnyQt import QtCore +from AnyQt import QtCore, _api from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QSpinBox from AnyQt.QtGui import QFont, QColor, QCursor, QPainter diff --git a/pyforms/gui/controls/ControlFile.py b/pyforms/gui/controls/ControlFile.py index 14c0ffb..ff064d2 100644 --- a/pyforms/gui/controls/ControlFile.py +++ b/pyforms/gui/controls/ControlFile.py @@ -7,14 +7,15 @@ import pyforms.utils.tools as tools -from AnyQt import uic +from AnyQt import uic, _api from AnyQt.QtWidgets import QFileDialog class ControlFile(ControlText): def __init__(self, *args, **kwargs): - super(ControlFile, self).__init__(label, default, helptext) + + super(ControlFile, self).__init__(*args, **kwargs) self.use_save_dialog = kwargs.get('use_save_dialog', False) def init_form(self): diff --git a/pyforms/gui/controls/ControlImage.py b/pyforms/gui/controls/ControlImage.py index 6d178d3..a8418e9 100644 --- a/pyforms/gui/controls/ControlImage.py +++ b/pyforms/gui/controls/ControlImage.py @@ -31,9 +31,9 @@ import platform if platform.system() == 'Darwin': - from pyforms.gui.controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + from pyforms.gui.controls.control_player.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget else: - from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget elif _api.USED_API == _api.QT_API_PYQT4: try: @@ -41,7 +41,7 @@ except: logger.debug("No OpenGL library available") - from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget import numpy as np diff --git a/pyforms/gui/controls/ControlOpenGL.py b/pyforms/gui/controls/ControlOpenGL.py index f78802a..15b0319 100644 --- a/pyforms/gui/controls/ControlOpenGL.py +++ b/pyforms/gui/controls/ControlOpenGL.py @@ -25,9 +25,9 @@ import platform if platform.system() == 'Darwin': - from pyforms.gui.controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + from pyforms.gui.controls.control_player.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget else: - from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget elif _api.USED_API == _api.QT_API_PYQT4: try: @@ -35,7 +35,7 @@ except: logger.debug("No OpenGL library available") - from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget class OpenglGLWidget(QGLWidget): diff --git a/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py b/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py old mode 100755 new mode 100644 index a95b33c..b5e02a7 --- a/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py +++ b/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py @@ -1,492 +1,499 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import csv, os +import csv +import os -from pysettings import conf -from AnyQt.QtWidgets import QWidget, QScrollArea, QColorDialog, QFileDialog, QMessageBox -from AnyQt.QtWidgets import QPushButton, QLabel, QSlider, QHBoxLayout, QVBoxLayout -from AnyQt import QtCore +from pysettings import conf + + +from AnyQt.QtWidgets import QWidget, QScrollArea, QColorDialog, QFileDialog, QMessageBox, QPushButton, QLabel, QSlider, QHBoxLayout, QVBoxLayout +from AnyQt import QtCore, _api + +from pyforms.gui.controls.control_event_timeline.TimelineChart import TimelineChart +from pyforms.gui.controls.ControlBase import ControlBase +from pyforms.gui.controls.control_event_timeline.TimelineWidget import TimelineWidget +from pyforms.gui.controls.control_event_timeline.TimelinePopupWindow import TimelinePopupWindow +from pyforms.gui.controls.control_event_timeline.import_window import ImportWindow + +from pyforms.gui.controls.control_event_timeline.graphs_graph2event import Graph2Event +from pyforms.gui.controls.control_event_timeline.graphs_properties import GraphsProperties +from pyforms.gui.controls.control_event_timeline.graphs_eventsgenerator import GraphsEventsGenerator -from pyforms.gui.controls.ControlBase import ControlBase -from pyforms.gui.controls.control_event_timeline.TimelineChart import TimelineChart -from pyforms.gui.controls.control_event_timeline.TimelineWidget import TimelineWidget -from pyforms.gui.controls.control_event_timeline.TimelinePopupWindow import TimelinePopupWindow -from pyforms.gui.controls.control_event_timeline.import_window import ImportWindow -from pyforms.gui.controls.control_event_timeline.graphs_graph2event import Graph2Event -from pyforms.gui.controls.control_event_timeline.graphs_properties import GraphsProperties -from pyforms.gui.controls.control_event_timeline.graphs_eventsgenerator import GraphsEventsGenerator class ControlEventTimeline(ControlBase, QWidget): - """ - Timeline events editor - """ - - def __init__(self, label="", default=0, max=100): - QWidget.__init__(self) - ControlBase.__init__(self, label, default) - self._max = 100 - self._graphs_prop_win = GraphsProperties(self._time, self) - self._graphsgenerator_win = GraphsEventsGenerator(self._time) - self._graph2event_win = Graph2Event(self._time) - - # Popup menus that only show when clicking on a TIMELINEDELTA object - self._deltaLockAction = self.add_popup_menu_option("Lock", self.__lockSelected, key='L') - self._deltaColorAction = self.add_popup_menu_option("Pick a color", self.__pickColor) - self._deltaRemoveAction = self.add_popup_menu_option("Remove", self.__removeSelected, key='Delete') - self._deltaActions = [self._deltaLockAction, self._deltaColorAction, self._deltaRemoveAction] - for action in self._deltaActions: - action.setVisible(False) - - self.add_popup_menu_option("-") - - self.add_popup_menu_option("Graphs", self.show_graphs_properties, icon=conf.PYFORMS_ICON_EVENTTIMELINE_GRAPH) - self.add_popup_menu_option("Apply a function to the graphs", self.__generate_graphs_events, - icon=conf.PYFORMS_ICON_EVENTTIMELINE_GRAPH) - self.add_popup_menu_option("Convert graph to events", self.__graph2event_event, - icon=conf.PYFORMS_ICON_EVENTTIMELINE_GRAPH) - - self.add_popup_menu_option("-") - - # General righ click popup menus - self.add_popup_menu_option("Rows", self.__setLinePropertiesEvent, - icon=conf.PYFORMS_ICON_EVENTTIMELINE_REMOVE) - self.add_popup_menu_option("-") - - - - self.add_popup_menu_option("-") - - self.add_popup_menu_option("Auto adjust rows", self.__auto_adjust_tracks_evt, - icon=conf.PYFORMS_ICON_EVENTTIMELINE_REFRESH) - self.add_popup_menu_option("Add a row", self.__add_track_2_bottom_evt, - icon=conf.PYFORMS_ICON_EVENTTIMELINE_ADD) - - self.add_popup_menu_option("-") - - clean_menu = self.add_popup_submenu('Clean') - - self.add_popup_menu_option('The current row', function_action=self.__cleanLine, submenu=clean_menu) - self.add_popup_menu_option('-') - self.add_popup_menu_option('All graphs', function_action=self.__cleanCharts, submenu=clean_menu) - self.add_popup_menu_option('-') - self.add_popup_menu_option('Everything', function_action=self.clean, submenu=clean_menu) - - def init_form(self): - # Get the current path of the file - rootPath = os.path.dirname(__file__) - - vlayout = QVBoxLayout() - hlayout = QHBoxLayout() - - if _api.USED_API == _api.QT_API_PYQT5: - hlayout.setContentsMargins(0,0,0,0) - vlayout.setContentsMargins(0,0,0,0) - elif _api.USED_API == _api.QT_API_PYQT4: - hlayout.setMargin(0) - vlayout.setMargin(0) - - self.setLayout(vlayout) - - # Add scroll area - scrollarea = QScrollArea() - scrollarea.setMinimumHeight(140) - scrollarea.setWidgetResizable(True) - scrollarea.keyPressEvent = self.__scrollAreaKeyPressEvent - scrollarea.keyReleaseEvent = self.__scrollAreaKeyReleaseEvent - vlayout.addWidget(scrollarea) - # vlayout.setContentsMargins(5, 5, 5, 5) - - # The timeline widget - widget = TimelineWidget(self) - widget._scroll = scrollarea - # widget.setMinimumHeight(1000) - scrollarea.setWidget(widget) - - # TODO Options buttons - # btn_1 = QtGui.QPushButton("?") - # btn_2 = QtGui.QPushButton("?") - # vlayout_options = QtGui.QVBoxLayout() - # vlayout_options.addWidget(btn_1) - # vlayout_options.addWidget(btn_2) - # hlayout.addLayout(vlayout_options) - # hlayout.addWidget(btn_1) - # hlayout.addWidget(btn_2) - - # Timeline zoom slider - slider = QSlider(QtCore.Qt.Horizontal) - slider.setFocusPolicy(QtCore.Qt.NoFocus) - slider.setMinimum(1) - slider.setMaximum(100) - slider.setValue(10) - slider.setPageStep(1) - slider.setTickPosition(QSlider.NoTicks) # TicksBothSides - slider.valueChanged.connect(self.__scaleSliderChange) - - slider_label_zoom_in = QLabel() - slider_label_zoom_out = QLabel() - slider_label_zoom_in.setPixmap(conf.PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_IN) - slider_label_zoom_out.setPixmap(conf.PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_OUT) - - self._zoomLabel = QLabel("100%") - hlayout.addWidget(self._zoomLabel) - hlayout.addWidget(slider_label_zoom_out) - hlayout.addWidget(slider) - hlayout.addWidget(slider_label_zoom_in) - # hlayout.setContentsMargins(5, 0, 5, 5) - # Import/Export Buttons - btn_import = QPushButton("Import") - - btn_import.setIcon(conf.PYFORMS_ICON_EVENTTIMELINE_IMPORT) - btn_import.clicked.connect(self.__import) - btn_export = QPushButton("Export") - - btn_export.setIcon(conf.PYFORMS_ICON_EVENTTIMELINE_EXPORT) - btn_export.clicked.connect(self.__export) - # importexport_vlayout = QtGui.QVBoxLayout() - # importexport_vlayout.adimdWidget(btn_import) - # importexport_vlayout.addWidget(btn_export) - # hlayout.addLayout(importexport_vlayout) - hlayout.addWidget(btn_import) - hlayout.addWidget(btn_export) - - vlayout.addLayout(hlayout) - - self._time = widget - self._scrollArea = scrollarea - - ########################################################################## - #### HELPERS/PUBLIC FUNCTIONS ############################################ - ########################################################################## - - def __add__(self, other): - if isinstance(other, TimelineChart): - self._graphs_prop_win += other - self._graphsgenerator_win += other - self._graph2event_win += other - return self - - def __sub__(self, other): - if isinstance(other, int): - self._graphs_prop_win -= other - self._graphsgenerator_win -= other - self._graph2event_win -= other - return self - - def rename_graph(self, graph_index, newname): - self._graphs_prop_win.rename_graph(graph_index, newname) - self._graphsgenerator_win.rename_graph(graph_index, newname) - self._graph2event_win.rename_graph(graph_index, newname) - - def add_period(self, value, row=0, color=None): - """ - - :param value: - :param row: - :param color: - :return: - """ - self._time.addPeriod(value, track, color) - self._time.repaint() - - def add_graph(self, name, data): - """ - - :param name: - :param data: - :return: - """ - self._time.add_chart(name, data) - - def import_graph(self, filename, frame_col=0, val_col=1): - """ - - :param filename: - :param frame_col: - :param val_col: - :return: - """ - self.__import() - self._import_window.import_chart(filename, frame_col, val_col) - - def import_graph_file(self, filename, separator=';', ignore_rows=0): - """ - - :param filename: - :param separator: - :param ignore_rows: - :return: - """ - csvfile = open(filename, 'U') - spamreader = csv.reader(csvfile, delimiter=separator) - for i in range(ignore_rows): next(spamreader, None) - chart = self._time.importchart_csv(spamreader) - chart.name = os.path.basename(filename).replace('.csv', '').replace('.CSV', '') - csvfile.close() - - def show_graphs_properties(self): - """ - - """ - self._graphs_prop_win.show() - self._time.repaint() - - def import_csv(self, csvfile): - """ - - :param csvfile: - """ - # If there are annotation in the timeline, show a warning - if len(self._time._tracks) > 0: # dict returns True if not empty - message = ["You are about to import new data. ", - "If you proceed, current annotations will be erased. ", - "Make sure to export current annotations first to save.", - "\n", - "Are you sure you want to proceed?"] - reply = QMessageBox.question(self, - "Warning!", - "".join(message), - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No) - - if reply != QMessageBox.Yes: - return - - self._time.import_csv(csvfile) - - def export_csv_file(self, filename): - with open(filename, 'w') as csvfile: - spamwriter = csv.writer(csvfile, dialect='excel') - self._time.export_csv(spamwriter) - - def import_csv_file(self, filename): - with open(filename, 'r') as csvfile: - spamreader = csv.reader(csvfile, dialect='excel') - self._time.import_csv(spamreader) - - ########################################################################## - #### EVENTS ############################################################## - ########################################################################## - - def mouse_moveover_timeline_event(self, event): - self._graphs_prop_win.mouse_moveover_timeline_event(event) - - - @property - def pointer_changed_event(self): - return self._time._pointer.moveEvent - - @pointer_changed_event.setter - def pointer_changed_event(self, value): - self._time._pointer.moveEvent = value - - def __auto_adjust_tracks_evt(self): - for i in range(len(self._time.tracks) - 1, -1, -1): - track = self._time.tracks[i] - if len(track) == 0: - self._time.remove_track(track) - else: - break - - def __add_track_2_bottom_evt(self): - self._time.addTrack() - - def __remove_track_from_bottom_evt(self): - if len(self._time.tracks) > 0: - track = self._time.tracks[-1] - if len(track) == 0: - self._time.remove_track(track) - - def __generate_graphs_events(self): - self._graphsgenerator_win.show() - - def __graph2event_event(self): - self._graph2event_win.show() - - ########################################################################## - #### PROPERTIES ########################################################## - ########################################################################## - - @property - def value(self): - return self._time.position - - @value.setter - def value(self, value): - ControlBase.value.fset(self, value) - self._time.position = value - - @property - def max(self): - return self._time.minimumWidth() - - @max.setter - def max(self, value): - self._max = value - self._time.setMinimumWidth(value) - self.repaint() - - @property - def form(self): - return self - - @property - def rows(self): - return self._time.tracks - - @property - def graphs(self): return self._time.graphs - - ########################################################################## - #### PRIVATE FUNCTIONS ################################################### - ########################################################################## - - def about_to_show_contextmenu_event(self): - for action in self._deltaActions: - action.setVisible( - True) if self._time._selected is not None else action.setVisible(False) - - - - def __setLinePropertiesEvent(self): - """ - This controls makes possible the edition of a track in the - timeline, based on the position of the mouse. - - Updates: - - Track label - - Track default color - """ - current_track = self._time.current_mouseover_track - parent = self._time - - # Tracks info dict and index - i = current_track - - # Save current default color to override with selected track color - timeline_default_color = parent.color - try: - parent.color = self._time._tracks[current_track].color - except Exception as e: - error_message = ("You tried to edit an empty track.", - "\n", - "Initialize it by creating an event first.") - QMessageBox.warning( - parent, "Attention!", "".join(error_message)) - return e - - # Create dialog - dialog = TimelinePopupWindow(parent, i) - dialog.setModal(True) # to disable main application window - - # If dialog is accepted, update dict info - if dialog._ui.exec_() == dialog.Accepted: - # Update label - if dialog.behavior is not None: - self._time._tracks[i].title = dialog.behavior - - # Update color - if self._time._tracks[i].color != dialog.color: - for delta in self._time._tracks[i].periods: - delta.color = dialog.color - self._time._tracks[i].color = dialog.color - self._time.repaint() - else: - pass - - # Restore timeline default color - parent.color = timeline_default_color - - def __lockSelected(self): - self._time.lockSelected() - - def __removeSelected(self): - self._time.removeSelected() - - def __import(self): - """Import annotations from a file.""" - if not hasattr(self, '_import_window'): self._import_window = ImportWindow(self) - self._import_window.show() - - def __export(self): - """Export annotations to a file.""" - - filename, ffilter = QFileDialog.getSaveFileName(parent=self, - caption="Export annotations file", - directory="untitled.csv", - filter="CSV Files (*.csv);;CSV Matrix Files (*.csv)", - options=QFileDialog.DontUseNativeDialog) - - filename = str(filename) - ffilter = str(ffilter) - if filename != "": - with open(filename, 'w') as csvfile: - spamwriter = csv.writer(csvfile, dialect='excel') - if ffilter == 'CSV Files (*.csv)': - self._time.export_csv(spamwriter) - elif ffilter == 'CSV Matrix Files (*.csv)': - self._time.export_2_csv_matrix(spamwriter) - - def __export_2_csv_matrix(self): - QMessageBox.warning( - self, "Important!", 'Please note that this file cannot be imported after.') - - filename = QFileDialog.getSaveFileName(parent=self, - caption="Export matrix file", - directory="untitled.csv", - filter="CSV Files (*.csv)", - options=QFileDialog.DontUseNativeDialog) - if filename != "": - with open(filename, 'w') as csvfile: - spamwriter = csv.writer(csvfile, dialect='excel') - self._time.export_2_csv_matrix(spamwriter) - - def __cleanLine(self): - reply = QMessageBox.question(self, 'Confirm', - "Are you sure you want to clean all the events on this track?", - QMessageBox.Yes | - QMessageBox.No, QMessageBox.No) - if reply == QMessageBox.Yes: - self._time.cleanLine(self._time.current_mouseover_track) - - def __cleanCharts(self): - reply = QMessageBox.question(self, 'Confirm', - "Are you sure you want to clean all the charts?", QMessageBox.Yes | - QMessageBox.No, QMessageBox.No) - if reply == QMessageBox.Yes: - self._time.cleanCharts() - - def clean(self): - reply = QMessageBox.question(self, 'Confirm', - "Are you sure you want to clean everything?", QMessageBox.Yes | - QMessageBox.No, QMessageBox.No) - if reply == QMessageBox.Yes: - self._time.clean() - - def __pickColor(self): - self._time.color = QColorDialog.getColor(self._time.color) - if self._time._selected != None: - self._time._selected.color = self._time.color - self._time.repaint() - - def __scaleSliderChange(self, value): - scale = 0.1 * value - self._time.setMinimumWidth(scale * self._max) - self._time.scale = scale - self._zoomLabel.setText(str(value * 10).zfill(3) + "%") - - def __scrollAreaKeyReleaseEvent(self, event): - modifiers = int(event.modifiers()) - self._time.keyReleaseEvent(event) - if modifiers is not QtCore.Qt.ControlModifier and \ - modifiers is not int(QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier) and \ - modifiers is not QtCore.Qt.ShiftModifier: - QScrollArea.keyReleaseEvent(self._scrollArea, event) - - def __scrollAreaKeyPressEvent(self, event): - modifiers = int(event.modifiers()) - if modifiers is not QtCore.Qt.ControlModifier and \ - modifiers is not int(QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier) and \ - modifiers is not QtCore.Qt.ShiftModifier: - QScrollArea.keyPressEvent(self._scrollArea, event) + """ + Timeline events editor + """ + + def __init__(self, label="", default=0, max=100): + QWidget.__init__(self) + ControlBase.__init__(self, label, default) + self._max = 100 + self._graphs_prop_win = GraphsProperties(self._time, self) + self._graphsgenerator_win = GraphsEventsGenerator(self._time) + self._graph2event_win = Graph2Event(self._time) + + # Popup menus that only show when clicking on a TIMELINEDELTA object + self._deltaLockAction = self.add_popup_menu_option("Lock", self.__lockSelected, key='L') + self._deltaColorAction = self.add_popup_menu_option("Pick a color", self.__pickColor) + self._deltaRemoveAction = self.add_popup_menu_option("Remove", self.__removeSelected, key='Delete') + self._deltaActions = [self._deltaLockAction, self._deltaColorAction, self._deltaRemoveAction] + for action in self._deltaActions: + action.setVisible(False) + + self.add_popup_menu_option("-") + + self.add_popup_menu_option("Graphs", self.show_graphs_properties, icon=conf.PYFORMS_ICON_EVENTTIMELINE_GRAPH) + self.add_popup_menu_option("Apply a function to the graphs", self.__generate_graphs_events, + icon=conf.PYFORMS_ICON_EVENTTIMELINE_GRAPH) + self.add_popup_menu_option("Convert graph to events", self.__graph2event_event, + icon=conf.PYFORMS_ICON_EVENTTIMELINE_GRAPH) + + self.add_popup_menu_option("-") + + # General righ click popup menus + self.add_popup_menu_option("Rows", self.__setLinePropertiesEvent, + icon=conf.PYFORMS_ICON_EVENTTIMELINE_REMOVE) + self.add_popup_menu_option("-") + + + + self.add_popup_menu_option("-") + + self.add_popup_menu_option("Auto adjust rows", self.__auto_adjust_tracks_evt, + icon=conf.PYFORMS_ICON_EVENTTIMELINE_REFRESH) + self.add_popup_menu_option("Add a row", self.__add_track_2_bottom_evt, + icon=conf.PYFORMS_ICON_EVENTTIMELINE_ADD) + + self.add_popup_menu_option("-") + + clean_menu = self.add_popup_submenu('Clean') + + self.add_popup_menu_option('The current row', function_action=self.__cleanLine, submenu=clean_menu) + self.add_popup_menu_option('-') + self.add_popup_menu_option('All graphs', function_action=self.__cleanCharts, submenu=clean_menu) + self.add_popup_menu_option('-') + self.add_popup_menu_option('Everything', function_action=self.clean, submenu=clean_menu) + + def init_form(self): + # Get the current path of the file + rootPath = os.path.dirname(__file__) + + vlayout = QVBoxLayout() + hlayout = QHBoxLayout() + + if _api.USED_API == _api.QT_API_PYQT5: + hlayout.setContentsMargins(0,0,0,0) + vlayout.setContentsMargins(0,0,0,0) + elif _api.USED_API == _api.QT_API_PYQT4: + hlayout.setMargin(0) + vlayout.setMargin(0) + + + + + self.setLayout(vlayout) + + # Add scroll area + scrollarea = QScrollArea() + scrollarea.setMinimumHeight(140) + scrollarea.setWidgetResizable(True) + scrollarea.keyPressEvent = self.__scrollAreaKeyPressEvent + scrollarea.keyReleaseEvent = self.__scrollAreaKeyReleaseEvent + vlayout.addWidget(scrollarea) + # vlayout.setContentsMargins(5, 5, 5, 5) + + # The timeline widget + widget = TimelineWidget(self) + widget._scroll = scrollarea + # widget.setMinimumHeight(1000) + scrollarea.setWidget(widget) + + # TODO Options buttons + # btn_1 = QtGui.QPushButton("?") + # btn_2 = QtGui.QPushButton("?") + # vlayout_options = QtGui.QVBoxLayout() + # vlayout_options.addWidget(btn_1) + # vlayout_options.addWidget(btn_2) + # hlayout.addLayout(vlayout_options) + # hlayout.addWidget(btn_1) + # hlayout.addWidget(btn_2) + + # Timeline zoom slider + slider = QSlider(QtCore.Qt.Horizontal) + slider.setFocusPolicy(QtCore.Qt.NoFocus) + slider.setMinimum(1) + slider.setMaximum(100) + slider.setValue(10) + slider.setPageStep(1) + slider.setTickPosition(QSlider.NoTicks) # TicksBothSides + slider.valueChanged.connect(self.__scaleSliderChange) + + slider_label_zoom_in = QLabel() + slider_label_zoom_out = QLabel() + slider_label_zoom_in.setPixmap(conf.PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_IN) + slider_label_zoom_out.setPixmap(conf.PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_OUT) + + self._zoomLabel = QLabel("100%") + hlayout.addWidget(self._zoomLabel) + hlayout.addWidget(slider_label_zoom_out) + hlayout.addWidget(slider) + hlayout.addWidget(slider_label_zoom_in) + # hlayout.setContentsMargins(5, 0, 5, 5) + # Import/Export Buttons + btn_import = QPushButton("Import") + + btn_import.setIcon(conf.PYFORMS_ICON_EVENTTIMELINE_IMPORT) + btn_import.clicked.connect(self.__import) + btn_export = QPushButton("Export") + + btn_export.setIcon(conf.PYFORMS_ICON_EVENTTIMELINE_EXPORT) + btn_export.clicked.connect(self.__export) + # importexport_vlayout = QtGui.QVBoxLayout() + # importexport_vlayout.adimdWidget(btn_import) + # importexport_vlayout.addWidget(btn_export) + # hlayout.addLayout(importexport_vlayout) + hlayout.addWidget(btn_import) + hlayout.addWidget(btn_export) + + vlayout.addLayout(hlayout) + + self._time = widget + self._scrollArea = scrollarea + + ########################################################################## + #### HELPERS/PUBLIC FUNCTIONS ############################################ + ########################################################################## + + def __add__(self, other): + if isinstance(other, TimelineChart): + self._graphs_prop_win += other + self._graphsgenerator_win += other + self._graph2event_win += other + return self + + def __sub__(self, other): + if isinstance(other, int): + self._graphs_prop_win -= other + self._graphsgenerator_win -= other + self._graph2event_win -= other + return self + + def rename_graph(self, graph_index, newname): + self._graphs_prop_win.rename_graph(graph_index, newname) + self._graphsgenerator_win.rename_graph(graph_index, newname) + self._graph2event_win.rename_graph(graph_index, newname) + + def add_period(self, value, row=0, color=None): + """ + + :param value: + :param row: + :param color: + :return: + """ + self._time.add_period(value, row, color) + self._time.repaint() + + def add_graph(self, name, data): + """ + + :param name: + :param data: + :return: + """ + self._time.add_chart(name, data) + + def import_graph(self, filename, frame_col=0, val_col=1): + """ + + :param filename: + :param frame_col: + :param val_col: + :return: + """ + self.__import() + self._import_window.import_chart(filename, frame_col, val_col) + + def import_graph_file(self, filename, separator=';', ignore_rows=0): + """ + + :param filename: + :param separator: + :param ignore_rows: + :return: + """ + csvfile = open(filename, 'U') + spamreader = csv.reader(csvfile, delimiter=separator) + for i in range(ignore_rows): next(spamreader, None) + chart = self._time.importchart_csv(spamreader) + chart.name = os.path.basename(filename).replace('.csv', '').replace('.CSV', '') + csvfile.close() + + def show_graphs_properties(self): + """ + + """ + self._graphs_prop_win.show() + self._time.repaint() + + def import_csv(self, csvfile): + """ + + :param csvfile: + """ + # If there are annotation in the timeline, show a warning + if len(self._time._tracks) > 0: # dict returns True if not empty + message = ["You are about to import new data. ", + "If you proceed, current annotations will be erased. ", + "Make sure to export current annotations first to save.", + "\n", + "Are you sure you want to proceed?"] + reply = QMessageBox.question(self, + "Warning!", + "".join(message), + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No) + + if reply != QMessageBox.Yes: + return + + self._time.import_csv(csvfile) + + def export_csv_file(self, filename): + with open(filename, 'w') as csvfile: + spamwriter = csv.writer(csvfile, dialect='excel') + self._time.export_csv(spamwriter) + + def import_csv_file(self, filename): + with open(filename, 'r') as csvfile: + spamreader = csv.reader(csvfile, dialect='excel') + self._time.import_csv(spamreader) + + ########################################################################## + #### EVENTS ############################################################## + ########################################################################## + + def mouse_moveover_timeline_event(self, event): + self._graphs_prop_win.mouse_moveover_timeline_event(event) + + + @property + def pointer_changed_event(self): + return self._time._pointer.moveEvent + + @pointer_changed_event.setter + def pointer_changed_event(self, value): + self._time._pointer.moveEvent = value + + def __auto_adjust_tracks_evt(self): + for i in range(len(self._time.tracks) - 1, -1, -1): + track = self._time.tracks[i] + if len(track) == 0: + self._time.remove_track(track) + else: + break + + def __add_track_2_bottom_evt(self): + self._time.add_track() + + def __remove_track_from_bottom_evt(self): + if len(self._time.tracks) > 0: + track = self._time.tracks[-1] + if len(track) == 0: + self._time.remove_track(track) + + def __generate_graphs_events(self): + self._graphsgenerator_win.show() + + def __graph2event_event(self): + self._graph2event_win.show() + + ########################################################################## + #### PROPERTIES ########################################################## + ########################################################################## + + @property + def value(self): + return self._time.position + + @value.setter + def value(self, value): + ControlBase.value.fset(self, value) + self._time.position = value + + @property + def max(self): + return self._time.minimumWidth() + + @max.setter + def max(self, value): + self._max = value + self._time.setMinimumWidth(value) + self.repaint() + + @property + def form(self): + return self + + @property + def rows(self): + return self._time.tracks + + @property + def graphs(self): return self._time.graphs + + ########################################################################## + #### PRIVATE FUNCTIONS ################################################### + ########################################################################## + + def about_to_show_contextmenu_event(self): + for action in self._deltaActions: + action.setVisible( + True) if self._time._selected is not None else action.setVisible(False) + + + + def __setLinePropertiesEvent(self): + """ + This controls makes possible the edition of a track in the + timeline, based on the position of the mouse. + + Updates: + - Track label + - Track default color + """ + current_track = self._time.current_mouseover_track + parent = self._time + + # Tracks info dict and index + i = current_track + + # Save current default color to override with selected track color + timeline_default_color = parent.color + try: + parent.color = self._time._tracks[current_track].color + except Exception as e: + error_message = ("You tried to edit an empty track.", + "\n", + "Initialize it by creating an event first.") + QMessageBox.warning( + parent, "Attention!", "".join(error_message)) + return e + + # Create dialog + dialog = TimelinePopupWindow(parent, i) + dialog.setModal(True) # to disable main application window + + # If dialog is accepted, update dict info + if dialog._ui.exec_() == dialog.Accepted: + # Update label + if dialog.behavior is not None: + self._time._tracks[i].title = dialog.behavior + + # Update color + if self._time._tracks[i].color != dialog.color: + for delta in self._time._tracks[i].periods: + delta.color = dialog.color + self._time._tracks[i].color = dialog.color + self._time.repaint() + else: + pass + + # Restore timeline default color + parent.color = timeline_default_color + + def __lockSelected(self): + self._time.lockSelected() + + def __removeSelected(self): + self._time.removeSelected() + + def __import(self): + """Import annotations from a file.""" + if not hasattr(self, '_import_window'): self._import_window = ImportWindow(self) + self._import_window.show() + + def __export(self): + """Export annotations to a file.""" + + filename, ffilter = QFileDialog.getSaveFileName(parent=self, + caption="Export annotations file", + directory="untitled.csv", + filter="CSV Files (*.csv);;CSV Matrix Files (*.csv)", + options=QFileDialog.DontUseNativeDialog) + + filename = str(filename) + ffilter = str(ffilter) + if filename != "": + with open(filename, 'w') as csvfile: + spamwriter = csv.writer(csvfile, dialect='excel') + if ffilter == 'CSV Files (*.csv)': + self._time.export_csv(spamwriter) + elif ffilter == 'CSV Matrix Files (*.csv)': + self._time.export_2_csv_matrix(spamwriter) + + def __export_2_csv_matrix(self): + QMessageBox.warning( + self, "Important!", 'Please note that this file cannot be imported after.') + + filename = QFileDialog.getSaveFileName(parent=self, + caption="Export matrix file", + directory="untitled.csv", + filter="CSV Files (*.csv)", + options=QFileDialog.DontUseNativeDialog) + if filename != "": + with open(filename, 'w') as csvfile: + spamwriter = csv.writer(csvfile, dialect='excel') + self._time.export_2_csv_matrix(spamwriter) + + def __cleanLine(self): + reply = QMessageBox.question(self, 'Confirm', + "Are you sure you want to clean all the events on this track?", + QMessageBox.Yes | + QMessageBox.No, QMessageBox.No) + if reply == QMessageBox.Yes: + self._time.cleanLine(self._time.current_mouseover_track) + + def __cleanCharts(self): + reply = QMessageBox.question(self, 'Confirm', + "Are you sure you want to clean all the charts?", QMessageBox.Yes | + QMessageBox.No, QMessageBox.No) + if reply == QMessageBox.Yes: + self._time.cleanCharts() + + def clean(self): + reply = QMessageBox.question(self, 'Confirm', + "Are you sure you want to clean everything?", QMessageBox.Yes | + QMessageBox.No, QMessageBox.No) + if reply == QMessageBox.Yes: + self._time.clean() + + def __pickColor(self): + self._time.color = QColorDialog.getColor(self._time.color) + if self._time._selected != None: + self._time._selected.color = self._time.color + self._time.repaint() + + def __scaleSliderChange(self, value): + scale = 0.1 * value + self._time.setMinimumWidth(scale * self._max) + self._time.scale = scale + self._zoomLabel.setText(str(value * 10).zfill(3) + "%") + + def __scrollAreaKeyReleaseEvent(self, event): + modifiers = int(event.modifiers()) + self._time.keyReleaseEvent(event) + if modifiers is not QtCore.Qt.ControlModifier and \ + modifiers is not int(QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier) and \ + modifiers is not QtCore.Qt.ShiftModifier: + QScrollArea.keyReleaseEvent(self._scrollArea, event) + + def __scrollAreaKeyPressEvent(self, event): + modifiers = int(event.modifiers()) + if modifiers is not QtCore.Qt.ControlModifier and \ + modifiers is not int(QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier) and \ + modifiers is not QtCore.Qt.ShiftModifier: + QScrollArea.keyPressEvent(self._scrollArea, event) diff --git a/pyforms/gui/controls/control_event_timeline/TimelineChart.py b/pyforms/gui/controls/control_event_timeline/TimelineChart.py index 24f8fcc..a5cf8cf 100644 --- a/pyforms/gui/controls/control_event_timeline/TimelineChart.py +++ b/pyforms/gui/controls/control_event_timeline/TimelineChart.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- from AnyQt.QtGui import QColor + class TimelineChart(object): """ """ diff --git a/pyforms/gui/controls/control_event_timeline/TimelineDelta.py b/pyforms/gui/controls/control_event_timeline/TimelineDelta.py index ec29c48..202f2f0 100644 --- a/pyforms/gui/controls/control_event_timeline/TimelineDelta.py +++ b/pyforms/gui/controls/control_event_timeline/TimelineDelta.py @@ -1,10 +1,14 @@ # !/usr/bin/python # -*- coding: utf-8 -*- + +from AnyQt.QtWidgets import QInputDialog +from AnyQt.QtGui import QColor + from pyforms.gui.controls.control_event_timeline.Track import Track -from pyforms import BaseWidget + +from pyforms import BaseWidget from pyforms.controls import ControlText, ControlNumber, ControlButton -from AnyQt.QtWidgets import QInputDialog -from AnyQt.QtGui import QColor + class DeltaEditWindow(BaseWidget): @@ -100,7 +104,7 @@ def checkNumberOfTracks(self): """ if self.track >= (self._parent.numberoftracks - 1): for i in range(self._parent.numberoftracks - 1, self.track + 1): - self._parent.addTrack() + self._parent.add_track() def collide(self, x, y): """ @@ -316,7 +320,7 @@ def track(self, value): # Verify if the new track exists. In case not create it self._top = Track.whichTop(value) - if self.track >= len(self._parent._tracks): self._parent.addTrack() + if self.track >= len(self._parent._tracks): self._parent.add_track() # if do not exists in the track add it if self not in self._parent._tracks[self.track].periods: self._parent._tracks[self.track].periods.append(self) diff --git a/pyforms/gui/controls/control_event_timeline/TimelinePointer.py b/pyforms/gui/controls/control_event_timeline/TimelinePointer.py old mode 100755 new mode 100644 index 3f7007e..ab9f6c4 --- a/pyforms/gui/controls/control_event_timeline/TimelinePointer.py +++ b/pyforms/gui/controls/control_event_timeline/TimelinePointer.py @@ -1,7 +1,9 @@ # !/usr/bin/python # -*- coding: utf-8 -*- + from AnyQt.QtGui import QColor -from AnyQt import QtCore +from AnyQt import QtCore + class TimelinePointer(object): def __init__(self, position, parent): diff --git a/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py b/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py index af27144..7087f6d 100644 --- a/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py +++ b/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py @@ -1,11 +1,15 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -import pyforms.utils.tools as tools + +from pysettings import conf from AnyQt.QtWidgets import QDialog, QInputDialog, QColorDialog -from AnyQt.QtGui import QColor, QPixmap, QFont, QPainter -from AnyQt import uic -from AnyQt import QtCore +from AnyQt.QtGui import QColor, QPixmap, QFont, QPainter +from AnyQt import uic +from AnyQt import QtCore + + +import pyforms.utils.tools as tools class TimelinePopupWindow(QDialog): diff --git a/pyforms/gui/controls/control_event_timeline/TimelineWidget.py b/pyforms/gui/controls/control_event_timeline/TimelineWidget.py old mode 100755 new mode 100644 index 518e4cb..157d61a --- a/pyforms/gui/controls/control_event_timeline/TimelineWidget.py +++ b/pyforms/gui/controls/control_event_timeline/TimelineWidget.py @@ -1,13 +1,15 @@ # !/usr/bin/python # -*- coding: utf-8 -*- + + from AnyQt.QtWidgets import QWidget, QMessageBox -from AnyQt.QtGui import QColor, QPainter, QFont, QCursor -from AnyQt import QtCore +from AnyQt.QtGui import QColor, QPainter, QFont, QCursor +from AnyQt import QtCore -from pyforms.gui.controls.control_event_timeline.Track import Track -from pyforms.gui.controls.control_event_timeline.TimelinePointer import TimelinePointer -from pyforms.gui.controls.control_event_timeline.TimelineDelta import TimelineDelta -from pyforms.gui.controls.control_event_timeline.TimelineChart import TimelineChart +from pyforms.gui.controls.control_event_timeline.Track import Track +from pyforms.gui.controls.control_event_timeline.TimelinePointer import TimelinePointer +from pyforms.gui.controls.control_event_timeline.TimelineDelta import TimelineDelta +from pyforms.gui.controls.control_event_timeline.TimelineChart import TimelineChart class TimelineWidget(QWidget): @@ -186,10 +188,10 @@ def import_csv(self, csvfileobject): for row in csvfileobject: if len(row) == 0: continue if row[0] == "T": - track = self.addTrack() + track = self.add_track() track.properties = row elif row[0] == "P": - period = self.addPeriod([0, 1, '-']) + period = self.add_period([0, 1, '-']) period.properties = row def export_csv(self, csvfileobject): @@ -267,16 +269,16 @@ def cleanLine(self, track_index=None): QMessageBox.about(self, "Error", "You must select a timebar first") return - def addTrack(self): + def add_track(self): t = Track(parent=self) self._tracks.append(t) self.setMinimumHeight(Track.whichTop(len(self._tracks))) return t - def addPeriod(self, value, track=0, color=None): + def add_period(self, value, row=0, color=None): """Adds an annotated interval.""" begin, end, title = value - period = TimelineDelta(begin, end, title=title, parent=self, top=Track.whichTop(track)) + period = TimelineDelta(begin, end, title=title, parent=self, top=Track.whichTop(row)) self._tracks[period.track].periods.append(period) return period @@ -421,7 +423,7 @@ def keyReleaseEvent(self, event): comment = "" if end > start: - self.addPeriod((start, end, comment), self._selected_track) + self.add_period((start, end, comment), self._selected_track) self.repaint() self._creating_event = False else: @@ -560,7 +562,7 @@ def numberoftracks(self, value): # self._n_tracks = value if value < len(self._tracks): for i in range(value, self._tracks + 1): - self.addTrack() + self.add_track() y = value * 34 + 20 if y + 40 > self.height(): self.setMinimumHeight(y + 40) diff --git a/pyforms/gui/controls/control_event_timeline/Track.py b/pyforms/gui/controls/control_event_timeline/Track.py index ddb908a..c44e187 100644 --- a/pyforms/gui/controls/control_event_timeline/Track.py +++ b/pyforms/gui/controls/control_event_timeline/Track.py @@ -1,7 +1,8 @@ # !/usr/bin/python # -*- coding: utf-8 -*- + from AnyQt.QtGui import QColor -from AnyQt import QtCore +from AnyQt import QtCore class Track(object): """ diff --git a/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py b/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py index cd10195..9d03ada 100644 --- a/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py +++ b/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py @@ -1,4 +1,5 @@ -from pyforms import BaseWidget +import csv, sys +from pyforms import BaseWidget from pyforms.controls import ControlProgress from pyforms.controls import ControlButton from pyforms.controls import ControlList @@ -8,109 +9,123 @@ from pyforms.controls import ControlText from pyforms.controls import ControlNumber from pyforms.controls import ControlLabel -from AnyQt.QtWidgets import QMessageBox +import traceback +import time +import datetime + +from pysettings import conf +from AnyQt.QtWidgets import QMessageBox + + class GraphsEventsGenerator(BaseWidget): - def __init__(self, timeline=None): - super(GraphsEventsGenerator, self).__init__('Apply a function to the graph values', parent_win=timeline) - self.setContentsMargins(10, 10, 10, 10) - self._timeline = timeline + def __init__(self, timeline=None): + super(GraphsEventsGenerator, self).__init__('Apply a function to the graph values', parent_win=timeline) + self.setContentsMargins(10, 10, 10, 10) + self._timeline = timeline + + + # Definition of the forms fields + self._graphs_list = ControlList('Graphs list (try double click)', readonly=False, select_entire_row=True) + self._equation = ControlTextArea('Equation') + self._graphname = ControlText('Graph name') + self._genevts_btn = ControlButton('Generate graph') + + self._formset = [ + ( + ['_graphs_list'], + '||', + [ + '_graphname', + '_equation', + '_genevts_btn', + ] + ), + ] - # Definition of the forms fields - self._graphs_list = ControlList('Graphs list (try double click)') - self._equation = ControlTextArea('Equation') - self._graphname = ControlText('Graph name') - self._genevts_btn = ControlButton('Generate graph') + self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt + self._graphs_list.readonly = True + self._graphs_list.select_entire_row = True + self._genevts_btn.value = self.__generage_events_evt - - self._formset = [ - ( - ['_graphs_list'], - '||', - [ - '_graphname', - '_equation', - '_genevts_btn', - ] - ), - ] - self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt - self._graphs_list.readonly = True - self._graphs_list.select_entire_row = True - self._genevts_btn.value = self.__generage_events_evt + def __add__(self, other): + self._graphs_list += [other.name] + return self + def __sub__(self, other): + self._graphs_list -= other + return self - def __add__(self, other): - self._graphs_list += [other.name] - return self + def rename_graph(self, graph_index, newname): + self._graphs_list.set_value(graph_index, 0, newname) - def __sub__(self, other): - self._graphs_list -= other - return self + @property + def graphs(self): + return self._timeline._charts - def rename_graph(self, graph_index, newname): - self._graphs_list.set_value(graph_index, 0, newname) + def show(self): + super(GraphsEventsGenerator, self).show() - @property - def graphs(self): - return self._timeline._charts + if len(self._graphname.value.strip())==0: + self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) - def show(self): - super(GraphsEventsGenerator, self).show() - if len(self._graphname.value.strip())==0: - self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) + def __cell_double_clicked_evt(self, row, column): + if len(self._equation.value.strip())==0: + self._equation.value += '[{0}]'.format( self._graphs_list.value[row][column] ) + else: + self._equation.value += ' and [{0}]'.format( self._graphs_list.value[row][column] ) - def __cell_double_clicked_evt(self, row, column): - if len(self._equation.value.strip())==0: - self._equation.value += '[{0}]'.format( self._graphs_list.value[row][column] ) - else: - self._equation.value += ' and [{0}]'.format( self._graphs_list.value[row][column] ) + def __generage_events_evt(self): + if len(self._graphname.value.strip())==0: + QMessageBox.warning( + self, "Attention!", 'The graph name cannot be empty') + return + if len(self._equation.value.strip())==0: + QMessageBox.warning( + self, "Attention!", 'The equation cannot be empty') + return - def __generage_events_evt(self): - if len(self._graphname.value.strip())==0: - QMessageBox.warning( - self, "Attention!", 'The graph name cannot be empty') - return + max_frame = 0 + equation = self._equation.value + for i, values in enumerate(self._graphs_list.value): + graphname = '[{0}]'.format(values[0]) - if len(self._equation.value.strip())==0: - QMessageBox.warning( - self, "Attention!", 'The equation cannot be empty') - return + if graphname in equation: max_frame = max(max_frame, len(self.graphs[i])) - max_frame = 0 - equation = self._equation.value - for i, values in enumerate(self._graphs_list.value): - graphname = '[{0}]'.format(values[0]) + equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i) ) + + graphs = self.graphs + data = [] + try: + for i in range(max_frame): - if graphname in equation: max_frame = max(max_frame, len(self.graphs[i])) + try: + value = eval(equation) + except: + value = None - equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i) ) - - graphs = self.graphs - data = [] - try: - for i in range(max_frame): - data.append( (i, eval(equation)) ) - self._timeline.add_chart(self._graphname.value, data) + data.append( (i, value) ) + self._timeline.add_chart(self._graphname.value, data) - self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) - except Exception as e: - QMessageBox.warning( self, "Error!", str(e) ) + self._graphname.value = "generated-graph-{0}".format( len(self._timeline.graphs)) + except Exception as e: + traceback.print_exc() + QMessageBox.warning( self, "Error!", str(e) ) - + ################################################################################################################## ################################################################################################################## ################################################################################################################## # Execute the application if __name__ == "__main__": - import pyforms - pyforms.start_app(GraphsEventsGenerator, geometry=(0, 0, 600, 400)) + import pyforms + pyforms.start_app(GraphsEventsGenerator, geometry=(0, 0, 600, 400)) diff --git a/pyforms/gui/controls/control_event_timeline/graphs_properties.py b/pyforms/gui/controls/control_event_timeline/graphs_properties.py index 9af1487..8227afe 100644 --- a/pyforms/gui/controls/control_event_timeline/graphs_properties.py +++ b/pyforms/gui/controls/control_event_timeline/graphs_properties.py @@ -7,6 +7,10 @@ from pyforms.controls import ControlSlider from pyforms.controls import ControlText from pyforms.controls import ControlLabel +from pysettings import conf + +if conf.PYFORMS_MODE=='GUI': + from AnyQt.QtWidgets import QColorDialog logger = logging.getLogger(__name__) @@ -24,12 +28,13 @@ def __init__(self, timelineWidget=None, parent_win=None): # Definition of the forms fields self._graphs_list = ControlList('Graphs list') self._name = ControlText('Name') - self._min_value = ControlNumber('Min', 0, -sys.float_info.max, sys.float_info.max) - self._max_value = ControlNumber('Max', 0, -sys.float_info.max, sys.float_info.max) - self._values_zoom = ControlSlider('Amplitude', 100, 60, 400) - self._values_top = ControlNumber('Bottom', 0, -1000, 1000) + self._min_value = ControlNumber('Min', default=0, minimum=-sys.float_info.max, maximum=sys.float_info.max) + self._max_value = ControlNumber('Max', default=0, minimum=-sys.float_info.max, maximum=sys.float_info.max) + self._values_zoom = ControlSlider('Amplitude', default=100, minimum=60, maximum=400) + self._values_top = ControlNumber('Bottom', default=0, minimum=-1000, maximum=1000) self._remove_graph_btn = ControlButton('Remove graph') self._value = ControlLabel() + self._pickcolor = ControlButton('Pick color', default=self.__pickcolor_evt) self._graphs_list.readonly = True @@ -41,7 +46,7 @@ def __init__(self, timelineWidget=None, parent_win=None): ' ', '_name', ('_min_value', '_max_value', ' '), - ('_values_top', ' '), + ('_values_top', '_pickcolor'), '_values_zoom', 'info:Choose one graph and move the mouse over \nthe timeline to visualize the coordenates.', '_value' @@ -66,6 +71,7 @@ def __init__(self, timelineWidget=None, parent_win=None): self._values_zoom.enabled = False self._values_top.enabled = False self._remove_graph_btn.enabled = False + self._pickcolor.enabled = False self._remove_graph_btn.value = self.__remove_chart @@ -97,6 +103,13 @@ def show(self): super(GraphsProperties, self).show() self._loaded = False + def __pickcolor_evt(self): + color = QColorDialog.getColor( + self._current_selected_graph._color, + self, 'Pick a color for the graph') + self._current_selected_graph._color = color + self._timeline.repaint() + def __remove_chart(self): index = self._graphs_list.selected_row_index @@ -110,6 +123,7 @@ def __remove_chart(self): self._values_zoom.enabled = False self._values_top.enabled = False self._remove_graph_btn.enabled = False + self._pickcolor.enabled = False self._timeline.repaint() self._mainwindow -= index @@ -143,6 +157,7 @@ def __graphs_list_selection_changed(self): self._values_zoom.enabled = True self._values_top.enabled = True self._remove_graph_btn.enabled = True + self._pickcolor.enabled = True self._current_selected_graph = graph del self._updating_properties diff --git a/pyforms/gui/controls/control_event_timeline/import_window.py b/pyforms/gui/controls/control_event_timeline/import_window.py index f4c4047..85d8c4a 100644 --- a/pyforms/gui/controls/control_event_timeline/import_window.py +++ b/pyforms/gui/controls/control_event_timeline/import_window.py @@ -7,157 +7,247 @@ from pyforms.controls import ControlFile from pyforms.controls import ControlNumber - + import time import datetime - +import dateutil.parser class BonsaiImportFileDlg(BaseWidget): - def __init__(self, timeline=None): - super(BonsaiImportFileDlg, self).__init__('Import file') + def __init__(self, timeline=None): + super(BonsaiImportFileDlg, self).__init__('Import file') - self._file = ControlFile('File to import') - self._fps = ControlNumber('Video FPS', 30) + self._file = ControlFile('File to import') + self._fps = ControlNumber('Video FPS', default=30) - self._formset = [('_fps', '_file')] + self._formset = [('_fps', '_file')] - #self._file.value = '/home/ricardo/Desktop/rat1e2.csv' + #self._file.value = '/home/ricardo/Desktop/rat1e2.csv' class ImportWindow(BaseWidget): - def __init__(self, timeline=None): - super(ImportWindow, self).__init__('Import file', parent_win=timeline) - self.setContentsMargins(10, 10, 10, 10) - self._timeline = timeline - - # Definition of the forms fields - self._filetype = ControlCombo('Please select the type of file you would like to import:') - self._importButton = ControlButton('Import') - self._panel = ControlEmptyWidget('Panel') - self._file = ControlFile('File to import') - - self._panel.value = self._file - self._filetype.add_item('Events file', 0) - self._filetype.add_item('Graph file', 1) - self._filetype.add_item('Bonsai events file', 2) - - self._formset = [ - ('_filetype', ' '), - '_panel', - (' ', '_importButton'), ' '] - - self._filetype.changed_event = self.__fileTypeChanged - self._importButton.value = self.__importData - - from pyforms.gui.dialogs.csv_parser import CsvParserDialog - self._graphCsvParserDlg = CsvParserDialog() - self._graphCsvParserDlg.xField.label = "Value column" - self._graphCsvParserDlg.yField.hide() - self._graphCsvParserDlg.zField.hide() - self._graphCsvParserDlg.loadButton.hide() - - self._bonsaiImportDlg = BonsaiImportFileDlg() - - def __fileTypeChanged(self): - if self._filetype.value == 0: - self._panel.value = self._file - - elif self._filetype.value == 1: - self._panel.value = self._graphCsvParserDlg - - elif self._filetype.value == 2: - self._panel.value = self._bonsaiImportDlg - - def __importData(self): - if self._filetype.value == 0: - separator = ',' - with open(self._file.value, 'rU') as csvfile: - line = csvfile.readline() - if ";" in line: - separator = ';' - with open(self._file.value, 'rU') as csvfile: - csvfile = csv.reader(csvfile, delimiter=separator) - self._timeline._time.import_csv(csvfile) - - elif self._filetype.value == 1: - self._timeline._time.importchart_csv(self._graphCsvParserDlg) - self._timeline.show_graphs_properties() - - elif self._filetype.value == 2: - with open(self._bonsaiImportDlg._file.value, 'rU') as csvfile: - values = [] - pointEventValues = [] - csvfile = csv.reader(csvfile, delimiter=' ') - for row in csvfile: # strip Start/End word from all events names which are not PointEven - try: - timestr = row[1].rstrip('0') - cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S.%f") - except: - timestr = row[1] - cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S") - - seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() - frame = int(round(self._bonsaiImportDlg._fps.value * seconds)) - - if row[2] == "PointEvent": - eventtype = row[0] - pointEventValues.append([eventtype, frame, row[2]]) - else: - if row[0].startswith('Start'): - eventtype = row[0][len('Start'):] # strip Start word from the beginning - else: - eventtype = row[0][len('End'):] # strip End word from the beginning - values.append([eventtype, frame, row[2]]) - - values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) - pointEventValues = sorted(pointEventValues, key=lambda x: (x[0].capitalize(), x[1])) - ntracks = len(set([x[0] for x in values])) + 1 - - # collapse - events = [] - eventsTypes = {} # Events names - currentTrack = 0 - for index in range(0, len(pointEventValues)): - pointEventValue = pointEventValues[index] - eventsTypes[pointEventValue[0]] = currentTrack - self._timeline.addPeriod([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], track=currentTrack) - - currentTrack = 1 - - for index in range(0, len(values), 2): - row0 = values[index] - row1 = values[index + 1] - - if row0[0] not in eventsTypes: - eventsTypes[row0[0]] = currentTrack - track = currentTrack - currentTrack += 1 - else: - track = eventsTypes[row0[0]] - - self._timeline.addPeriod([row0[1], row1[1], row0[0]], track=track) - - self._timeline.repaint() - self._timeline._time.repaint() - self.close() # pylint: disable=no-member - - - def import_chart(self, filename, frame_col=0, val_col=1): - self._filetype.value = 1 - self._graphCsvParserDlg.filename = filename - self._graphCsvParserDlg.frameColumn = frame_col - self._graphCsvParserDlg.xColumn = val_col - - - - -################################################################################################################## -################################################################################################################## -################################################################################################################## - -# Execute the application -if __name__ == "__main__": - import pyforms - pyforms.start_app(ImportWindow, geometry=(0, 0, 600, 400)) + def __init__(self, timeline=None): + super(ImportWindow, self).__init__('Import file', parent_win=timeline) + self.setContentsMargins(10, 10, 10, 10) + self._timeline = timeline + + # Definition of the forms fields + self._filetype = ControlCombo('Please select the type of file you would like to import:') + self._importButton = ControlButton('Import') + self._panel = ControlEmptyWidget('Panel') + self._file = ControlFile('File to import') + + self._panel.value = self._file + self._filetype.add_item('Events file', 0) + self._filetype.add_item('Graph file', 1) + self._filetype.add_item('Bonsai events file', 2) + self._filetype.add_item('Bonsai events file (old format)', 3) + + self._formset = [ + ('_filetype', ' '), + '_panel', + (' ', '_importButton'), ' '] + + self._filetype.changed_event = self.__fileTypeChanged + self._importButton.value = self.__importData + + from pyforms.gui.dialogs.csv_parser import CsvParserDialog + self._graphCsvParserDlg = CsvParserDialog() + self._graphCsvParserDlg.xField.label = "Value column" + self._graphCsvParserDlg.yField.hide() + self._graphCsvParserDlg.zField.hide() + self._graphCsvParserDlg.loadButton.hide() + + self._bonsai_import_dlg = BonsaiImportFileDlg() + + def __fileTypeChanged(self): + if self._filetype.value == 0: + self._panel.value = self._file + + elif self._filetype.value == 1: + self._panel.value = self._graphCsvParserDlg + + elif self._filetype.value in [2, 3]: + self._panel.value = self._bonsai_import_dlg + + + + + + + + + + + + + + def __importData(self): + if self._filetype.value == 0: + separator = ',' + with open(self._file.value, 'rU') as csvfile: + line = csvfile.readline() + if ";" in line: + separator = ';' + with open(self._file.value, 'rU') as csvfile: + csvfile = csv.reader(csvfile, delimiter=separator) + self._timeline._time.import_csv(csvfile) + + elif self._filetype.value == 1: + self._timeline._time.importchart_csv(self._graphCsvParserDlg) + self._timeline.show_graphs_properties() + + elif self._filetype.value == 2: + self.__import_bonsai_events() + elif self._filetype.value == 3: + self.__import_bonsai_events_oldformat() + + self._timeline.repaint() + self._timeline._time.repaint() + self.close() # pylint: disable=no-member + + + def import_chart(self, filename, frame_col=0, val_col=1): + self._filetype.value = 1 + self._graphCsvParserDlg.filename = filename + self._graphCsvParserDlg.frameColumn = frame_col + self._graphCsvParserDlg.xColumn = val_col + + + + def __import_bonsai_events(self): + + with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: + values = [] + pointEventValues = [] + csvfile = csv.reader(csvfile, delimiter=' ') + for row in csvfile: # strip Start/End word from all events names which are not PointEven + + try: + timestr = row[1].rstrip('0') + cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S.%f") + except: + timestr = row[1] + try: + print(timestr) + cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S") + except: + timestr = timestr.replace('T', ' ') + print(timestr) + cvttime = dateutil.parser.parse(timestr) + + seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() + frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) + + if row[2] == "PointEvent": + eventtype = row[0] + pointEventValues.append([eventtype, frame, row[2]]) + else: + if row[0].startswith('Start'): + eventtype = row[0][len('Start'):] # strip Start word from the beginning + else: + eventtype = row[0][len('End'):] # strip End word from the beginning + values.append([eventtype, frame, row[2]]) + + values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) + pointEventValues = sorted(pointEventValues, key=lambda x: (x[0].capitalize(), x[1])) + ntracks = len(set([x[0] for x in values])) + 1 + + # collapse + events = [] + eventsTypes = {} # Events names + currentTrack = 0 + for index in range(0, len(pointEventValues)): + pointEventValue = pointEventValues[index] + eventsTypes[pointEventValue[0]] = currentTrack + self._timeline.add_period([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], row=currentTrack) + + currentTrack = 1 + + for index in range(0, len(values), 2): + row0 = values[index] + row1 = values[index + 1] + + if row0[0] not in eventsTypes: + eventsTypes[row0[0]] = currentTrack + track = currentTrack + currentTrack += 1 + else: + track = eventsTypes[row0[0]] + + self._timeline.add_period([row0[1], row1[1], row0[0]], row=track) + + + + + def __import_bonsai_events_oldformat(self): + + with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: + windows_events = [] + points_events = [] + first_date = None + + for row in csvfile: + row = row[:-1] #remove the newline character + + if row.endswith('WindowClosing'): + split = row.rfind(' ') + #eventtype = row[-split:] + eventtype = 'end' + timestr = row[split-33:split] + eventname = row[4:split-33] + elif row.endswith('PointEvent'): + split = row.rfind(' ') + eventtype = row[split+1:] + timestr = row[split-33:split] + eventname = row[:split-33] + else: + eventtype = 'start' + timestr = row[-33:] + eventname = row[6:-33] + + cvttime = dateutil.parser.parse(timestr.replace('T', ' ')) + cvttime = cvttime.replace(tzinfo=None) + if first_date is None: first_date = cvttime + + seconds = (cvttime - first_date).total_seconds() + frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) + + if eventtype=='PointEvent': + points_events.append([eventtype, frame, eventname]) + else: + if eventtype=='start': + windows_events.append( [eventtype, frame, eventname] ) + elif eventtype=='end': + windows_events.append( [eventtype, frame, eventname] ) + + windows_events = sorted(windows_events, key=lambda x: (x[0][0].capitalize(), x[0][1])) + points_events = sorted(points_events, key=lambda x: (x[0].capitalize(), x[1])) + ntracks = len(set([x[0][1] for x in windows_events])) + 1 + + # collapse + events = [] + events_types = {} # Events names + current_track = 0 + for index in range(0, len(points_events)): + eventtype, frame, eventname = points_events[index] + events_types[eventname] = current_track + self._timeline.add_period([frame, frame+2, eventname], row=current_track) + + current_track = 1 + + for i in range(0, len(windows_events), 2): + start = windows_events[i] + end = windows_events[i+1] + eventtype, frame_begin, eventname = start + _, frame_end, _ = end + + if eventname not in events_types: + events_types[eventname] = current_track + track = current_track + current_track += 1 + else: + track = events_types[eventname] + + self._timeline.add_period([frame_begin, frame_end, eventname], row=track) \ No newline at end of file diff --git a/pyforms/gui/controls/control_player/ControlPlayer.py b/pyforms/gui/controls/control_player/ControlPlayer.py index f58ffe0..8833337 100755 --- a/pyforms/gui/controls/control_player/ControlPlayer.py +++ b/pyforms/gui/controls/control_player/ControlPlayer.py @@ -24,12 +24,12 @@ if _api.USED_API == _api.QT_API_PYQT5: import platform if platform.system() == 'Darwin': - from pyforms.gui.controls.ControlPlayer.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + from pyforms.gui.controls.control_player.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget else: - from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget elif _api.USED_API == _api.QT_API_PYQT4: - from pyforms.gui.controls.ControlPlayer.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget diff --git a/pyforms/gui/controls/control_player/VideoGLWidget.py b/pyforms/gui/controls/control_player/VideoGLWidget.py index 9a3c22c..1cae8fa 100644 --- a/pyforms/gui/controls/control_player/VideoGLWidget.py +++ b/pyforms/gui/controls/control_player/VideoGLWidget.py @@ -5,7 +5,7 @@ """ -from pyforms.gui.controls.ControlPlayer.AbstractGLWidget import AbstractGLWidget +from pyforms.gui.controls.control_player.AbstractGLWidget import AbstractGLWidget from AnyQt.QtOpenGL import QGLWidget class VideoGLWidget(AbstractGLWidget, QGLWidget): pass \ No newline at end of file diff --git a/pyforms/gui/controls/control_player/VideoQt5GLWidget.py b/pyforms/gui/controls/control_player/VideoQt5GLWidget.py index c475272..0d16072 100644 --- a/pyforms/gui/controls/control_player/VideoQt5GLWidget.py +++ b/pyforms/gui/controls/control_player/VideoQt5GLWidget.py @@ -1,4 +1,4 @@ -from pyforms.gui.controls.ControlPlayer.AbstractGLWidget import AbstractGLWidget +from pyforms.gui.controls.control_player.AbstractGLWidget import AbstractGLWidget import math from AnyQt import QtGui diff --git a/setup.py b/setup.py index 1f7cec3..7fd72f1 100644 --- a/setup.py +++ b/setup.py @@ -26,6 +26,6 @@ package_data={'pyforms': [ 'gui/controls/uipics/*.png', 'gui/mainWindow.ui', 'gui/controls/*.ui', 'gui/controls/control_player/*.ui', - 'gui/controls/control_events_timeline/*.ui'] + 'gui/controls/control_event_timeline/*.ui'] }, ) From 2435fccc9f673c2e4d088c1cf5dfbad067296e65 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 1 Feb 2018 11:43:30 +0000 Subject: [PATCH 35/66] Catch the exceptions when importing a Bonsai old events formats --- .../control_event_timeline/import_window.py | 140 +++++++++--------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/pyforms/gui/controls/control_event_timeline/import_window.py b/pyforms/gui/controls/control_event_timeline/import_window.py index 85d8c4a..3c0f1bf 100644 --- a/pyforms/gui/controls/control_event_timeline/import_window.py +++ b/pyforms/gui/controls/control_event_timeline/import_window.py @@ -12,6 +12,10 @@ import datetime import dateutil.parser +import logging + +logger=logging.getLogger(__file__) + class BonsaiImportFileDlg(BaseWidget): def __init__(self, timeline=None): @@ -183,71 +187,75 @@ def __import_bonsai_events(self): def __import_bonsai_events_oldformat(self): - with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: - windows_events = [] - points_events = [] - first_date = None - - for row in csvfile: - row = row[:-1] #remove the newline character - - if row.endswith('WindowClosing'): - split = row.rfind(' ') - #eventtype = row[-split:] - eventtype = 'end' - timestr = row[split-33:split] - eventname = row[4:split-33] - elif row.endswith('PointEvent'): - split = row.rfind(' ') - eventtype = row[split+1:] - timestr = row[split-33:split] - eventname = row[:split-33] - else: - eventtype = 'start' - timestr = row[-33:] - eventname = row[6:-33] - - cvttime = dateutil.parser.parse(timestr.replace('T', ' ')) - cvttime = cvttime.replace(tzinfo=None) - if first_date is None: first_date = cvttime - - seconds = (cvttime - first_date).total_seconds() - frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) - - if eventtype=='PointEvent': - points_events.append([eventtype, frame, eventname]) - else: - if eventtype=='start': - windows_events.append( [eventtype, frame, eventname] ) - elif eventtype=='end': - windows_events.append( [eventtype, frame, eventname] ) - - windows_events = sorted(windows_events, key=lambda x: (x[0][0].capitalize(), x[0][1])) - points_events = sorted(points_events, key=lambda x: (x[0].capitalize(), x[1])) - ntracks = len(set([x[0][1] for x in windows_events])) + 1 - - # collapse - events = [] - events_types = {} # Events names - current_track = 0 - for index in range(0, len(points_events)): - eventtype, frame, eventname = points_events[index] - events_types[eventname] = current_track - self._timeline.add_period([frame, frame+2, eventname], row=current_track) - - current_track = 1 - - for i in range(0, len(windows_events), 2): - start = windows_events[i] - end = windows_events[i+1] - eventtype, frame_begin, eventname = start - _, frame_end, _ = end - - if eventname not in events_types: + try: + with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: + windows_events = [] + points_events = [] + first_date = None + + for row in csvfile: + row = row[:-1] #remove the newline character + + if row.endswith('WindowClosing'): + split = row.rfind(' ') + #eventtype = row[-split:] + eventtype = 'end' + timestr = row[split-33:split] + eventname = row[4:split-33] + elif row.endswith('PointEvent'): + split = row.rfind(' ') + eventtype = row[split+1:] + timestr = row[split-33:split] + eventname = row[:split-33] + else: + eventtype = 'start' + timestr = row[-33:] + eventname = row[6:-33] + + cvttime = dateutil.parser.parse(timestr.replace('T', ' ')) + cvttime = cvttime.replace(tzinfo=None) + if first_date is None: first_date = cvttime + + seconds = (cvttime - first_date).total_seconds() + frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) + + if eventtype=='PointEvent': + points_events.append([eventtype, frame, eventname]) + else: + if eventtype=='start': + windows_events.append( [eventtype, frame, eventname] ) + elif eventtype=='end': + windows_events.append( [eventtype, frame, eventname] ) + + windows_events = sorted(windows_events, key=lambda x: (x[0][0].capitalize(), x[0][1])) + points_events = sorted(points_events, key=lambda x: (x[0].capitalize(), x[1])) + ntracks = len(set([x[0][1] for x in windows_events])) + 1 + + # collapse + events = [] + events_types = {} # Events names + current_track = 0 + for index in range(0, len(points_events)): + eventtype, frame, eventname = points_events[index] events_types[eventname] = current_track - track = current_track - current_track += 1 - else: - track = events_types[eventname] + self._timeline.add_period([frame, frame+2, eventname], row=current_track) + + current_track = 1 + + for i in range(0, len(windows_events), 2): + start = windows_events[i] + end = windows_events[i+1] + eventtype, frame_begin, eventname = start + _, frame_end, _ = end + + if eventname not in events_types: + events_types[eventname] = current_track + track = current_track + current_track += 1 + else: + track = events_types[eventname] - self._timeline.add_period([frame_begin, frame_end, eventname], row=track) \ No newline at end of file + self._timeline.add_period([frame_begin, frame_end, eventname], row=track) + except Exception as e: + self.warning("An error occurred when trying to import the file. Please check the logs.") + logger.error(e, exc_info=True) \ No newline at end of file From 2d4a661ef404e06d62d81e38f7a9458b20885d00 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Mon, 5 Feb 2018 13:14:48 +0000 Subject: [PATCH 36/66] Fix issues with the new pyforms version --- README.md | 4 +- pyforms/gui/basewidget.py | 14 +- pyforms/gui/controls/ControlFile.py | 2 +- pyforms/gui/controls/ControlList.py | 3 + pyforms/gui/controls/ControlOpenGL.py | 459 +++++++++--------- .../ControlEventTimeline.py | 2 +- .../ControlEventsGraph.py | 2 +- pyforms/terminal/controls/ControlPlayer.py | 2 +- .../ComputerVisionAlgorithmExample/Example.py | 4 +- .../3.CodeOrganization/AddMenuFuntionality.py | 4 +- 10 files changed, 255 insertions(+), 241 deletions(-) diff --git a/README.md b/README.md index 53a74ef..e71f747 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ class ComputerVisionAlgorithm(BaseWidget): #Define the event that will be called when the run button is processed self._runbutton.value = self.__runEvent #Define the event called before showing the image in the player - self._player.processFrame = self.__processFrame + self._player.process_frame_event = self.__process_frame #Define the organization of the Form Controls self._formset = [ @@ -99,7 +99,7 @@ class ComputerVisionAlgorithm(BaseWidget): """ self._player.value = self._videofile.value - def __processFrame(self, frame): + def __process_frame(self, frame): """ Do some processing to the frame and return the result frame """ diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index acd2b4e..9984f8e 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -29,8 +29,10 @@ class BaseWidget(QFrame): def __init__(self, *args, **kwargs): title = kwargs.get('title', args[0] if len(args)>0 else '') - parent_win = kwargs.get('parent_win', None) - win_flag = kwargs.get('win_flag', None) + parent_win = kwargs.get('parent_win', kwargs.get('parent_widget', None)) + win_flag = kwargs.get('win_flag', None) + + self._parent_widget = parent_win if parent_win is not None and win_flag is None: win_flag = QtCore.Qt.Dialog @@ -340,7 +342,7 @@ def save_window(self): data = {} self.save_form(data) - filename = QFileDialog.getSaveFileName(self, 'Select file') + filename, _ = QFileDialog.getSaveFileName(self, 'Select file') with open(filename, 'w') as output_file: json.dump(data, output_file) def load_form_filename(self, filename): @@ -350,7 +352,7 @@ def load_form_filename(self, filename): self.load_form(data) def load_window(self): - filename = QFileDialog.getOpenFileNames(self, 'Select file') + filename, _ = QFileDialog.getOpenFileNames(self, 'Select file') self.load_form_filename(str(filename[0])) def close(self): @@ -462,7 +464,9 @@ def controls(self): def form_has_loaded(self): return self._formLoaded - + @property + def parent_widget(self): + return self._parent_widget @property def form(self): diff --git a/pyforms/gui/controls/ControlFile.py b/pyforms/gui/controls/ControlFile.py index ff064d2..174face 100644 --- a/pyforms/gui/controls/ControlFile.py +++ b/pyforms/gui/controls/ControlFile.py @@ -33,7 +33,7 @@ def finishEditing(self): def click(self): if self.use_save_dialog: - value = QFileDialog.getSaveFileName(self.parent, self._label, self.value) + value, _ = QFileDialog.getSaveFileName(self.parent, self._label, self.value) else: value = QFileDialog.getOpenFileName(self.parent, self._label, self.value) diff --git a/pyforms/gui/controls/ControlList.py b/pyforms/gui/controls/ControlList.py index 02b73f8..bfbb3b2 100644 --- a/pyforms/gui/controls/ControlList.py +++ b/pyforms/gui/controls/ControlList.py @@ -62,6 +62,9 @@ def init_form(self): self.tableWidget.cellDoubleClicked.connect(self.tableWidgetCellDoubleClicked) self.tableWidget.model().dataChanged.connect(self._dataChangedEvent) + + self.tableWidget.horizontalHeader().setVisible(False) + if plusFunction is None and minusFunction is None: self.bottomBar.hide() elif plusFunction is None: diff --git a/pyforms/gui/controls/ControlOpenGL.py b/pyforms/gui/controls/ControlOpenGL.py index 15b0319..99ce076 100644 --- a/pyforms/gui/controls/ControlOpenGL.py +++ b/pyforms/gui/controls/ControlOpenGL.py @@ -15,249 +15,256 @@ from OpenGL.GL import * from OpenGL.GLU import * - + from AnyQt import _api if _api.USED_API == _api.QT_API_PYQT5: - try: - from AnyQt.QtOpenGL import QGLWidget - except: - logger.debug("No OpenGL library available") + try: + from AnyQt.QtOpenGL import QGLWidget + except: + logger.debug("No OpenGL library available") - import platform - if platform.system() == 'Darwin': - from pyforms.gui.controls.control_player.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget - else: - from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget + import platform + if platform.system() == 'Darwin': + from pyforms.gui.controls.control_player.VideoQt5GLWidget import VideoQt5GLWidget as VideoGLWidget + else: + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget elif _api.USED_API == _api.QT_API_PYQT4: - try: - from PyQt4.QtOpenGL import QGLWidget - except: - logger.debug("No OpenGL library available") + try: + from PyQt4.QtOpenGL import QGLWidget + except: + logger.debug("No OpenGL library available") - from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget + from pyforms.gui.controls.control_player.VideoGLWidget import VideoGLWidget class OpenglGLWidget(QGLWidget): - def __init__(self, parent=None): - QGLWidget.__init__(self, parent) - - self._zoom = 1.0 - self._scene = None - self._rotation = [0, 0, 0] - - self._mouseLeftDown = False - self._mouseRightDown = False - - self._mouseGLPosition = [0, 0, 0] - self._lastMouseGLPosition = [0, 0, 0] - - self._mousePosition = [0, 0] # Current mouse position - self._lastMousePosition = [0, 0] # Last mouse position - - self._mouseStartDragPoint = None - self._clear_color = None - - self.setMinimumHeight(100) - self.setMinimumWidth(100) - self.setMouseTracking(True) - self.setAcceptDrops(True) - - self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding); - - def initializeGL(self): - glClearDepth(1.0) - if self._clear_color: glClearColor(*self._clear_color) - glEnable(GL_BLEND) - glBlendFunc(GL_SRC_ALPHA, GL_ONE) - - glEnable(GL_POINT_SMOOTH); - glEnable(GL_LINE_SMOOTH); - glEnable(GL_POLYGON_SMOOTH); - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); - - def resizeGL(self, width, height): - """ - - :param width: - :param height: - :return: - """ - glViewport(0, 0, width, height) - glMatrixMode(GL_PROJECTION) - glLoadIdentity() - gluPerspective(65.0, float(width) / float(height), 0.01, 800.0) - - def paintGL(self): - """ - - """ - if self._clear_color: - glBlendFunc(GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE_MINUS_SRC_ALPHA) - glClearColor(*self._clear_color) - else: - glBlendFunc(GL_SRC_ALPHA, GL_ONE) - glClearColor(0, 0, 0, 1) - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) - glMatrixMode(GL_MODELVIEW) - glLoadIdentity() - - glEnable(GL_BLEND) - - glScalef(1, -1, -1) - - glTranslatef(0, 0, self._zoom) - glRotatef(self._rotation[0], 1, 0, 0) - glRotatef(self._rotation[1], 0, 1, 0) - glRotatef(self._rotation[2], 0, 0, 1) - - if self._scene != None: self._scene.DrawGLScene() - - if self.mouseDown: - # Get mouse position - modelview, projection = glGetDoublev(GL_MODELVIEW_MATRIX), glGetDoublev(GL_PROJECTION_MATRIX) - viewport = glGetIntegerv(GL_VIEWPORT) - winX, winY = float(self._mousePosition[0]), float(viewport[3] - self._mousePosition[1]) - winZ = glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT) - self._mouseGLPosition = gluUnProject(winX, winY, winZ[0][0], modelview, projection, viewport) - - glDisable(GL_BLEND) - - def __updateMouse(self, event, pressed=None): - self._mousePosition[0] = event.x() - self._mousePosition[1] = event.y() - - if pressed != None: - if event.button() == 2: self._mouseRightDown = pressed - if event.button() == 1: self._mouseLeftDown = pressed - - def wheelEvent(self, event): - """ - - :param event: - """ - if event.delta() < 0: - self._zoom += 1 - else: - self._zoom -= 1 - - self.repaint() - - def mouseReleaseEvent(self, event): - """ - - :param event: - """ - self.__updateMouse(event) - - if self._mouseRightDown: - self._lastMouseGLPosition = self._mouseGLPosition - self._mouseRightDown = False - - if self._mouseLeftDown: - self.onEndDrag(self._mouseStartDragPoint, self._mouseGLPosition) - self._mouseLeftDown = False - - def mousePressEvent(self, event): - """ - - :param event: - """ - QGLWidget.mousePressEvent(self, event) - self.__updateMouse(event, pressed=True) - self.repaint() - - if self._mouseLeftDown: self._mouseStartDragPoint = self._mouseGLPosition - if self._mouseRightDown: self._lastMouseGLPosition = self._mouseGLPosition - - self.onPress(event.button(), self._mousePosition, self._mouseGLPosition) - - def mouseMoveEvent(self, event): - """ - - :param event: - """ - QGLWidget.mouseMoveEvent(self, event) - self.__updateMouse(event) - self.repaint() - - self.onMove((self._mouseGLPosition[0], self._mouseGLPosition[1])) - - if self.mouseDown: - if self._mouseLeftDown: - # p = self._mouseGLPosition[0] - self._x, self._mouseGLPosition[1] + self._y - # p = self._mouseGLPosition[0], self._mouseGLPosition[1] - self.onDrag(self._lastMousePosition, self._mousePosition) - - self._lastMousePosition = list(self._mousePosition) - - def onMove(self, point): - pass - - def onPress(self, button, point, glpoint=None): - pass - - def onDrag(self, startPoint, endPoint, startGLPoint=None, endGLPoint=None): - """ - - :param startPoint: - :param endPoint: - :param startGLPoint: - :param endGLPoint: - """ - movX, movY = endPoint[0] - startPoint[0], endPoint[1] - startPoint[1] - self._rotation[2] -= float(movX) * 0.15 - self._rotation[0] += float(movY) * 0.15 - - def onEndDrag(self, startPoint, endPoint, startGLPoint=None, endGLPoint=None): - pass - - ############################################################################## - ###### Properties ############################################################ - ############################################################################## - - @property - def scene(self): - return self._scene - - @scene.setter - def scene(self, value): - self._scene = value - - @property - def mouseDown(self): - return self._mouseLeftDown or self._mouseRightDown - - def resetZoomAndRotation(self): - self._zoom, self._rotation = 0.0, [0, 0, 0] + def __init__(self, parent=None): + QGLWidget.__init__(self, parent) + + self._zoom = 1.0 + self._scene = None + self._rotation = [0, 0, 0] + + self._mouseLeftDown = False + self._mouseRightDown = False + + self._mouseGLPosition = [0, 0, 0] + self._lastMouseGLPosition = [0, 0, 0] + + self._mousePosition = [0, 0] # Current mouse position + self._lastMousePosition = [0, 0] # Last mouse position + + self._mouseStartDragPoint = None + self._clear_color = None + + self.setMinimumHeight(100) + self.setMinimumWidth(100) + self.setMouseTracking(True) + self.setAcceptDrops(True) + + self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding); + + def initializeGL(self): + glClearDepth(1.0) + if self._clear_color: glClearColor(*self._clear_color) + glEnable(GL_BLEND) + glBlendFunc(GL_SRC_ALPHA, GL_ONE) + + glEnable(GL_POINT_SMOOTH); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + def resizeGL(self, width, height): + """ + + :param width: + :param height: + :return: + """ + glViewport(0, 0, width, height) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + gluPerspective(65.0, float(width) / float(height), 0.01, 800.0) + + def paintGL(self): + """ + + """ + if self._clear_color: + glBlendFunc(GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + glClearColor(*self._clear_color) + else: + glBlendFunc(GL_SRC_ALPHA, GL_ONE) + glClearColor(0, 0, 0, 1) + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + + glEnable(GL_BLEND) + + glScalef(1, -1, -1) + + glTranslatef(0, 0, self._zoom) + glRotatef(self._rotation[0], 1, 0, 0) + glRotatef(self._rotation[1], 0, 1, 0) + glRotatef(self._rotation[2], 0, 0, 1) + + if self._scene != None: self._scene.DrawGLScene() + + if self.mouseDown: + # Get mouse position + modelview, projection = glGetDoublev(GL_MODELVIEW_MATRIX), glGetDoublev(GL_PROJECTION_MATRIX) + viewport = glGetIntegerv(GL_VIEWPORT) + winX, winY = float(self._mousePosition[0]), float(viewport[3] - self._mousePosition[1]) + winZ = glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT) + self._mouseGLPosition = gluUnProject(winX, winY, winZ[0][0], modelview, projection, viewport) + + glDisable(GL_BLEND) + + def __updateMouse(self, event, pressed=None): + self._mousePosition[0] = event.x() + self._mousePosition[1] = event.y() + + if pressed != None: + if event.button() == 2: self._mouseRightDown = pressed + if event.button() == 1: self._mouseLeftDown = pressed + + def wheelEvent(self, event): + """ + + :param event: + """ + if _api.USED_API == _api.QT_API_PYQT5: + p = event.angleDelta() + delta = p.y() + elif _api.USED_API == _api.QT_API_PYQT4: + delta = event.delta() + + + if delta < 0: + self._zoom += 1 + else: + self._zoom -= 1 + + self.repaint() + + def mouseReleaseEvent(self, event): + """ + + :param event: + """ + self.__updateMouse(event) + + if self._mouseRightDown: + self._lastMouseGLPosition = self._mouseGLPosition + self._mouseRightDown = False + + if self._mouseLeftDown: + self.onEndDrag(self._mouseStartDragPoint, self._mouseGLPosition) + self._mouseLeftDown = False + + def mousePressEvent(self, event): + """ + + :param event: + """ + QGLWidget.mousePressEvent(self, event) + self.__updateMouse(event, pressed=True) + self.repaint() + + if self._mouseLeftDown: self._mouseStartDragPoint = self._mouseGLPosition + if self._mouseRightDown: self._lastMouseGLPosition = self._mouseGLPosition + + self.onPress(event.button(), self._mousePosition, self._mouseGLPosition) + + def mouseMoveEvent(self, event): + """ + + :param event: + """ + QGLWidget.mouseMoveEvent(self, event) + self.__updateMouse(event) + self.repaint() + + self.onMove((self._mouseGLPosition[0], self._mouseGLPosition[1])) + + if self.mouseDown: + if self._mouseLeftDown: + # p = self._mouseGLPosition[0] - self._x, self._mouseGLPosition[1] + self._y + # p = self._mouseGLPosition[0], self._mouseGLPosition[1] + self.onDrag(self._lastMousePosition, self._mousePosition) + + self._lastMousePosition = list(self._mousePosition) + + def onMove(self, point): + pass + + def onPress(self, button, point, glpoint=None): + pass + + def onDrag(self, startPoint, endPoint, startGLPoint=None, endGLPoint=None): + """ + + :param startPoint: + :param endPoint: + :param startGLPoint: + :param endGLPoint: + """ + movX, movY = endPoint[0] - startPoint[0], endPoint[1] - startPoint[1] + self._rotation[2] -= float(movX) * 0.15 + self._rotation[0] += float(movY) * 0.15 + + def onEndDrag(self, startPoint, endPoint, startGLPoint=None, endGLPoint=None): + pass + + ############################################################################## + ###### Properties ############################################################ + ############################################################################## + + @property + def scene(self): + return self._scene + + @scene.setter + def scene(self, value): + self._scene = value + + @property + def mouseDown(self): + return self._mouseLeftDown or self._mouseRightDown + + def resetZoomAndRotation(self): + self._zoom, self._rotation = 0.0, [0, 0, 0] class ControlOpenGL(ControlBase): - def init_form(self): self._form = OpenglGLWidget() + def init_form(self): self._form = OpenglGLWidget() - def repaint(self): self._form.repaint() + def repaint(self): self._form.repaint() - def reset_zoom_and_rotation(self): self._form.resetZoomAndRotation() + def reset_zoom_and_rotation(self): self._form.resetZoomAndRotation() - @property - def value(self): return self._form.scene + @property + def value(self): return self._form.scene - @value.setter - def value(self, value): self._form.scene = value; self._form.repaint() + @value.setter + def value(self, value): self._form.scene = value; self._form.repaint() - @property - def clear_color(self): self._form._clear_color + @property + def clear_color(self): self._form._clear_color - @clear_color.setter - def clear_color(self, value): - self._form._clear_color = value; - self._form.repaint() + @clear_color.setter + def clear_color(self, value): + self._form._clear_color = value; + self._form.repaint() - @property - def width(self): return self._form.width() + @property + def width(self): return self._form.width() - @property - def height(self): return self._form.height() + @property + def height(self): return self._form.height() diff --git a/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py b/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py index b5e02a7..c8e9ff9 100644 --- a/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py +++ b/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py @@ -439,7 +439,7 @@ def __export_2_csv_matrix(self): QMessageBox.warning( self, "Important!", 'Please note that this file cannot be imported after.') - filename = QFileDialog.getSaveFileName(parent=self, + filename, _ = QFileDialog.getSaveFileName(parent=self, caption="Export matrix file", directory="untitled.csv", filter="CSV Files (*.csv)", diff --git a/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py b/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py index e6440dd..7a686d3 100644 --- a/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py +++ b/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py @@ -86,7 +86,7 @@ def get_export_filename(self): return "untitled.csv" def __export(self): """Export annotations to a file.""" - filename = QFileDialog.getSaveFileName(parent=self, + filename, _ = QFileDialog.getSaveFileName(parent=self, caption="Export annotations file", directory=self.get_export_filename(), filter="CSV Files (*.csv)", diff --git a/pyforms/terminal/controls/ControlPlayer.py b/pyforms/terminal/controls/ControlPlayer.py index 9291012..37eb365 100644 --- a/pyforms/terminal/controls/ControlPlayer.py +++ b/pyforms/terminal/controls/ControlPlayer.py @@ -69,7 +69,7 @@ def value(self): _, image = capture.read() if isinstance(image, numpy.ndarray): - image = self.processFrame(image) + image = self.process_frame_event(image) if isinstance(image, list) or isinstance(image, tuple): image = groupImage(image, True) diff --git a/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py b/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py index af913da..ba5265e 100644 --- a/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py +++ b/tutorials/1.SimpleExamples/ComputerVisionAlgorithmExample/Example.py @@ -30,7 +30,7 @@ def __init__(self): #Define the event that will be called when the run button is processed self._runbutton.value = self.__runEvent #Define the event called before showing the image in the player - self._player.processFrame = self.__processFrame + self._player.process_frame_event = self.__process_frame #Define the organization of the Form Controls self.formset = [ @@ -47,7 +47,7 @@ def __videoFileSelectionEvent(self): """ self._player.value = self._videofile.value - def __processFrame(self, frame): + def __process_frame(self, frame): """ Do some processing to the frame and return the result frame """ diff --git a/tutorials/3.CodeOrganization/AddMenuFuntionality.py b/tutorials/3.CodeOrganization/AddMenuFuntionality.py index d83b09e..9a6c595 100644 --- a/tutorials/3.CodeOrganization/AddMenuFuntionality.py +++ b/tutorials/3.CodeOrganization/AddMenuFuntionality.py @@ -23,7 +23,7 @@ def __init__(self): def __savePeople(self): - filename = QtGui.QFileDialog.getSaveFileName(parent=self, + filename, _ = QtGui.QFileDialog.getSaveFileName(parent=self, caption="Save file", directory=".", filter="*.dat") @@ -31,7 +31,7 @@ def __savePeople(self): if filename!=None and filename!='': self.save(filename) def __loadPeople(self): - filename = QtGui.QFileDialog.getOpenFileName(parent=self, + filename, _ = QtGui.QFileDialog.getOpenFileName(parent=self, caption="Import file", directory=".", filter="*.dat") From 92b6d8d6f860f17531940e6b876337eabdfa819f Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 9 Feb 2018 19:38:56 +0000 Subject: [PATCH 37/66] Fix imports on terminal mode --- pyforms/controls.py | 1 + pyforms/terminal/basewidget.py | 2 ++ .../controls/ControlBoundingSlider.py | 2 +- pyforms/terminal/controls/ControlButton.py | 2 +- pyforms/terminal/controls/ControlCheckBox.py | 2 +- .../terminal/controls/ControlCheckBoxList.py | 2 +- pyforms/terminal/controls/ControlCombo.py | 2 +- pyforms/terminal/controls/ControlDir.py | 2 +- .../terminal/controls/ControlEmptyWidget.py | 2 +- pyforms/terminal/controls/ControlFile.py | 2 +- pyforms/terminal/controls/ControlImage.py | 2 +- pyforms/terminal/controls/ControlLabel.py | 2 +- pyforms/terminal/controls/ControlList.py | 2 +- pyforms/terminal/controls/ControlNumber.py | 2 +- pyforms/terminal/controls/ControlPlayer.py | 36 +++++++++++++++---- pyforms/terminal/controls/ControlProgress.py | 6 ++-- pyforms/terminal/controls/ControlSlider.py | 2 +- pyforms/terminal/controls/ControlText.py | 2 +- pyforms/terminal/controls/ControlTextArea.py | 2 +- pyforms/terminal/controls/ControlToolBox.py | 2 +- pyforms/terminal/controls/ControlTree.py | 2 +- 21 files changed, 52 insertions(+), 27 deletions(-) diff --git a/pyforms/controls.py b/pyforms/controls.py index 18ed926..f883614 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -70,6 +70,7 @@ elif conf.PYFORMS_MODE=='TERMINAL': from pyforms.terminal.controls.ControlBase import ControlBase + from pyforms.terminal.controls.ControlBoundingSlider import ControlBoundingSlider from pyforms.terminal.controls.ControlText import ControlText from pyforms.terminal.controls.ControlButton import ControlButton from pyforms.terminal.controls.ControlCheckBox import ControlCheckBox diff --git a/pyforms/terminal/basewidget.py b/pyforms/terminal/basewidget.py index 512f764..b8f2774 100644 --- a/pyforms/terminal/basewidget.py +++ b/pyforms/terminal/basewidget.py @@ -23,6 +23,8 @@ def __init__(self, *args, **kwargs): ############ Module functions ############################################# ############################################################################ + def set_margin(self, margin):pass + def init_form(self, parse=True): result = {} for fieldname, var in self.controls.items(): diff --git a/pyforms/terminal/controls/ControlBoundingSlider.py b/pyforms/terminal/controls/ControlBoundingSlider.py index 1eb7a97..4b8e0b2 100644 --- a/pyforms/terminal/controls/ControlBoundingSlider.py +++ b/pyforms/terminal/controls/ControlBoundingSlider.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlBoundingSlider(ControlBase):pass diff --git a/pyforms/terminal/controls/ControlButton.py b/pyforms/terminal/controls/ControlButton.py index 3349535..01d0130 100644 --- a/pyforms/terminal/controls/ControlButton.py +++ b/pyforms/terminal/controls/ControlButton.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlButton(ControlBase): diff --git a/pyforms/terminal/controls/ControlCheckBox.py b/pyforms/terminal/controls/ControlCheckBox.py index 2c7540d..1e8ada4 100644 --- a/pyforms/terminal/controls/ControlCheckBox.py +++ b/pyforms/terminal/controls/ControlCheckBox.py @@ -1,5 +1,5 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlCheckBox(ControlBase): diff --git a/pyforms/terminal/controls/ControlCheckBoxList.py b/pyforms/terminal/controls/ControlCheckBoxList.py index 4b66268..e26fd80 100644 --- a/pyforms/terminal/controls/ControlCheckBoxList.py +++ b/pyforms/terminal/controls/ControlCheckBoxList.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlCheckBoxList(ControlBase): diff --git a/pyforms/terminal/controls/ControlCombo.py b/pyforms/terminal/controls/ControlCombo.py index 32a81ff..7317b80 100644 --- a/pyforms/terminal/controls/ControlCombo.py +++ b/pyforms/terminal/controls/ControlCombo.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlCombo(ControlBase): diff --git a/pyforms/terminal/controls/ControlDir.py b/pyforms/terminal/controls/ControlDir.py index 2b1f64e..7828cb9 100644 --- a/pyforms/terminal/controls/ControlDir.py +++ b/pyforms/terminal/controls/ControlDir.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlDir(ControlBase): diff --git a/pyforms/terminal/controls/ControlEmptyWidget.py b/pyforms/terminal/controls/ControlEmptyWidget.py index 8490a32..294d493 100644 --- a/pyforms/terminal/controls/ControlEmptyWidget.py +++ b/pyforms/terminal/controls/ControlEmptyWidget.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlEmptyWidget(ControlBase): diff --git a/pyforms/terminal/controls/ControlFile.py b/pyforms/terminal/controls/ControlFile.py index 4f8aa63..0da983e 100644 --- a/pyforms/terminal/controls/ControlFile.py +++ b/pyforms/terminal/controls/ControlFile.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlFile(ControlBase): diff --git a/pyforms/terminal/controls/ControlImage.py b/pyforms/terminal/controls/ControlImage.py index a189775..db4914f 100644 --- a/pyforms/terminal/controls/ControlImage.py +++ b/pyforms/terminal/controls/ControlImage.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlImage(ControlBase): diff --git a/pyforms/terminal/controls/ControlLabel.py b/pyforms/terminal/controls/ControlLabel.py index 36d42f0..61431a8 100644 --- a/pyforms/terminal/controls/ControlLabel.py +++ b/pyforms/terminal/controls/ControlLabel.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlLabel(ControlBase):pass diff --git a/pyforms/terminal/controls/ControlList.py b/pyforms/terminal/controls/ControlList.py index e3a46a8..fd7443e 100644 --- a/pyforms/terminal/controls/ControlList.py +++ b/pyforms/terminal/controls/ControlList.py @@ -6,7 +6,7 @@ """ import logging from pyforms.terminal.BaseWidget import BaseWidget -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase logger = logging.getLogger(__name__) diff --git a/pyforms/terminal/controls/ControlNumber.py b/pyforms/terminal/controls/ControlNumber.py index 8ea43b9..58c34ba 100644 --- a/pyforms/terminal/controls/ControlNumber.py +++ b/pyforms/terminal/controls/ControlNumber.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlNumber(ControlBase): diff --git a/pyforms/terminal/controls/ControlPlayer.py b/pyforms/terminal/controls/ControlPlayer.py index 37eb365..183eccd 100644 --- a/pyforms/terminal/controls/ControlPlayer.py +++ b/pyforms/terminal/controls/ControlPlayer.py @@ -1,12 +1,13 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase -import numpy +from pyforms.terminal.controls.ControlBase import ControlBase +from pyforms.utils.tools import groupImage +import numpy, types import numpy as np try: - from StringIO import StringIO + from StringIO import StringIO as BufferClass except ImportError: - from io import StringIO + from io import BytesIO as BufferClass try: @@ -77,7 +78,7 @@ def value(self): if len(image.shape)>2: image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB) image = Image.fromarray(image) - buff = StringIO.StringIO() + buff = BufferClass() image.save(buff, format="PNG") content = buff.getvalue() buff.close() @@ -96,7 +97,7 @@ def value(self, value): if 'position' in value.keys(): self.video_index = int(value['position']) self._filename = value['filename'] - if isinstance(value, cv2.VideoCapture): + if isinstance(value,types.BuiltinFunctionType): ControlBase.value.fset(self, value ) self._max = int(self._value.get(7)) @@ -120,5 +121,26 @@ def image(self): return self._currentFrame @image.setter def image(self, value): pass - + + + + + @property + def frame_width(self): return self._value.get(3) + + @property + def frame_height(self): return self._value.get(4) + + @property + def max(self): return int(self._value.get(7)) + + @property + def frame(self): return self._currentFrame + + @property + def fps(self): + """ + Return the video frames per second + """ + return self._value.get(5) diff --git a/pyforms/terminal/controls/ControlProgress.py b/pyforms/terminal/controls/ControlProgress.py index 9550f25..33299b8 100644 --- a/pyforms/terminal/controls/ControlProgress.py +++ b/pyforms/terminal/controls/ControlProgress.py @@ -1,15 +1,15 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlProgress(ControlBase): _min = 0 _max = 100 - def __init__(self, label = "%p%", defaultValue = 0, min = 0, max = 100, helptext=None): + def __init__(self, *args, **kwargs): self._updateSlider = True self._min = min self._max = max - ControlBase.__init__(self, label, defaultValue) + ControlBase.__init__(self, *args, **kwargs) @property diff --git a/pyforms/terminal/controls/ControlSlider.py b/pyforms/terminal/controls/ControlSlider.py index 007599d..ca5de38 100644 --- a/pyforms/terminal/controls/ControlSlider.py +++ b/pyforms/terminal/controls/ControlSlider.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlSlider(ControlBase): diff --git a/pyforms/terminal/controls/ControlText.py b/pyforms/terminal/controls/ControlText.py index 1e851cf..c3b76cb 100644 --- a/pyforms/terminal/controls/ControlText.py +++ b/pyforms/terminal/controls/ControlText.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlText(ControlBase):pass diff --git a/pyforms/terminal/controls/ControlTextArea.py b/pyforms/terminal/controls/ControlTextArea.py index 0a560e5..e1d5d3f 100644 --- a/pyforms/terminal/controls/ControlTextArea.py +++ b/pyforms/terminal/controls/ControlTextArea.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlTextArea(ControlBase):pass diff --git a/pyforms/terminal/controls/ControlToolBox.py b/pyforms/terminal/controls/ControlToolBox.py index 1171f71..412d2a6 100644 --- a/pyforms/terminal/controls/ControlToolBox.py +++ b/pyforms/terminal/controls/ControlToolBox.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlToolBox(ControlBase):pass diff --git a/pyforms/terminal/controls/ControlTree.py b/pyforms/terminal/controls/ControlTree.py index 0f298eb..a3d50d4 100644 --- a/pyforms/terminal/controls/ControlTree.py +++ b/pyforms/terminal/controls/ControlTree.py @@ -1,4 +1,4 @@ -from pyforms.terminal.Controls.ControlBase import ControlBase +from pyforms.terminal.controls.ControlBase import ControlBase class ControlTree(ControlBase):pass From 3dead276b50c0d7879f0358fb4983f249cdb08cd Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Mon, 12 Feb 2018 18:40:24 +0000 Subject: [PATCH 38/66] Fix terminal bounding slider --- pyforms/terminal/basewidget.py | 6 ++++-- .../controls/ControlBoundingSlider.py | 6 +++--- pyforms/terminal/controls/ControlProgress.py | 20 ++++++++++++------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/pyforms/terminal/basewidget.py b/pyforms/terminal/basewidget.py index b8f2774..86348f6 100644 --- a/pyforms/terminal/basewidget.py +++ b/pyforms/terminal/basewidget.py @@ -1,4 +1,4 @@ -from pyforms.controls import ControlFile, ControlSlider, ControlText, ControlCombo, ControlCheckBox, ControlBase, ControlDir, ControlNumber +from pyforms.controls import ControlFile, ControlSlider, ControlText, ControlCombo, ControlCheckBox, ControlBase, ControlDir, ControlNumber, ControlBoundingSlider from datetime import datetime, timedelta import argparse, uuid, os, shutil, time, sys, subprocess import simplejson as json @@ -31,7 +31,7 @@ def init_form(self, parse=True): name = var._name if isinstance(var, ( ControlFile, ControlSlider, ControlText, - ControlCombo,ControlCheckBox, ControlDir, ControlNumber + ControlCombo,ControlCheckBox, ControlDir, ControlNumber, ControlBoundingSlider ) ): self._parser.add_argument("--%s" % name, help=var.label) @@ -89,6 +89,8 @@ def __parse_terminal_parameters(self): var.value = self._args.__dict__[name]=='True' elif isinstance(var, (ControlSlider, ControlNumber) ): var.value = int(self._args.__dict__[name]) + elif isinstance(var, ControlBoundingSlider): + var.value = eval(self._args.__dict__[name]) if self._args.load: print('\n--------- LOADING CONFIG ------------------') diff --git a/pyforms/terminal/controls/ControlBoundingSlider.py b/pyforms/terminal/controls/ControlBoundingSlider.py index 4b8e0b2..f424808 100644 --- a/pyforms/terminal/controls/ControlBoundingSlider.py +++ b/pyforms/terminal/controls/ControlBoundingSlider.py @@ -1,5 +1,5 @@ from pyforms.terminal.controls.ControlBase import ControlBase -class ControlBoundingSlider(ControlBase):pass - - \ No newline at end of file +class ControlBoundingSlider(ControlBase): + + pass \ No newline at end of file diff --git a/pyforms/terminal/controls/ControlProgress.py b/pyforms/terminal/controls/ControlProgress.py index 33299b8..ca5094b 100644 --- a/pyforms/terminal/controls/ControlProgress.py +++ b/pyforms/terminal/controls/ControlProgress.py @@ -1,4 +1,5 @@ from pyforms.terminal.controls.ControlBase import ControlBase +from sys import stdout class ControlProgress(ControlBase): @@ -7,8 +8,8 @@ class ControlProgress(ControlBase): def __init__(self, *args, **kwargs): self._updateSlider = True - self._min = min - self._max = max + self._min = kwargs.get('min', kwargs.get('minimum', 0)) + self._max = kwargs.get('max', kwargs.get('maximum', 100)) ControlBase.__init__(self, *args, **kwargs) @@ -16,16 +17,21 @@ def __init__(self, *args, **kwargs): def value(self): return self._value @value.setter - def value(self, value):self._value = value + def value(self, value): + #diff = self._max-self._min + + if (value % 100 == 0): + stdout.write( '\rprogress {0}/{1}'.format(value-self._min, self._max) ) + self._value = value @property - def min(self): return + def min(self): return self._min @min.setter - def min(self, value): pass + def min(self, value): self._min = value @property - def max(self): return + def max(self): return self._max @max.setter - def max(self, value): pass \ No newline at end of file + def max(self, value): self._max = value \ No newline at end of file From 81cc638dc88f819bc671a4595fa467d24650b5ff Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 13 Feb 2018 11:54:25 +0000 Subject: [PATCH 39/66] Update controls to the new pyforms version --- .idea/pyforms.iml | 17 ----------- build_settings/win/build.bat | 31 --------------------- pyforms/controls.py | 2 +- pyforms/gui/controls/ControlOpenGL.py | 8 +++++- pyforms/gui/controls/ControlVisVis.py | 8 +++--- pyforms/gui/controls/ControlVisVisVolume.py | 5 ++-- pyforms/gui/dialogs/csv_parser.py | 20 ++++++------- 7 files changed, 24 insertions(+), 67 deletions(-) delete mode 100644 .idea/pyforms.iml delete mode 100755 build_settings/win/build.bat diff --git a/.idea/pyforms.iml b/.idea/pyforms.iml deleted file mode 100644 index 5554030..0000000 --- a/.idea/pyforms.iml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build_settings/win/build.bat b/build_settings/win/build.bat deleted file mode 100755 index 13a4b27..0000000 --- a/build_settings/win/build.bat +++ /dev/null @@ -1,31 +0,0 @@ -@echo off - -setlocal enableextensions enabledelayedexpansion - -rem set /A PYTHON_VERSION=2 - -IF /I "%PYTHON_VERSION%" EQU "2" ( - set "WINPYDIR=C:\Users\swp\Python\WinPython-32bit-2.7.10.3\python-2.7.10" - set "WINPYVER=2.7.10.3" -) ELSE ( - set "WINPYDIR=C:\WinPython\WinPython-64bit-3.5.3.0Qt5\python-3.5.3.amd64" - set "WINPYVER=3.5.3.0Qt5" -) - -set "HOME=%WINPYDIR%\..\settings" -set "WINPYARCH=WIN32" - -set "PATH=%WINPYDIR%\Lib\site-packages\PyQt4;%WINPYDIR%\;%WINPYDIR%\DLLs;%WINPYDIR%\Scripts;%WINPYDIR%\..\tools;" - -rem keep nbextensions in Winpython directory, rather then %APPDATA% default -set "JUPYTER_DATA_DIR=%WINPYDIR%\..\settings" - -set PROJECTNAME="pyforms" - -python --version - -pip uninstall -y %PROJECTNAME% -pip install . -pip show %PROJECTNAME% - -python setup.py sdist --formats=zip \ No newline at end of file diff --git a/pyforms/controls.py b/pyforms/controls.py index f883614..188110b 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -66,7 +66,7 @@ logger.warning("QScintilla2 not installed") logger.error(e, exc_info=True) - + elif conf.PYFORMS_MODE=='TERMINAL': from pyforms.terminal.controls.ControlBase import ControlBase diff --git a/pyforms/gui/controls/ControlOpenGL.py b/pyforms/gui/controls/ControlOpenGL.py index 99ce076..de5a180 100644 --- a/pyforms/gui/controls/ControlOpenGL.py +++ b/pyforms/gui/controls/ControlOpenGL.py @@ -85,10 +85,16 @@ def resizeGL(self, width, height): :param height: :return: """ + glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() - gluPerspective(65.0, float(width) / float(height), 0.01, 800.0) + + if height!=0: + ratio = float(width) / float(height) + else: + ratio = 1 + gluPerspective(65.0, ratio, 0.01, 800.0) def paintGL(self): """ diff --git a/pyforms/gui/controls/ControlVisVis.py b/pyforms/gui/controls/ControlVisVis.py index fd4060d..5efad6b 100644 --- a/pyforms/gui/controls/ControlVisVis.py +++ b/pyforms/gui/controls/ControlVisVis.py @@ -20,8 +20,8 @@ class ControlVisVis(ControlBase): def init_form(self): - self._form = QtGui.QWidget() - layout = QtGui.QVBoxLayout() + self._form = QWidget() + layout = QVBoxLayout() if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) @@ -29,13 +29,13 @@ def init_form(self): layout.setMargin(0) self._form.setLayout( layout ) - self._app = vv.use('pyqt4') + self._app = vv.use('pyqt5') self._app.Create() Figure = self._app.GetFigureClass() self._fig = Figure(self._form) - policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) widget = self._fig._widget widget.setSizePolicy(policy) diff --git a/pyforms/gui/controls/ControlVisVisVolume.py b/pyforms/gui/controls/ControlVisVisVolume.py index 3282e92..723fc35 100644 --- a/pyforms/gui/controls/ControlVisVisVolume.py +++ b/pyforms/gui/controls/ControlVisVisVolume.py @@ -19,15 +19,14 @@ class ControlVisVisVolume(ControlBase): def init_form(self): self._form = QWidget() layout = QVBoxLayout() - layout.setMargin(0) - + if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0,0,0,0) elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) self._form.setLayout(layout) - self._app = vv.use('pyqt4') + self._app = vv.use('pyqt5') self._app.Create() self._first = True diff --git a/pyforms/gui/dialogs/csv_parser.py b/pyforms/gui/dialogs/csv_parser.py index c770170..cb219c0 100644 --- a/pyforms/gui/dialogs/csv_parser.py +++ b/pyforms/gui/dialogs/csv_parser.py @@ -15,12 +15,12 @@ def __init__(self, parent=None): # Definition of the forms fields self._filename = ControlFile('CSV File') - self._separator = ControlText('Separator', ';') - self._startingrow = ControlNumber('Starting row', 0) - self._frameCol = ControlNumber('Frame column', 0, 0, 100) - self._xCol = ControlNumber('X column', 1, 0, 100) - self._yCol = ControlNumber('Y column', 2, 0, 100) - self._zCol = ControlNumber('Z column', 3, 0, 100) + self._separator = ControlText('Separator', default=';') + self._startingrow = ControlNumber('Starting row', default=0) + self._frameCol = ControlNumber('Frame column', default=0, minumum=0, maximum=100) + self._xCol = ControlNumber('X column', default=1, minumum=0, maximum=100) + self._yCol = ControlNumber('Y column', default=2, minumum=0, maximum=100) + self._zCol = ControlNumber('Z column', default=3, minumum=0, maximum=100) self._filePreview = ControlList('Preview') self._loadButton = ControlButton('Load') @@ -40,10 +40,10 @@ def filename(self, value): self.__refreshPreview() @property - def loadFileEvent(self): return self._loadButton.value + def load_file_event(self): return self._loadButton.value - @loadFileEvent.setter - def loadFileEvent(self, value): self._loadButton.value = value + @load_file_event.setter + def load_file_event(self, value): self._loadButton.value = value @property def separator(self): return self._separator.value @@ -107,7 +107,7 @@ def __next__(self): return self.next() def next(self): if self._spamreader != None: - row = self._spamreader.next() + row = next(self._spamreader) return [row[int(col)] for col in self._cols] else: raise StopIteration() From fb7088fad177cf67ff72550c19b2352ebb9dfc15 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 13 Feb 2018 15:11:59 +0000 Subject: [PATCH 40/66] Removed pysettings --- docs/api-documentation/settings.md | 2 +- docs/index.md | 4 +- pyforms/__init__.py | 3 +- pyforms/controls.py | 2 +- pyforms/gui/appmanager.py | 4 +- pyforms/gui/basewidget.py | 2 +- pyforms/gui/controls/ControlBase.py | 2 +- pyforms/gui/controls/ControlBoundingSlider.py | 2 +- pyforms/gui/controls/ControlButton.py | 2 +- pyforms/gui/controls/ControlCheckBox.py | 2 +- pyforms/gui/controls/ControlCheckBoxList.py | 2 +- pyforms/gui/controls/ControlCodeEditor.py | 2 +- pyforms/gui/controls/ControlCombo.py | 2 +- pyforms/gui/controls/ControlDir.py | 2 +- pyforms/gui/controls/ControlEmptyWidget.py | 2 +- pyforms/gui/controls/ControlFile.py | 2 +- pyforms/gui/controls/ControlFilesTree.py | 2 +- pyforms/gui/controls/ControlImage.py | 2 +- pyforms/gui/controls/ControlLabel.py | 2 +- pyforms/gui/controls/ControlList.py | 2 +- pyforms/gui/controls/ControlMatplotlib.py | 2 +- pyforms/gui/controls/ControlMdiArea.py | 2 +- pyforms/gui/controls/ControlNumber.py | 2 +- pyforms/gui/controls/ControlOpenGL.py | 2 +- pyforms/gui/controls/ControlToolBox.py | 2 +- .../ControlEventTimeline.py | 2 +- .../TimelinePopupWindow.py | 2 +- .../graphs_eventsgenerator.py | 2 +- .../graphs_properties.py | 2 +- .../control_events_graph/EventsWidget.py | 2 +- .../control_player/AbstractGLWidget.py | 2 +- .../controls/control_player/ControlPlayer.py | 2 +- pyforms/terminal/basewidget.py | 5 ++- pyforms/utils/plugins_finder.py | 2 +- pyforms/utils/settings_manager.py | 42 +++++++++++++++++++ setup.py | 9 +++- tutorials/3.CodeOrganization/PersonWindow.py | 2 +- 37 files changed, 91 insertions(+), 38 deletions(-) create mode 100644 pyforms/utils/settings_manager.py diff --git a/docs/api-documentation/settings.md b/docs/api-documentation/settings.md index d61cf7c..4424bd7 100644 --- a/docs/api-documentation/settings.md +++ b/docs/api-documentation/settings.md @@ -1,6 +1,6 @@ # Settings -Pyforms is using the pysettings library to manage it settings. +Pyforms is using the pyforms.utils.settings_manager library to manage it settings. Here it is described some of the settings of the library. diff --git a/docs/index.md b/docs/index.md index 62b5a5f..c50af58 100644 --- a/docs/index.md +++ b/docs/index.md @@ -34,7 +34,7 @@ pip install pyforms * [setuptools] (https://pypi.python.org/pypi/setuptools) * [Python 2.7](https://www.python.org/download/releases/2.7/) -* [pysettings](https://github.com/UmSenhorQualquer/pysettings.git) +* [pyforms.utils.settings_manager](https://github.com/UmSenhorQualquer/pyforms.utils.settings_manager.git) * [PyQt4](http://www.riverbankcomputing.co.uk/software/pyqt/download) * [PyOpenGL](http://pyopengl.sourceforge.net/) [Optional - Only used by some Controls] * [VisVis](https://code.google.com/p/visvis/) [Optional - Only used by some Controls] @@ -45,7 +45,7 @@ pip install pyforms ### Ubuntu 14 * setuptools: ```sudo apt-get install python-setuptools``` -* pysettings: ```sudo pip install git+https://github.com/UmSenhorQualquer/pysettings.git``` +* pyforms.utils.settings_manager: ```sudo pip install git+https://github.com/UmSenhorQualquer/pyforms.utils.settings_manager.git``` * Opengl: ```sudo apt-get install python-opengl``` * OpenCV: ```sudo apt-get install python-opencv``` * PyQt4: ```sudo apt-get install pyqt4-dev-tools python-qt4``` diff --git a/pyforms/__init__.py b/pyforms/__init__.py index 5b0bd74..ef2d1d9 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf + +from pyforms.utils.settings_manager import conf conf += 'pyforms.settings' diff --git a/pyforms/controls.py b/pyforms/controls.py index 188110b..3a195db 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -48,7 +48,7 @@ from pyforms.gui.controls.ControlImage import ControlImage from pyforms.gui.controls.control_player.ControlPlayer import ControlPlayer except Exception as e: - logger.warning("GL widgets or Opencv not installed") + logger.warning("GL widgets or Opencv is not installed") logger.error(e, exc_info=True) if conf.PYFORMS_VISVIS_ENABLED: diff --git a/pyforms/gui/appmanager.py b/pyforms/gui/appmanager.py index 1a1e080..ae76633 100644 --- a/pyforms/gui/appmanager.py +++ b/pyforms/gui/appmanager.py @@ -5,7 +5,7 @@ from AnyQt import QtCore, _api from AnyQt.QtGui import QIcon -from pysettings import conf +from pyforms.utils.settings_manager import conf import sys, os, platform, logging logger = logging.getLogger(__name__) @@ -157,7 +157,7 @@ def execute_test_file(myapp): def start_app(ClassObject, geometry=None): - from pysettings import conf + from pyforms.utils.settings_manager import conf app = QApplication(sys.argv) diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index 9984f8e..a8e7ef6 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -3,7 +3,7 @@ import json, AnyQt -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QFrame from AnyQt.QtWidgets import QVBoxLayout diff --git a/pyforms/gui/controls/ControlBase.py b/pyforms/gui/controls/ControlBase.py index 9809644..80d669b 100644 --- a/pyforms/gui/controls/ControlBase.py +++ b/pyforms/gui/controls/ControlBase.py @@ -1,7 +1,7 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import QtCore, uic from AnyQt.QtWidgets import QMenu, QAction diff --git a/pyforms/gui/controls/ControlBoundingSlider.py b/pyforms/gui/controls/ControlBoundingSlider.py index dd29ea8..fc051a7 100644 --- a/pyforms/gui/controls/ControlBoundingSlider.py +++ b/pyforms/gui/controls/ControlBoundingSlider.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import QtCore, _api from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QSpinBox diff --git a/pyforms/gui/controls/ControlButton.py b/pyforms/gui/controls/ControlButton.py index 2d81409..923bbfd 100644 --- a/pyforms/gui/controls/ControlButton.py +++ b/pyforms/gui/controls/ControlButton.py @@ -3,7 +3,7 @@ -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import uic from AnyQt.QtWidgets import QPushButton, QSizePolicy diff --git a/pyforms/gui/controls/ControlCheckBox.py b/pyforms/gui/controls/ControlCheckBox.py index 31159a8..df62a48 100644 --- a/pyforms/gui/controls/ControlCheckBox.py +++ b/pyforms/gui/controls/ControlCheckBox.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import uic, QtCore diff --git a/pyforms/gui/controls/ControlCheckBoxList.py b/pyforms/gui/controls/ControlCheckBoxList.py index 1ac74bb..8cfa367 100644 --- a/pyforms/gui/controls/ControlCheckBoxList.py +++ b/pyforms/gui/controls/ControlCheckBoxList.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf import pyforms.utils.tools as tools diff --git a/pyforms/gui/controls/ControlCodeEditor.py b/pyforms/gui/controls/ControlCodeEditor.py index 35033e4..9f634d1 100644 --- a/pyforms/gui/controls/ControlCodeEditor.py +++ b/pyforms/gui/controls/ControlCodeEditor.py @@ -4,7 +4,7 @@ import logging from AnyQt import _api -from pysettings import conf +from pyforms.utils.settings_manager import conf from pyforms.gui.controls.ControlBase import ControlBase import pyforms.utils.tools as tools diff --git a/pyforms/gui/controls/ControlCombo.py b/pyforms/gui/controls/ControlCombo.py index 6965f67..f9f388e 100644 --- a/pyforms/gui/controls/ControlCombo.py +++ b/pyforms/gui/controls/ControlCombo.py @@ -4,7 +4,7 @@ import pyforms.utils.tools as tools -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QLabel, QWidget, QComboBox, QHBoxLayout, QSizePolicy diff --git a/pyforms/gui/controls/ControlDir.py b/pyforms/gui/controls/ControlDir.py index f2f3fb0..8091a12 100644 --- a/pyforms/gui/controls/ControlDir.py +++ b/pyforms/gui/controls/ControlDir.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from pyforms.gui.controls.ControlText import ControlText diff --git a/pyforms/gui/controls/ControlEmptyWidget.py b/pyforms/gui/controls/ControlEmptyWidget.py index bc12f2f..443b6ba 100644 --- a/pyforms/gui/controls/ControlEmptyWidget.py +++ b/pyforms/gui/controls/ControlEmptyWidget.py @@ -1,7 +1,7 @@ #!/usr/bifn/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import _api from AnyQt.QtWidgets import QWidget, QVBoxLayout diff --git a/pyforms/gui/controls/ControlFile.py b/pyforms/gui/controls/ControlFile.py index 174face..f892f81 100644 --- a/pyforms/gui/controls/ControlFile.py +++ b/pyforms/gui/controls/ControlFile.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from pyforms.gui.controls.ControlText import ControlText import pyforms.utils.tools as tools diff --git a/pyforms/gui/controls/ControlFilesTree.py b/pyforms/gui/controls/ControlFilesTree.py index ab4d5f1..1e6fa3e 100644 --- a/pyforms/gui/controls/ControlFilesTree.py +++ b/pyforms/gui/controls/ControlFilesTree.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from pyforms.gui.controls.ControlBase import ControlBase diff --git a/pyforms/gui/controls/ControlImage.py b/pyforms/gui/controls/ControlImage.py index a8418e9..f669b4b 100644 --- a/pyforms/gui/controls/ControlImage.py +++ b/pyforms/gui/controls/ControlImage.py @@ -3,7 +3,7 @@ import logging -from pysettings import conf +from pyforms.utils.settings_manager import conf logger = logging.getLogger(__name__) diff --git a/pyforms/gui/controls/ControlLabel.py b/pyforms/gui/controls/ControlLabel.py index 8dce8e9..669877b 100644 --- a/pyforms/gui/controls/ControlLabel.py +++ b/pyforms/gui/controls/ControlLabel.py @@ -4,7 +4,7 @@ """ pyforms.gui.controls.ControlLabel""" import pyforms.utils.tools as tools -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import uic diff --git a/pyforms/gui/controls/ControlList.py b/pyforms/gui/controls/ControlList.py index bfbb3b2..905d4fe 100644 --- a/pyforms/gui/controls/ControlList.py +++ b/pyforms/gui/controls/ControlList.py @@ -7,7 +7,7 @@ import logging import os -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import QtCore, uic from AnyQt.QtWidgets import QTableWidgetItem, QWidget, QAbstractItemView diff --git a/pyforms/gui/controls/ControlMatplotlib.py b/pyforms/gui/controls/ControlMatplotlib.py index b892f7f..13a7ed2 100644 --- a/pyforms/gui/controls/ControlMatplotlib.py +++ b/pyforms/gui/controls/ControlMatplotlib.py @@ -10,7 +10,7 @@ __status__ = "Development" -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout diff --git a/pyforms/gui/controls/ControlMdiArea.py b/pyforms/gui/controls/ControlMdiArea.py index cf6037e..ba45418 100644 --- a/pyforms/gui/controls/ControlMdiArea.py +++ b/pyforms/gui/controls/ControlMdiArea.py @@ -3,7 +3,7 @@ import logging -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QMdiArea, QMdiSubWindow diff --git a/pyforms/gui/controls/ControlNumber.py b/pyforms/gui/controls/ControlNumber.py index 47113d0..5f29b31 100644 --- a/pyforms/gui/controls/ControlNumber.py +++ b/pyforms/gui/controls/ControlNumber.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf import pyforms.utils.tools as tools diff --git a/pyforms/gui/controls/ControlOpenGL.py b/pyforms/gui/controls/ControlOpenGL.py index de5a180..dcb6bd4 100644 --- a/pyforms/gui/controls/ControlOpenGL.py +++ b/pyforms/gui/controls/ControlOpenGL.py @@ -3,7 +3,7 @@ import logging -from pysettings import conf +from pyforms.utils.settings_manager import conf logger = logging.getLogger(__name__) diff --git a/pyforms/gui/controls/ControlToolBox.py b/pyforms/gui/controls/ControlToolBox.py index c91be40..4562d9d 100644 --- a/pyforms/gui/controls/ControlToolBox.py +++ b/pyforms/gui/controls/ControlToolBox.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import _api from AnyQt.QtWidgets import QToolBox diff --git a/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py b/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py index c8e9ff9..b1e7f41 100644 --- a/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py +++ b/pyforms/gui/controls/control_event_timeline/ControlEventTimeline.py @@ -4,7 +4,7 @@ import csv import os -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QWidget, QScrollArea, QColorDialog, QFileDialog, QMessageBox, QPushButton, QLabel, QSlider, QHBoxLayout, QVBoxLayout diff --git a/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py b/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py index 7087f6d..42d8587 100644 --- a/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py +++ b/pyforms/gui/controls/control_event_timeline/TimelinePopupWindow.py @@ -1,7 +1,7 @@ # !/usr/bin/python # -*- coding: utf-8 -*- -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QDialog, QInputDialog, QColorDialog from AnyQt.QtGui import QColor, QPixmap, QFont, QPainter diff --git a/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py b/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py index 9d03ada..5aac17e 100644 --- a/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py +++ b/pyforms/gui/controls/control_event_timeline/graphs_eventsgenerator.py @@ -13,7 +13,7 @@ import time import datetime -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QMessageBox diff --git a/pyforms/gui/controls/control_event_timeline/graphs_properties.py b/pyforms/gui/controls/control_event_timeline/graphs_properties.py index 8227afe..ba8de0a 100644 --- a/pyforms/gui/controls/control_event_timeline/graphs_properties.py +++ b/pyforms/gui/controls/control_event_timeline/graphs_properties.py @@ -7,7 +7,7 @@ from pyforms.controls import ControlSlider from pyforms.controls import ControlText from pyforms.controls import ControlLabel -from pysettings import conf +from pyforms.utils.settings_manager import conf if conf.PYFORMS_MODE=='GUI': from AnyQt.QtWidgets import QColorDialog diff --git a/pyforms/gui/controls/control_events_graph/EventsWidget.py b/pyforms/gui/controls/control_events_graph/EventsWidget.py index 3f6f0ea..77a012f 100644 --- a/pyforms/gui/controls/control_events_graph/EventsWidget.py +++ b/pyforms/gui/controls/control_events_graph/EventsWidget.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- import sys -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt.QtWidgets import QWidget from AnyQt.QtGui import QColor, QPainter, QFont from AnyQt import QtCore diff --git a/pyforms/gui/controls/control_player/AbstractGLWidget.py b/pyforms/gui/controls/control_player/AbstractGLWidget.py index 699d0d5..3d391b5 100644 --- a/pyforms/gui/controls/control_player/AbstractGLWidget.py +++ b/pyforms/gui/controls/control_player/AbstractGLWidget.py @@ -6,7 +6,7 @@ """ import logging, cv2 -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import QtGui, QtCore, _api from AnyQt.QtWidgets import QApplication diff --git a/pyforms/gui/controls/control_player/ControlPlayer.py b/pyforms/gui/controls/control_player/ControlPlayer.py index 8833337..d5ab37b 100755 --- a/pyforms/gui/controls/control_player/ControlPlayer.py +++ b/pyforms/gui/controls/control_player/ControlPlayer.py @@ -14,7 +14,7 @@ import logging, platform, os, math, cv2 -from pysettings import conf +from pyforms.utils.settings_manager import conf from AnyQt import uic, _api from AnyQt import QtCore from AnyQt.QtWidgets import QFrame diff --git a/pyforms/terminal/basewidget.py b/pyforms/terminal/basewidget.py index 86348f6..4cdfd9b 100644 --- a/pyforms/terminal/basewidget.py +++ b/pyforms/terminal/basewidget.py @@ -3,10 +3,13 @@ import argparse, uuid, os, shutil, time, sys, subprocess import simplejson as json +import logging, traceback; logger=logging.getLogger(__file__) + try: import requests except: - print("No requests lib") + logger.warning("No requests lib") + logger.error(e, exc_info=True) class BaseWidget(object): diff --git a/pyforms/utils/plugins_finder.py b/pyforms/utils/plugins_finder.py index 8b0a9ed..0fb2b84 100644 --- a/pyforms/utils/plugins_finder.py +++ b/pyforms/utils/plugins_finder.py @@ -3,7 +3,7 @@ import re import logging -from pysettings import conf +from pyforms.utils.settings_manager import conf logger = logging.getLogger(__name__) diff --git a/pyforms/utils/settings_manager.py b/pyforms/utils/settings_manager.py new file mode 100644 index 0000000..3ede4d2 --- /dev/null +++ b/pyforms/utils/settings_manager.py @@ -0,0 +1,42 @@ + +import logging; logger = logging.getLogger(__name__) + +class SettingsManager(object): + + def __init__(self): + self._modules = [] + self._loaded_modules = {} + + def __load_module(self, module_name): + if module_name in self._loaded_modules.keys(): return self._loaded_modules[module_name] + + modules = module_name.split('.') + moduleclass = __import__( '.'.join(modules[:-1]) , fromlist=[modules[-1]] ) + + module = getattr(moduleclass, modules[-1]) + self._loaded_modules[module_name] = module + + return module + + def __add__(self, other): + if isinstance(other, str): other = self.__load_module(other) + + modules = object.__getattribute__(self, '_modules') + if other not in modules: + logger.info('added settings: {0}'.format(other.__name__)) + modules.append(other) + self._modules = sorted(modules, key=lambda x: (x.SETTINGS_PRIORITY if hasattr(x, 'SETTINGS_PRIORITY') else 999999999) ) + return self + + def __sub__(self, other): + self._modules.remove(other) + return self + + def __getattribute__(self, name): + for module in object.__getattribute__(self, '_modules'): + if hasattr(module, name): return getattr(module, name) + + return object.__getattribute__(self, name) + + +conf = SettingsManager() \ No newline at end of file diff --git a/setup.py b/setup.py index 7fd72f1..3c34bae 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,14 @@ license='MIT', url='https://github.com/UmSenhorQualquer/pyforms', install_requires=[ - "anyqt", + 'anyqt', + 'pyqt5', + 'pyopengl', + 'QScintilla', + 'visvis', + 'matplotlib', + 'python-dateutil', + 'numpy' ], packages=find_packages(), package_data={'pyforms': [ diff --git a/tutorials/3.CodeOrganization/PersonWindow.py b/tutorials/3.CodeOrganization/PersonWindow.py index 05118f5..8301246 100644 --- a/tutorials/3.CodeOrganization/PersonWindow.py +++ b/tutorials/3.CodeOrganization/PersonWindow.py @@ -1,4 +1,4 @@ -from pysettings import conf; +from pyforms.utils.settings_manager import conf; import settings conf+=settings From 2532c8c4e66dc0df559a1a2e07afa03d566837c3 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 13 Feb 2018 15:45:08 +0000 Subject: [PATCH 41/66] Update setup --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 3c34bae..d2ddd72 100644 --- a/setup.py +++ b/setup.py @@ -13,8 +13,7 @@ setup( name='PyForms', version=version, - description="""Pyforms is a Python 2.7 and 3.4 framework to develop GUI application, - which promotes modular software design and code reusability with minimal effort.""", + description="""Pyforms is a Python 2.7 and 3.4 framework to develop GUI applications based on pyqt""", author='Ricardo Ribeiro', author_email='ricardojvr@gmail.com', license='MIT', From 9d9324a961f71b893a5bf0c68d9f3602968c03e6 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 13 Feb 2018 15:48:47 +0000 Subject: [PATCH 42/66] Create branch v3.0 --- pyforms/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyforms/__init__.py b/pyforms/__init__.py index ef2d1d9..3c8831b 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -13,7 +13,6 @@ __email__ = ["ricardojvr@gmail.com", "cajomferro@gmail.com"] __status__ = "Production" - if conf.PYFORMS_MODE in ['GUI', 'GUI-OPENCSP']: from pyforms.gui import controls From 850948fa43ef4d1193cce3562ff11c5bfb7c75fa Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 13 Feb 2018 16:02:01 +0000 Subject: [PATCH 43/66] Update documentation --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e71f747..466a5bf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![Important](https://img.shields.io/badge/Important-Note-red.svg "Screen") If you find this project useful, please, do not forget to ![star it](https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/v1.0.beta/docs/imgs/start.png?raw=true "Screen") it. -![New version available](https://img.shields.io/badge/New%20version%20available-2.0-green.svg "Screen") +![New version available](https://img.shields.io/badge/New%20version%20available-3.0-green.svg "Screen") @@ -35,6 +35,7 @@ Example of an application running in the Desktop, Web and Terminal enviroments: ## Examples of applications developed in Pyforms * [Python Video Annotator](https://github.com/UmSenhorQualquer/pythonVideoAnnotator) * [3D tracking analyser](https://github.com/UmSenhorQualquer/3D-tracking-analyser) +* [PyBpod](http://pybpod.readthedocs.io) ## Documentation From 6c54cfc7e58af226517c9e27d6b115ff13694ac2 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 13 Feb 2018 16:05:19 +0000 Subject: [PATCH 44/66] Update documentation --- docs/index.md | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/docs/index.md b/docs/index.md index c50af58..11d1397 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,7 +16,7 @@ Pyforms is a Python 2.7.x and 3.x cross-enviroment framework to develop GUI appl * A Python layer that allow applications to run on Desktop GUI, Web and terminal without requiring code modifications. * A group of rules and methodologies that help the developer maintaining his code short, clean, reusable and readable. -![Diagram](https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/v1.0.beta/docs/pyforms.png?raw=true "Screen") +![Diagram](https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/v3.0.beta/docs/pyforms.png?raw=true "Screen") Example of an application running in the Desktop, Web and Terminal enviroments: @@ -28,35 +28,4 @@ Example of an application running in the Desktop, Web and Terminal enviroments: Run in the terminal: ```bash pip install pyforms -``` - -### Requirements - -* [setuptools] (https://pypi.python.org/pypi/setuptools) -* [Python 2.7](https://www.python.org/download/releases/2.7/) -* [pyforms.utils.settings_manager](https://github.com/UmSenhorQualquer/pyforms.utils.settings_manager.git) -* [PyQt4](http://www.riverbankcomputing.co.uk/software/pyqt/download) -* [PyOpenGL](http://pyopengl.sourceforge.net/) [Optional - Only used by some Controls] -* [VisVis](https://code.google.com/p/visvis/) [Optional - Only used by some Controls] -* [Numpy](http://www.numpy.org/) [Optional - Only used by some Controls] -* [Python opencv](http://opencv.org/) [Optional - Only used by some Controls] - - -### Ubuntu 14 - -* setuptools: ```sudo apt-get install python-setuptools``` -* pyforms.utils.settings_manager: ```sudo pip install git+https://github.com/UmSenhorQualquer/pyforms.utils.settings_manager.git``` -* Opengl: ```sudo apt-get install python-opengl``` -* OpenCV: ```sudo apt-get install python-opencv``` -* PyQt4: ```sudo apt-get install pyqt4-dev-tools python-qt4``` -* PyQt4 OpenGL Widget [Optional]: ```sudo apt-get install python-qt4-gl``` -* Pyforms: ```sudo pip install pyforms``` -* VisVis: ```sudo pip install visvis``` - -### Mac OSx - -* Install python and its tools using [Homebrew] (http://brew.sh) -* [Scientific Python on Mac OS X 10.9+ with homebrew | Jörn's Blog](https://joernhees.de/blog/2014/02/25/scientific-python-on-mac-os-x-10-9-with-homebrew/) -* [Installing scientific Python on Mac OS X | Lowin Data Company](http://www.lowindata.com/2013/installing-scientific-python-on-mac-os-x/) -* run ```sudo python setup.py install``` - +``` \ No newline at end of file From 18a4a5422a93153a3701c2ce7658a556cbcba3f9 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 13 Feb 2018 16:08:16 +0000 Subject: [PATCH 45/66] Update docs --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 11d1397..4d733f9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,7 +16,7 @@ Pyforms is a Python 2.7.x and 3.x cross-enviroment framework to develop GUI appl * A Python layer that allow applications to run on Desktop GUI, Web and terminal without requiring code modifications. * A group of rules and methodologies that help the developer maintaining his code short, clean, reusable and readable. -![Diagram](https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/v3.0.beta/docs/pyforms.png?raw=true "Screen") +![Diagram](https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/v3.0/docs/pyforms.png?raw=true "Screen") Example of an application running in the Desktop, Web and Terminal enviroments: From 80a58961d0f77b4603cbc606fe96fdea603a7c19 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 15 Feb 2018 12:05:25 +0000 Subject: [PATCH 46/66] Add django Admin Models --- pyforms/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyforms/__init__.py b/pyforms/__init__.py index 3c8831b..72601b4 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -31,3 +31,7 @@ from pyforms_web.web import Controls from pyforms_web.web.BaseWidget import BaseWidget from pyforms_web.web.appmanager import start_app + + from pyforms_web.web.django_pyforms.model_admin import ModelAdmin + from pyforms_web.web.django_pyforms.model_admin import ViewFormAdmin + from pyforms_web.web.django_pyforms.model_admin import EditFormAdmin From b9eee23ea220fda1fc919b062c9674f1a16a126d Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 16 Feb 2018 14:29:49 +0000 Subject: [PATCH 47/66] . --- pyforms/__init__.py | 4 ++-- pyforms/controls.py | 39 ++++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/pyforms/__init__.py b/pyforms/__init__.py index 72601b4..7c8c6a1 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -28,8 +28,8 @@ elif conf.PYFORMS_MODE in ['WEB']: - from pyforms_web.web import Controls - from pyforms_web.web.BaseWidget import BaseWidget + from pyforms_web.web import controls + from pyforms_web.web.basewidget import BaseWidget, no_columns, segment from pyforms_web.web.appmanager import start_app from pyforms_web.web.django_pyforms.model_admin import ModelAdmin diff --git a/pyforms/controls.py b/pyforms/controls.py index 3a195db..1198a2c 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -85,22 +85,23 @@ elif conf.PYFORMS_MODE=='WEB': - from pyforms_web.web.Controls.ControlBase import ControlBase - from pyforms_web.web.Controls.ControlText import ControlText - from pyforms_web.web.Controls.ControlBoundingSlider import ControlBoundingSlider - from pyforms_web.web.Controls.ControlDate import ControlDate - from pyforms_web.web.Controls.ControlButton import ControlButton - from pyforms_web.web.Controls.ControlCheckBox import ControlCheckBox - from pyforms_web.web.Controls.ControlCombo import ControlCombo - from pyforms_web.web.Controls.ControlDir import ControlDir - from pyforms_web.web.Controls.ControlFile import ControlFile - from pyforms_web.web.Controls.ControlImage import ControlImage - from pyforms_web.web.Controls.ControlSlider import ControlSlider - from pyforms_web.web.Controls.ControlPlayer import ControlPlayer - from pyforms_web.web.Controls.ControlProgress import ControlProgress - from pyforms_web.web.Controls.ControlVisVis import ControlVisVis - from pyforms_web.web.Controls.ControlList import ControlList - from pyforms_web.web.Controls.ControlLabel import ControlLabel - from pyforms_web.web.Controls.ControlTimeout import ControlTimeout - from pyforms_web.web.Controls.ControlEmptyWidget import ControlEmptyWidget - from pyforms_web.web.Controls.ControlWorkflow import ControlWorkflow + from pyforms_web.web.controls.ControlBase import ControlBase + from pyforms_web.web.controls.ControlText import ControlText + from pyforms_web.web.controls.ControlBoundingSlider import ControlBoundingSlider + from pyforms_web.web.controls.ControlDate import ControlDate + from pyforms_web.web.controls.ControlButton import ControlButton + from pyforms_web.web.controls.ControlCheckBox import ControlCheckBox + from pyforms_web.web.controls.ControlCombo import ControlCombo + from pyforms_web.web.controls.ControlDir import ControlDir + from pyforms_web.web.controls.ControlFile import ControlFile + from pyforms_web.web.controls.ControlImage import ControlImage + from pyforms_web.web.controls.ControlSlider import ControlSlider + from pyforms_web.web.controls.ControlPlayer import ControlPlayer + from pyforms_web.web.controls.ControlProgress import ControlProgress + from pyforms_web.web.controls.ControlVisVis import ControlVisVis + from pyforms_web.web.controls.ControlList import ControlList + from pyforms_web.web.controls.ControlLabel import ControlLabel + from pyforms_web.web.controls.ControlTimeout import ControlTimeout + from pyforms_web.web.controls.ControlEmptyWidget import ControlEmptyWidget + from pyforms_web.web.controls.ControlWorkflow import ControlWorkflow + from pyforms_web.web.controls.ControlPieChart import ControlPieChart From 2bcaa2cda93e0470ab962c2f7f5a0f481554f727 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Wed, 21 Feb 2018 13:27:24 +0000 Subject: [PATCH 48/66] Add question function to basewidget --- pyforms/gui/basewidget.py | 32 ++++++++++++++++++++++++- pyforms/gui/controls/ControlTextArea.py | 2 +- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index a8e7ef6..8ed0932 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -20,6 +20,8 @@ from pyforms.gui.controls.ControlBase import ControlBase +from AnyQt.QtWidgets import QMessageBox + class BaseWidget(QFrame): """ @@ -358,11 +360,39 @@ def load_window(self): def close(self): super(BaseWidget, self).close() - def message(self, msg, title=None, msg_type=None): pass + + def question(self, msg, title=None, ): + reply = QMessageBox.question(self, title, msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) + + if reply == QMessageBox.Yes or reply == QMessageBox.No: + return reply == QMessageBox.Yes + else: + return None + + def message(self, msg, title=None, msg_type=None): + if msg_type=='success': + QMessageBox.about(self, title, msg) + elif msg_type=='info': + QMessageBox.information(self, title, msg) + elif msg_type=='warning': + QMessageBox.warning(self, title, msg) + elif msg_type=='error': + QMessageBox.critical(self, title, msg) + elif msg_type=='about': + QMessageBox.about(self, title, msg) + elif msg_type=='aboutQt': + QMessageBox.aboutQt(self, msg) + else: + QMessageBox.about(self, title, msg) + + def success(self, msg, title=None): self.message(msg, title, msg_type='success') def info(self, msg, title=None): self.message(msg, title, msg_type='info') def warning(self, msg, title=None): self.message(msg, title, msg_type='warning'); def alert(self, msg, title=None): self.message(msg, title, msg_type='error') + def critical(self, msg, title=None): self.message(msg, title, msg_type='error') + def about(self, msg, title=None): self.message(msg, title, msg_type='about') + def aboutQt(self, msg, title=None): self.message(msg, title, msg_type='aboutQt') def message_popup(self, msg, title='', buttons=None, handler=None, msg_type='success'): pass diff --git a/pyforms/gui/controls/ControlTextArea.py b/pyforms/gui/controls/ControlTextArea.py index 42ff0a9..cc1cd46 100644 --- a/pyforms/gui/controls/ControlTextArea.py +++ b/pyforms/gui/controls/ControlTextArea.py @@ -17,7 +17,7 @@ class ControlTextArea(ControlBase): def __init__(self, *args, **kwargs): ControlBase.__init__(self, *args, **kwargs) - self.autoscroll = False + self.autoscroll = kwargs.get('autoscroll', False) From c383f49d771474ad9d6f3615bef9745b0b1c6466 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Mon, 26 Feb 2018 16:51:05 +0000 Subject: [PATCH 49/66] . --- pyforms/__init__.py | 2 +- pyforms/gui/basewidget.py | 2 +- pyforms/gui/controls/ControlBase.py | 17 +- pyforms/gui/controls/ControlList.py | 767 ++++++++++++++-------------- pyforms/utils/timeit.py | 4 +- 5 files changed, 401 insertions(+), 391 deletions(-) diff --git a/pyforms/__init__.py b/pyforms/__init__.py index 7c8c6a1..92e6989 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -8,7 +8,7 @@ __author__ = "Ricardo Ribeiro" __credits__ = ["Ricardo Ribeiro"] __license__ = "MIT" -__version__ = '3.0.0' +__version__ = '3.0.1' __maintainer__ = ["Ricardo Ribeiro", "Carlos Mão de Ferro"] __email__ = ["ricardojvr@gmail.com", "cajomferro@gmail.com"] __status__ = "Production" diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index 8ed0932..c198c9e 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -362,7 +362,7 @@ def close(self): def question(self, msg, title=None, ): - reply = QMessageBox.question(self, title, msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) + reply = QMessageBox.question(self, title, msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes or reply == QMessageBox.No: return reply == QMessageBox.Yes diff --git a/pyforms/gui/controls/ControlBase.py b/pyforms/gui/controls/ControlBase.py index 80d669b..92a003f 100644 --- a/pyforms/gui/controls/ControlBase.py +++ b/pyforms/gui/controls/ControlBase.py @@ -16,12 +16,10 @@ class ControlBase(object): """ def __init__(self, *args, **kwargs): - self._form = None # Qt widget - self._parent = None # Parent window + self._form = None # Qt widget + self._parent = None # Parent window self._popup_menu = None - self.changed_event = kwargs.get('changed_event', self.changed_event) - self._help = kwargs.get('helptext', None) self._value = kwargs.get('default', None) self._label = kwargs.get('label', args[0] if len(args)>0 else '') @@ -33,14 +31,13 @@ def __init__(self, *args, **kwargs): self._readonly = kwargs.get('readonly', False) self._label_visible = kwargs.get('label_visible', True) """ - - self.init_form() - self.enabled = kwargs.get('enabled', True) - self.readonly = kwargs.get('readonly', False) + self.init_form() - if not kwargs.get('visible', True): - self.hide() + self.changed_event = kwargs.get('changed_event', self.changed_event) + self.enabled = kwargs.get('enabled', True) + self.readonly = kwargs.get('readonly', False) + if not kwargs.get('visible', True): self.hide() def __repr__(self): return str(self._value) diff --git a/pyforms/gui/controls/ControlList.py b/pyforms/gui/controls/ControlList.py index 905d4fe..25ab40e 100644 --- a/pyforms/gui/controls/ControlList.py +++ b/pyforms/gui/controls/ControlList.py @@ -9,9 +9,9 @@ from pyforms.utils.settings_manager import conf -from AnyQt import QtCore, uic +from AnyQt import QtCore, uic from AnyQt.QtWidgets import QTableWidgetItem, QWidget, QAbstractItemView -from AnyQt.QtGui import QIcon +from AnyQt.QtGui import QIcon from pyforms.gui.basewidget import BaseWidget from pyforms.gui.controls.ControlBase import ControlBase @@ -20,378 +20,391 @@ class ControlList(ControlBase, QWidget): - """ This class represents a wrapper to the table widget - It allows to implement a list view - """ - - CELL_VALUE_BEFORE_CHANGE = None # store value when cell is double clicked - - def __init__(self, *args, **kwargs): - QWidget.__init__(self) - - self._plusFunction = kwargs.get('add_function', None) - self._minusFunction = kwargs.get('remove_function', None) - ControlBase.__init__(self, *args, **kwargs) - - self.autoscroll = False - - self.select_entire_row = kwargs.get('select_entire_row', False) - - - ########################################################################## - ############ FUNCTIONS ################################################### - ########################################################################## - - def init_form(self): - plusFunction = self._plusFunction - minusFunction = self._minusFunction - - # Get the current path of the file - rootPath = os.path.dirname(__file__) - # Load the UI for the self instance - uic.loadUi(os.path.join(rootPath, "list.ui"), self) - - self.label = self._label - - self.tableWidget.currentCellChanged.connect( - self.tableWidgetCellChanged) - self.tableWidget.currentItemChanged.connect( - self.tableWidgetItemChanged) - self.tableWidget.itemSelectionChanged.connect( - self.tableWidgetItemSelectionChanged) - self.tableWidget.cellDoubleClicked.connect(self.tableWidgetCellDoubleClicked) - self.tableWidget.model().dataChanged.connect(self._dataChangedEvent) - - - self.tableWidget.horizontalHeader().setVisible(False) - - if plusFunction is None and minusFunction is None: - self.bottomBar.hide() - elif plusFunction is None: - self.plusButton.hide() - self.minusButton.pressed.connect(minusFunction) - elif minusFunction is None: - self.minusButton.hide() - self.plusButton.pressed.connect(plusFunction) - else: - self.plusButton.pressed.connect(plusFunction) - self.minusButton.pressed.connect(minusFunction) - - - - def __repr__(self): - return "ControlList " + str(self._value) - - def clear(self, headers=False): - - for row in range(self.rows_count): - columns = [] - for column in range(self.columns_count): - v = self.get_value(column, row) - if isinstance(v, BaseWidget): - v.destroy() - - if headers: - self.tableWidget.clear() - self.tableWidget.setColumnCount(3) - self.tableWidget.setRowCount(0) - else: - self.tableWidget.clearContents() - self.tableWidget.setRowCount(0) - - def save_form(self, data, path=None): - if self.value: - rows = [] - for row in range(self.rows_count): - columns = [] - for column in range(self.columns_count): - v = self.get_value(column, row) - if isinstance(v, BaseWidget): - columns.append(v.save_form({}, path)) - else: - columns.append(str(v)) - rows.append(columns) - data['value'] = rows - return data - - def load_form(self, data, path=None): - if self.value: - rows = data['value'] - for row in range(len(rows)): - for column in range(len(rows[row])): - v = self.get_value(column, row) - if isinstance(v, BaseWidget): - v.load_form(rows[row][column], path) - else: - self.set_value(column, row, rows[row][column]) - elif 'value' in data.keys(): - self.value = data['value'] - - def __add__(self, other): - row_index = self.tableWidget.rowCount() - - self.tableWidget.insertRow(row_index) - - #increase the number of columns if necessary #### - if self.tableWidget.currentColumn() < len(other): - self.tableWidget.setColumnCount(len(other)) - ################################################# - - for column, e in enumerate(other): self.set_value(column, row_index, e) - - self.tableWidget.resizeColumnsToContents() - - # auto scroll the list to the new inserted item ################## - if self.autoscroll: - self.tableWidget.scrollToItem( self.get_cell(0,row_index) ) - ################################################################## - return self - - def __sub__(self, other): - - if isinstance(other, int): - if other < 0: - indexToRemove = self.tableWidget.currentRow() - else: - indexToRemove = other - - self.tableWidget.removeRow(indexToRemove) - return self - - def set_value(self, column, row, value): - if isinstance(value, QWidget): - self.tableWidget.setCellWidget(row, column, value) - value.show() - self.tableWidget.setRowHeight(row, value.height()) - elif isinstance(value, ControlBase): - self.tableWidget.setCellWidget(row, column, value.form) - value.show() - self.tableWidget.setRowHeight(row, value.form.height()) - else: - args = [value] if not hasattr(value, 'icon') else [QIcon(value.icon), value] - item = QTableWidgetItem() - item.setData(QtCore.Qt.EditRole, *args) - self.tableWidget.setItem(row, column, item) - - def get_value(self, column, row): - try: - return str(self.tableWidget.item(row, column).text()) - except AttributeError as err: - return self.tableWidget.cellWidget(row, column) - except AttributeError as err: - return '' - - def resize_rows_contents(self): - self.tableWidget.resizeRowsToContents() - - def get_currentrow_value(self): - currentRow = self.tableWidget.currentRow() - if not currentRow < 0: - return self.value[currentRow] - else: - return [] - - def get_cell(self, column, row): - return self.tableWidget.item(row, column) - - def set_sorting_enabled(self, value): - """ - Enable or disable columns sorting - - :param bool value: True to enable sorting, False otherwise - """ - self.tableWidget.setSortingEnabled(value) - - ########################################################################## - ############ EVENTS ###################################################### - ########################################################################## - - def data_changed_event(self, row, col, item): - pass - - def item_selection_changed_event(self): - pass - - def current_cell_changed_event(self, next_row, next_col, previous_row, previous_col): - pass - - def current_item_changed_event(self, current, previous): - pass - - def cell_double_clicked_event(self, row, column): - pass - - ########################################################################## - ############ PROPERTIES ################################################## - ########################################################################## - - - @property - def horizontal_headers(self): - return self._horizontalHeaders - - @horizontal_headers.setter - def horizontal_headers(self, horizontal_headers): - """Set horizontal headers in the table list.""" - - self._horizontalHeaders = horizontal_headers - - self.tableWidget.setColumnCount(len(horizontal_headers)) - self.tableWidget.horizontalHeader().setVisible(True) - - for idx, header in enumerate(horizontal_headers): - item = QTableWidgetItem() - item.setText(header) - self.tableWidget.setHorizontalHeaderItem(idx, item) - - @property - def word_wrap(self): - return self.tableWidget.wordWrap() - - @word_wrap.setter - def word_wrap(self, value): - self.tableWidget.setWordWrap(value) - - @property - def readonly(self): - return self.tableWidget.editTriggers() - - @readonly.setter - def readonly(self, value): - if value: - self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) - else: - self.tableWidget.setEditTriggers(QAbstractItemView.AllEditTriggers) - - @property - def select_entire_row(self): - return self.tableWidget.selectionBehavior() - - @select_entire_row.setter - def select_entire_row(self, value): - if value: - self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) - else: - self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectItems) - - @property - def rows_count(self): - return self.tableWidget.rowCount() - - @property - def columns_count(self): - return self.tableWidget.columnCount() - - def __len__(self): - return self.rows_count - - @property - def value(self): - if hasattr(self, 'tableWidget'): - results = [] - for row in range(self.tableWidget.rowCount()): - r = [] - for col in range(self.tableWidget.columnCount()): - try: - r.append(self.get_value(col, row)) - except Exception as err: - logger.debug(str(err)) - r.append("") - results.append(r) - return results - return self._value - - @value.setter - def value(self, value): - self.clear() - for row in value: self += row - - # TODO: implement += on self.value? I want to add a list of tuples to - # self.value - - @property - def selected_rows_indexes(self): - result = [] - for index in self.tableWidget.selectedIndexes(): - result.append(index.row()) - return list(set(result)) - - @property - def selected_row_index(self): - indexes = self.selected_rows_indexes - if len(indexes) > 0: - return indexes[0] - else: - return None - - @property - def label(self): - return self.labelWidget.getText() - - @label.setter - def label(self, value): - if value != '': - self.labelWidget.setText(value) - else: - self.labelWidget.hide() - - @property - def form(self): - return self - - @property - def icon_size(self): - return self.tableWidget.iconSize() - - @icon_size.setter - def icon_size(self, value): - if isinstance(value, (tuple, list)): - self.tableWidget.setIconSize(QtCore.QSize(*value)) - else: - self.tableWidget.setIconSize(QtCore.QSize(value, value)) - - @property - def autoscroll(self): return self._autoscroll - @autoscroll.setter - def autoscroll(self, value): self._autoscroll = value - - - ########################################################################## - ############ PRIVATE FUNCTIONS ########################################### - ########################################################################## - - def _dataChangedEvent(self, item): - self.data_changed_event(item.row(), item.column(), self.tableWidget.model().data(item)) - self.changed_event() - - def tableWidgetCellChanged(self, nextRow, nextCol, previousRow, - previousCol): - self.current_cell_changed_event(nextRow, nextCol, previousRow, previousCol) - self.changed_event() - - def tableWidgetItemChanged(self, current, previous): - self.current_item_changed_event(current, previous) - self.changed_event() - - def tableWidgetItemSelectionChanged(self): - self.item_selection_changed_event() - - def tableWidgetCellDoubleClicked(self, row, column): - """ - (From PyQt) This signal is emitted whenever a cell in the table is double clicked. - The row and column specified is the cell that was double clicked. - - Besides firing this signal, we save the current value, in case the user needs to know the old value. - :param row: - :param column: - :return: - """ - self.CELL_VALUE_BEFORE_CHANGE = self.get_value(column, row) - logger.debug("Cell double clicked. Stored value: %s", self.CELL_VALUE_BEFORE_CHANGE) - self.cell_double_clicked_event(row, column) - - def empty_signal(self, *args, **kwargs): - """ - Use this function if you want to disconnect a signal temporarily - """ - pass + """ This class represents a wrapper to the table widget + It allows to implement a list view + """ + + CELL_VALUE_BEFORE_CHANGE = None # store value when cell is double clicked + + def __init__(self, *args, **kwargs): + QWidget.__init__(self) + + self._plusFunction = kwargs.get('add_function', None) + self._minusFunction = kwargs.get('remove_function', None) + ControlBase.__init__(self, *args, **kwargs) + + self.autoscroll = kwargs.get('autoscroll', True) + self.resizecolumns = kwargs.get('resizecolumns', True) + self.select_entire_row = kwargs.get('select_entire_row', False) + self.horizontal_headers = kwargs.get('horizontal_headers', None) + + ########################################################################## + ############ FUNCTIONS ################################################### + ########################################################################## + + def init_form(self): + plusFunction = self._plusFunction + minusFunction = self._minusFunction + + # Get the current path of the file + rootPath = os.path.dirname(__file__) + # Load the UI for the self instance + uic.loadUi(os.path.join(rootPath, "list.ui"), self) + + self.label = self._label + + self.tableWidget.currentCellChanged.connect( + self.tableWidgetCellChanged) + self.tableWidget.currentItemChanged.connect( + self.tableWidgetItemChanged) + self.tableWidget.itemSelectionChanged.connect( + self.tableWidgetItemSelectionChanged) + self.tableWidget.cellDoubleClicked.connect(self.tableWidgetCellDoubleClicked) + self.tableWidget.model().dataChanged.connect(self._dataChangedEvent) + + + self.tableWidget.horizontalHeader().setVisible(False) + + if plusFunction is None and minusFunction is None: + self.bottomBar.hide() + elif plusFunction is None: + self.plusButton.hide() + self.minusButton.pressed.connect(minusFunction) + elif minusFunction is None: + self.minusButton.hide() + self.plusButton.pressed.connect(plusFunction) + else: + self.plusButton.pressed.connect(plusFunction) + self.minusButton.pressed.connect(minusFunction) + + + + def __repr__(self): + return "ControlList " + str(self._value) + + def clear(self, headers=False): + + for row in range(self.rows_count): + columns = [] + for column in range(self.columns_count): + v = self.get_value(column, row) + if isinstance(v, BaseWidget): + v.destroy() + + if headers: + self.tableWidget.clear() + self.tableWidget.setColumnCount(3) + self.tableWidget.setRowCount(0) + else: + self.tableWidget.clearContents() + self.tableWidget.setRowCount(0) + + def save_form(self, data, path=None): + if self.value: + rows = [] + for row in range(self.rows_count): + columns = [] + for column in range(self.columns_count): + v = self.get_value(column, row) + if isinstance(v, BaseWidget): + columns.append(v.save_form({}, path)) + else: + columns.append(str(v)) + rows.append(columns) + data['value'] = rows + return data + + def load_form(self, data, path=None): + if self.value: + rows = data['value'] + for row in range(len(rows)): + for column in range(len(rows[row])): + v = self.get_value(column, row) + if isinstance(v, BaseWidget): + v.load_form(rows[row][column], path) + else: + self.set_value(column, row, rows[row][column]) + elif 'value' in data.keys(): + self.value = data['value'] + + def __add__(self, other): + row_index = self.tableWidget.rowCount() + + self.tableWidget.insertRow(row_index) + + #increase the number of columns if necessary #### + if self.tableWidget.currentColumn() < len(other): + self.tableWidget.setColumnCount(len(other)) + ################################################# + + for column, e in enumerate(other): self.set_value(column, row_index, e) + + #Auto resize the columns if the flag is activated ################ + if self.resizecolumns: + self.tableWidget.resizeColumnsToContents() + ################################################################## + + # auto scroll the list to the new inserted item ################## + if self.autoscroll: + self.tableWidget.scrollToItem( self.get_cell(0,row_index) ) + ################################################################## + return self + + def __sub__(self, other): + + if isinstance(other, int): + if other < 0: + indexToRemove = self.tableWidget.currentRow() + else: + indexToRemove = other + + self.tableWidget.removeRow(indexToRemove) + return self + + def set_value(self, column, row, value): + if isinstance(value, QWidget): + self.tableWidget.setCellWidget(row, column, value) + value.show() + self.tableWidget.setRowHeight(row, value.height()) + elif isinstance(value, ControlBase): + self.tableWidget.setCellWidget(row, column, value.form) + value.show() + self.tableWidget.setRowHeight(row, value.form.height()) + else: + args = [value] if not hasattr(value, 'icon') else [QIcon(value.icon), value] + item = QTableWidgetItem() + item.setData(QtCore.Qt.EditRole, *args) + self.tableWidget.setItem(row, column, item) + + def get_value(self, column, row): + try: + return str(self.tableWidget.item(row, column).text()) + except AttributeError as err: + return self.tableWidget.cellWidget(row, column) + except AttributeError as err: + return '' + + def resize_rows_contents(self): + self.tableWidget.resizeRowsToContents() + + def get_currentrow_value(self): + currentRow = self.tableWidget.currentRow() + if not currentRow < 0: + return self.value[currentRow] + else: + return [] + + def get_cell(self, column, row): + return self.tableWidget.item(row, column) + + def set_sorting_enabled(self, value): + """ + Enable or disable columns sorting + + :param bool value: True to enable sorting, False otherwise + """ + self.tableWidget.setSortingEnabled(value) + + ########################################################################## + ############ EVENTS ###################################################### + ########################################################################## + + def data_changed_event(self, row, col, item): + pass + + def item_selection_changed_event(self): + pass + + def current_cell_changed_event(self, next_row, next_col, previous_row, previous_col): + pass + + def current_item_changed_event(self, current, previous): + pass + + def cell_double_clicked_event(self, row, column): + pass + + ########################################################################## + ############ PROPERTIES ################################################## + ########################################################################## + + + @property + def horizontal_headers(self): + return self._horizontalHeaders + + @horizontal_headers.setter + def horizontal_headers(self, horizontal_headers): + """Set horizontal headers in the table list.""" + if horizontal_headers is None: + self._horizontalHeaders = horizontal_headers + self.tableWidget.horizontalHeader().setVisible(False) + return + + + self._horizontalHeaders = horizontal_headers + + self.tableWidget.setColumnCount(len(horizontal_headers)) + self.tableWidget.horizontalHeader().setVisible(True) + + for idx, header in enumerate(horizontal_headers): + item = QTableWidgetItem() + item.setText(header) + self.tableWidget.setHorizontalHeaderItem(idx, item) + + @property + def word_wrap(self): + return self.tableWidget.wordWrap() + + @word_wrap.setter + def word_wrap(self, value): + self.tableWidget.setWordWrap(value) + + @property + def readonly(self): + return self.tableWidget.editTriggers() + + @readonly.setter + def readonly(self, value): + if value: + self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) + else: + self.tableWidget.setEditTriggers(QAbstractItemView.AllEditTriggers) + + @property + def select_entire_row(self): + return self.tableWidget.selectionBehavior() + + @select_entire_row.setter + def select_entire_row(self, value): + if value: + self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) + else: + self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectItems) + + @property + def rows_count(self): + return self.tableWidget.rowCount() + + @property + def columns_count(self): + return self.tableWidget.columnCount() + + def __len__(self): + return self.rows_count + + @property + def value(self): + if hasattr(self, 'tableWidget'): + results = [] + for row in range(self.tableWidget.rowCount()): + r = [] + for col in range(self.tableWidget.columnCount()): + try: + r.append(self.get_value(col, row)) + except Exception as err: + logger.debug(str(err)) + r.append("") + results.append(r) + return results + return self._value + + @value.setter + def value(self, value): + self.clear() + for row in value: self += row + + # TODO: implement += on self.value? I want to add a list of tuples to + # self.value + + @property + def selected_rows_indexes(self): + result = [] + for index in self.tableWidget.selectedIndexes(): + result.append(index.row()) + return list(set(result)) + + @property + def selected_row_index(self): + indexes = self.selected_rows_indexes + if len(indexes) > 0: + return indexes[0] + else: + return None + + @property + def label(self): + return self.labelWidget.getText() + + @label.setter + def label(self, value): + if value != '': + self.labelWidget.setText(value) + else: + self.labelWidget.hide() + + @property + def form(self): + return self + + @property + def icon_size(self): + return self.tableWidget.iconSize() + + @icon_size.setter + def icon_size(self, value): + if isinstance(value, (tuple, list)): + self.tableWidget.setIconSize(QtCore.QSize(*value)) + else: + self.tableWidget.setIconSize(QtCore.QSize(value, value)) + + @property + def autoscroll(self): return self._autoscroll + @autoscroll.setter + def autoscroll(self, value): self._autoscroll = value + + @property + def resizecolumns(self): return self._resizecolumns + @resizecolumns.setter + def resizecolumns(self, value): self._resizecolumns = value + + + ########################################################################## + ############ PRIVATE FUNCTIONS ########################################### + ########################################################################## + + def _dataChangedEvent(self, item): + self.data_changed_event(item.row(), item.column(), self.tableWidget.model().data(item)) + self.changed_event() + + def tableWidgetCellChanged(self, nextRow, nextCol, previousRow, + previousCol): + self.current_cell_changed_event(nextRow, nextCol, previousRow, previousCol) + self.changed_event() + + def tableWidgetItemChanged(self, current, previous): + self.current_item_changed_event(current, previous) + self.changed_event() + + def tableWidgetItemSelectionChanged(self): + self.item_selection_changed_event() + + def tableWidgetCellDoubleClicked(self, row, column): + """ + (From PyQt) This signal is emitted whenever a cell in the table is double clicked. + The row and column specified is the cell that was double clicked. + + Besides firing this signal, we save the current value, in case the user needs to know the old value. + :param row: + :param column: + :return: + """ + self.CELL_VALUE_BEFORE_CHANGE = self.get_value(column, row) + logger.debug("Cell double clicked. Stored value: %s", self.CELL_VALUE_BEFORE_CHANGE) + self.cell_double_clicked_event(row, column) + + def empty_signal(self, *args, **kwargs): + """ + Use this function if you want to disconnect a signal temporarily + """ + pass diff --git a/pyforms/utils/timeit.py b/pyforms/utils/timeit.py index 6e780b1..2ea1eac 100755 --- a/pyforms/utils/timeit.py +++ b/pyforms/utils/timeit.py @@ -12,14 +12,14 @@ import time -from datetime import datetime, timedelta +from datetime import datetime as datetime_dt, timedelta def timeit(method): def timed(*args, **kw): ts = time.time() result = method(*args, **kw) te = time.time() - time_elapsed = datetime(1,1,1) + timedelta(seconds=(te-ts) ) + time_elapsed = datetime_dt(1,1,1) + timedelta(seconds=(te-ts) ) print("%s: %d:%d:%d:%d;%d" % (method.__name__, time_elapsed.day-1, time_elapsed.hour, time_elapsed.minute, time_elapsed.second, time_elapsed.microsecond)) return result return timed \ No newline at end of file From bad5ebf93046dd6d588a8f6055ad984a2862d792 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 27 Feb 2018 16:18:24 +0000 Subject: [PATCH 50/66] . --- pyforms/gui/controls/ControlButton.py | 3 +++ pyforms/gui/controls/control_player/ControlPlayer.py | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/pyforms/gui/controls/ControlButton.py b/pyforms/gui/controls/ControlButton.py index 923bbfd..a16ec7b 100644 --- a/pyforms/gui/controls/ControlButton.py +++ b/pyforms/gui/controls/ControlButton.py @@ -20,6 +20,9 @@ def __init__(self, *args, **kwargs): default = kwargs.get('default', None) if default: self.value = default + icon = kwargs.get('icon', None) + if icon: self.icon = icon + def init_form(self): self._form = QPushButton() self._form.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) diff --git a/pyforms/gui/controls/control_player/ControlPlayer.py b/pyforms/gui/controls/control_player/ControlPlayer.py index d5ab37b..8f2492a 100755 --- a/pyforms/gui/controls/control_player/ControlPlayer.py +++ b/pyforms/gui/controls/control_player/ControlPlayer.py @@ -206,6 +206,7 @@ def value(self): return ControlBase.value.fget(self) @value.setter def value(self, value): + self.form.setUpdatesEnabled(False) if value is None: self.stop() self.videoControl.setEnabled(False) @@ -233,6 +234,7 @@ def value(self, value): self.videoControl.setEnabled(True) self.refresh() + self.form.setUpdatesEnabled(True) ########################################################################## @@ -252,6 +254,8 @@ def __rotateZ(self): def update_frame(self): + self.form.setUpdatesEnabled(False) + if not self.visible: self.stop() if self.value is None: @@ -277,6 +281,9 @@ def update_frame(self): if self._updateVideoFrame: self.videoFrames.setValue(currentFrame) + self.form.setUpdatesEnabled(True) + + def videoPlay_clicked(self): """Slot for Play/Pause functionality.""" From 3734f99bf125dbb317a3c08d21d73d2adda8d39c Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 27 Feb 2018 18:35:42 +0000 Subject: [PATCH 51/66] . --- .../control_event_timeline/import_window.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/pyforms/gui/controls/control_event_timeline/import_window.py b/pyforms/gui/controls/control_event_timeline/import_window.py index 3c0f1bf..e534c6c 100644 --- a/pyforms/gui/controls/control_event_timeline/import_window.py +++ b/pyforms/gui/controls/control_event_timeline/import_window.py @@ -193,6 +193,8 @@ def __import_bonsai_events_oldformat(self): points_events = [] first_date = None + + open_windows = {} for row in csvfile: row = row[:-1] #remove the newline character @@ -201,7 +203,7 @@ def __import_bonsai_events_oldformat(self): #eventtype = row[-split:] eventtype = 'end' timestr = row[split-33:split] - eventname = row[4:split-33] + eventname = row[3:split-33].strip() elif row.endswith('PointEvent'): split = row.rfind(' ') eventtype = row[split+1:] @@ -210,7 +212,7 @@ def __import_bonsai_events_oldformat(self): else: eventtype = 'start' timestr = row[-33:] - eventname = row[6:-33] + eventname = row[5:-33].strip() cvttime = dateutil.parser.parse(timestr.replace('T', ' ')) cvttime = cvttime.replace(tzinfo=None) @@ -223,11 +225,14 @@ def __import_bonsai_events_oldformat(self): points_events.append([eventtype, frame, eventname]) else: if eventtype=='start': - windows_events.append( [eventtype, frame, eventname] ) + open_windows[eventname] = frame elif eventtype=='end': - windows_events.append( [eventtype, frame, eventname] ) + begin_frame = open_windows[eventname] + del open_windows[eventname] + windows_events.append( [eventtype, (begin_frame, frame) , eventname] ) - windows_events = sorted(windows_events, key=lambda x: (x[0][0].capitalize(), x[0][1])) + + windows_events = sorted(windows_events, key=lambda x: (x[0].capitalize(), x[2], x[1])) points_events = sorted(points_events, key=lambda x: (x[0].capitalize(), x[1])) ntracks = len(set([x[0][1] for x in windows_events])) + 1 @@ -242,11 +247,8 @@ def __import_bonsai_events_oldformat(self): current_track = 1 - for i in range(0, len(windows_events), 2): - start = windows_events[i] - end = windows_events[i+1] - eventtype, frame_begin, eventname = start - _, frame_end, _ = end + for event in windows_events: + eventtype, (frame_begin, frame_end), eventname = event if eventname not in events_types: events_types[eventname] = current_track @@ -256,6 +258,8 @@ def __import_bonsai_events_oldformat(self): track = events_types[eventname] self._timeline.add_period([frame_begin, frame_end, eventname], row=track) + + except Exception as e: self.warning("An error occurred when trying to import the file. Please check the logs.") logger.error(e, exc_info=True) \ No newline at end of file From f34816db018f05c581ede42804771faa39e78824 Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Mon, 5 Mar 2018 01:36:07 -0500 Subject: [PATCH 52/66] Changed a few gendered words in the docs --- README.md | 2 +- docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 53a74ef..7468f1c 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Pyforms is a Python 2.7.x and 3.x cross-enviroment framework to develop GUI appl ### It offers: * A Python layer of Desktop forms, based on PyQt, OpenGL and other libraries. * A Python layer that allow applications to run on Desktop GUI, Web and terminal without requiring code modifications. -* A group of rules and methodologies that help the developer maintaining his code short, clean, reusable and readable. +* A group of rules and methodologies that help the developer maintain short, clean, reusable and readable code. ![Diagram](docs/pyforms.png?raw=true "Screen") diff --git a/docs/index.md b/docs/index.md index 62b5a5f..e565510 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,7 +14,7 @@ Pyforms is a Python 2.7.x and 3.x cross-enviroment framework to develop GUI appl ### It offers * A Python layer of Desktop forms, based on PyQt, OpenGL and other libraries. * A Python layer that allow applications to run on Desktop GUI, Web and terminal without requiring code modifications. -* A group of rules and methodologies that help the developer maintaining his code short, clean, reusable and readable. +* A group of rules and methodologies that help the developer maintain short, clean, reusable and readable code. ![Diagram](https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/v1.0.beta/docs/pyforms.png?raw=true "Screen") From b27893b6fb331b1f8a4848e83887969ab449791f Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 8 Mar 2018 15:07:24 +0000 Subject: [PATCH 53/66] Add the initial frame on ControlEventsTimeline import window --- .../control_event_timeline/import_window.py | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/pyforms/gui/controls/control_event_timeline/import_window.py b/pyforms/gui/controls/control_event_timeline/import_window.py index e534c6c..749dd22 100644 --- a/pyforms/gui/controls/control_event_timeline/import_window.py +++ b/pyforms/gui/controls/control_event_timeline/import_window.py @@ -21,10 +21,12 @@ class BonsaiImportFileDlg(BaseWidget): def __init__(self, timeline=None): super(BonsaiImportFileDlg, self).__init__('Import file') - self._file = ControlFile('File to import') - self._fps = ControlNumber('Video FPS', default=30) + self._file = ControlFile('File to import') + self._fps = ControlNumber('Video FPS', default=30) + self._startframe = ControlNumber('Initial frame', visible=False) - self._formset = [('_fps', '_file')] + + self._formset = [('_startframe','_fps', '_file')] #self._file.value = '/home/ricardo/Desktop/rat1e2.csv' @@ -37,11 +39,11 @@ def __init__(self, timeline=None): self._timeline = timeline # Definition of the forms fields - self._filetype = ControlCombo('Please select the type of file you would like to import:') - self._importButton = ControlButton('Import') - self._panel = ControlEmptyWidget('Panel') - self._file = ControlFile('File to import') - + self._filetype = ControlCombo('Please select the type of file you would like to import:') + self._importButton = ControlButton('Import') + self._panel = ControlEmptyWidget('Panel') + self._file = ControlFile('File to import') + self._panel.value = self._file self._filetype.add_item('Events file', 0) self._filetype.add_item('Graph file', 1) @@ -51,7 +53,9 @@ def __init__(self, timeline=None): self._formset = [ ('_filetype', ' '), '_panel', - (' ', '_importButton'), ' '] + (' ', '_importButton'), + ' ' + ] self._filetype.changed_event = self.__fileTypeChanged self._importButton.value = self.__importData @@ -72,8 +76,13 @@ def __fileTypeChanged(self): elif self._filetype.value == 1: self._panel.value = self._graphCsvParserDlg - elif self._filetype.value in [2, 3]: + elif self._filetype.value == 2: + self._panel.value = self._bonsai_import_dlg + self._bonsai_import_dlg._startframe.hide() + + elif self._filetype.value == 3: self._panel.value = self._bonsai_import_dlg + self._bonsai_import_dlg._startframe.show() @@ -193,6 +202,7 @@ def __import_bonsai_events_oldformat(self): points_events = [] first_date = None + initial_frame = int(self._bonsai_import_dlg._startframe.value) open_windows = {} for row in csvfile: @@ -219,7 +229,7 @@ def __import_bonsai_events_oldformat(self): if first_date is None: first_date = cvttime seconds = (cvttime - first_date).total_seconds() - frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) + frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) + initial_frame if eventtype=='PointEvent': points_events.append([eventtype, frame, eventname]) From 77ad7c6ef251be0943e0c8d4684117610ea63008 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 8 Mar 2018 15:23:07 +0000 Subject: [PATCH 54/66] . --- pyforms/gui/controls/control_event_timeline/import_window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyforms/gui/controls/control_event_timeline/import_window.py b/pyforms/gui/controls/control_event_timeline/import_window.py index 749dd22..accc474 100644 --- a/pyforms/gui/controls/control_event_timeline/import_window.py +++ b/pyforms/gui/controls/control_event_timeline/import_window.py @@ -23,7 +23,7 @@ def __init__(self, timeline=None): self._file = ControlFile('File to import') self._fps = ControlNumber('Video FPS', default=30) - self._startframe = ControlNumber('Initial frame', visible=False) + self._startframe = ControlNumber('Initial frame', visible=False, maximum=100000) self._formset = [('_startframe','_fps', '_file')] From db44786ba6b5be290566491d643e895a5628aa66 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 16 Mar 2018 10:31:45 +0000 Subject: [PATCH 55/66] Add import to ControlEventsGraph --- .../gui/controls/control_events_graph/ControlEventsGraph.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py b/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py index 7a686d3..04938ca 100644 --- a/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py +++ b/pyforms/gui/controls/control_events_graph/ControlEventsGraph.py @@ -5,8 +5,7 @@ from pyforms.gui.controls.ControlBase import ControlBase from pyforms.gui.controls.control_events_graph.EventsWidget import EventsWidget from AnyQt.QtWidgets import QWidget, QVBoxLayout, QScrollArea, QScrollBar, QFileDialog -from AnyQt import QtCore - +from AnyQt import QtCore, _api class ControlEventsGraph(ControlBase, QWidget): """ From 81e7c22245280d093c179dac7af30fb2754616f2 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 20 Mar 2018 18:01:56 +0000 Subject: [PATCH 56/66] Fix bugs and add ControlTreeView --- pyforms/__init__.py | 1 + pyforms/gui/basewidget.py | 105 +++++++----- pyforms/gui/controls/ControlBase.py | 10 +- pyforms/gui/controls/ControlCodeEditor.py | 32 +++- pyforms/gui/controls/ControlList.py | 14 +- pyforms/gui/controls/ControlTreeView.py | 189 ++++++++------------- pyforms/gui/controls/code_editor.ui | 68 +++++++- pyforms/gui/controls/list.ui | 194 ++++++++++++++++------ pyforms/gui/settings.py | 1 + 9 files changed, 380 insertions(+), 234 deletions(-) diff --git a/pyforms/__init__.py b/pyforms/__init__.py index 92e6989..ca64213 100644 --- a/pyforms/__init__.py +++ b/pyforms/__init__.py @@ -18,6 +18,7 @@ from pyforms.gui import controls from pyforms.gui.basewidget import BaseWidget from pyforms.gui.appmanager import start_app + from pyforms.gui.basewidget import vsplitter, hsplitter elif conf.PYFORMS_MODE in ['TERMINAL']: diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index c198c9e..d7d35eb 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -20,7 +20,34 @@ from pyforms.gui.controls.ControlBase import ControlBase -from AnyQt.QtWidgets import QMessageBox +from AnyQt.QtWidgets import QMessageBox, QInputDialog + +class vsplitter(object): + def __init__(self, *args, **kwargs): + self.items = args + self.left_width = kwargs.get('left_width', 1) + self.right_width = kwargs.get('right_width', 1) + def __getitem__(self,index): return self.items[index] + def __setitem__(self,index,value): self.items[index] = value + def __len__(self): return len(self.items) + def __iter__(self): + self._index = -1; return self + def __next__(self): + self._index += 1 + if self._index>=len(self.items): raise StopIteration + return self.items[self._index] + +class hsplitter(object): + def __init__(self, *args, **kwargs): self.items = args + def __getitem__(self,index): return self.items[index] + def __setitem__(self,index,value): self.items[index] = value + def __len__(self): return len(self.items) + def __iter__(self): + self._index = -1; return self + def __next__(self): + self._index += 1 + if self._index>=len(self.items): raise StopIteration + return self.items[self._index] class BaseWidget(QFrame): @@ -72,7 +99,6 @@ def init_form(self): """ if not self._formLoaded: - if self._formset is not None: control = self.generate_panel(self._formset) self.layout().addWidget(control) @@ -116,34 +142,26 @@ def generate_panel(self, formset): @type formset: list """ control = None - if '=' in formset: - control = QSplitter(QtCore.Qt.Vertical) - tmp = list(formset) - index = tmp.index('=') - firstPanel = self.generate_panel(formset[0:index]) - secondPanel = self.generate_panel(formset[index + 1:]) - control.addWidget(firstPanel) - control.addWidget(secondPanel) + if '=' in formset or isinstance( formset, hsplitter ): + control = QSplitter(QtCore.Qt.Vertical) + index = list(formset).index('=') + first_panel = self.generate_panel(formset[0:index]) + second_panel = self.generate_panel(formset[index+1:]) + control.addWidget(first_panel) + control.addWidget(second_panel) self._splitters.append(control) return control - elif '||' in formset: - control = QSplitter(QtCore.Qt.Horizontal) - tmp = list(formset) - rindex = lindex = index = tmp.index('||') - rindex -= 1 - rindex += 2 - if isinstance(formset[lindex - 1], int): - lindex = lindex - 1 - if len(formset) > rindex and isinstance(formset[index + 1], int): - rindex += 1 - firstPanel = self.generate_panel(formset[0:lindex]) - secondPanel = self.generate_panel(formset[rindex:]) - if isinstance(formset[index - 1], int): - firstPanel.setMaximumWidth(formset[index - 1]) - if isinstance(formset[index + 1], int): - secondPanel.setMaximumWidth(formset[index + 1]) - control.addWidget(firstPanel) - control.addWidget(secondPanel) + elif '||' in formset or isinstance( formset, vsplitter ): + control = QSplitter(QtCore.Qt.Horizontal) + index = list(formset).index('||') + first_panel = self.generate_panel(formset[0:index]) + second_panel = self.generate_panel(formset[index+1:]) + control.addWidget(first_panel) + control.addWidget(second_panel) + + if isinstance( formset, vsplitter ): + sizes = [formset.left_width, formset.right_width] + control.setSizes(sizes) self._splitters.append(control) return control control = QFrame(self) @@ -151,7 +169,7 @@ def generate_panel(self, formset): if type(formset) is tuple: layout = QHBoxLayout() for row in formset: - if isinstance(row, (list, tuple)): + if isinstance(row, (list, tuple, vsplitter, hsplitter) ): panel = self.generate_panel(row) layout.addWidget(panel) elif row == " ": @@ -224,7 +242,7 @@ def generate_panel(self, formset): elif type(formset) is list: layout = QVBoxLayout() for row in formset: - if isinstance(row, (list, tuple)): + if isinstance(row, (list, tuple, vsplitter, hsplitter) ): panel = self.generate_panel(row) layout.addWidget(panel) elif row == " ": @@ -361,9 +379,17 @@ def close(self): super(BaseWidget, self).close() - def question(self, msg, title=None, ): - reply = QMessageBox.question(self, title, msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) + def input_text(self, msg, title='', default=None): + text, ok = QInputDialog.getText(self, title, msg, text=default) + if ok: + return str(text) + else: + return None + def question(self, msg, title=None, ): + m = QMessageBox(QMessageBox.Question, title, msg, + QMessageBox.Yes | QMessageBox.No) + reply = m.exec() if reply == QMessageBox.Yes or reply == QMessageBox.No: return reply == QMessageBox.Yes else: @@ -371,20 +397,21 @@ def question(self, msg, title=None, ): def message(self, msg, title=None, msg_type=None): if msg_type=='success': - QMessageBox.about(self, title, msg) + m = QMessageBox(QMessageBox.NoIcon, title, msg) elif msg_type=='info': - QMessageBox.information(self, title, msg) + m = QMessageBox(QMessageBox.Information, title, msg) elif msg_type=='warning': - QMessageBox.warning(self, title, msg) + m = QMessageBox(QMessageBox.Warning, title, msg) elif msg_type=='error': - QMessageBox.critical(self, title, msg) + m = QMessageBox(QMessageBox.Critical, title, msg) elif msg_type=='about': - QMessageBox.about(self, title, msg) + m = QMessageBox(QMessageBox.Question, title, msg) elif msg_type=='aboutQt': - QMessageBox.aboutQt(self, msg) + m = QMessageBox(QMessageBox.Question, title, msg) else: - QMessageBox.about(self, title, msg) + m = QMessageBox(QMessageBox.NoIcon, title, msg) + m.exec() def success(self, msg, title=None): self.message(msg, title, msg_type='success') def info(self, msg, title=None): self.message(msg, title, msg_type='info') diff --git a/pyforms/gui/controls/ControlBase.py b/pyforms/gui/controls/ControlBase.py index 92a003f..edc3053 100644 --- a/pyforms/gui/controls/ControlBase.py +++ b/pyforms/gui/controls/ControlBase.py @@ -76,7 +76,10 @@ def show(self): """ if self.form is None: return - self.form.show() + elif self.form==self: + super(ControlBase,self).show() + else: + self.form.show() def hide(self): """ @@ -84,7 +87,10 @@ def hide(self): """ if self.form is None: return - self.form.hide() + elif self.form==self: + super(ControlBase,self).hide() + else: + self.form.hide() def __create_popup_menu(self): diff --git a/pyforms/gui/controls/ControlCodeEditor.py b/pyforms/gui/controls/ControlCodeEditor.py index 9f634d1..2b2c883 100644 --- a/pyforms/gui/controls/ControlCodeEditor.py +++ b/pyforms/gui/controls/ControlCodeEditor.py @@ -40,6 +40,7 @@ def __init__(self, *args, **kwargs): self._changed_func = None super(ControlCodeEditor, self).__init__(*args, **kwargs) + self.discart_event = kwargs.get('discart_event', self.discart_event) def init_form(self): @@ -50,14 +51,19 @@ def init_form(self): control_path = tools.getFileInSameDirectory(__file__, "code_editor.ui") self._form = uic.loadUi(control_path) - self._code_editor = self._form.code_editor + self._code_editor = self._form.code_editor self._save_button = self._form.save_button + self._discart_button = self._form.discart_button + self._save_button.clicked[bool].connect(self.on_save_changes) + self._discart_button.clicked[bool].connect(self.on_discart_changes) + if self._read_only: self._code_editor.setReadOnly(True) self._save_button.setVisible(False) + self._discart_button.setVisible(False) self.form.font_size.addItem('9') self.form.font_size.addItem('10') @@ -74,6 +80,7 @@ def init_form(self): self.form.font_size.currentIndexChanged.connect(self.__font_size_index_changed) self.form.save_button.setIcon(QIcon(conf.PYFORMS_ICON_CODEEDITOR_SAVE)) + self.form.discart_button.setIcon(QIcon(conf.PYFORMS_ICON_CODEEDITOR_DISCART)) self.lexer = QsciLexerPython @@ -179,15 +186,30 @@ def on_modification_changed(self): """ On modification change, re-enable save button """ - if self._changed_func: self._save_button.setEnabled(True) + if self._changed_func: + self._save_button.setEnabled(True) + self._discart_button.setEnabled(True) def on_save_changes(self): """ On button save clicked, save changes made on the code editor to file """ - if self.changed_event() and self._changed_func: + if self.changed_event(): self._code_editor.setModified(False) self._save_button.setEnabled(False) + self._discart_button.setEnabled(False) + + def on_discart_changes(self): + + if self.discart_event(): + self._code_editor.setModified(False) + self._save_button.setEnabled(False) + self._discart_button.setEnabled(False) + + def discart_event(self): + + return True + def _key_pressed(self, event): """ @@ -234,11 +256,11 @@ def value(self): @value.setter def value(self, value): - ControlBase.value.fset(self, value) - if value is not None and len(value) > 0: + if value is not None: self._code_editor.setText(str(value)) self._code_editor.setModified(False) self._save_button.setEnabled(False) + self._discart_button.setEnabled(False) @property def changed_event(self): diff --git a/pyforms/gui/controls/ControlList.py b/pyforms/gui/controls/ControlList.py index 25ab40e..2426a4f 100644 --- a/pyforms/gui/controls/ControlList.py +++ b/pyforms/gui/controls/ControlList.py @@ -43,7 +43,7 @@ def __init__(self, *args, **kwargs): ########################################################################## def init_form(self): - plusFunction = self._plusFunction + plusFunction = self._plusFunction minusFunction = self._minusFunction # Get the current path of the file @@ -53,12 +53,9 @@ def init_form(self): self.label = self._label - self.tableWidget.currentCellChanged.connect( - self.tableWidgetCellChanged) - self.tableWidget.currentItemChanged.connect( - self.tableWidgetItemChanged) - self.tableWidget.itemSelectionChanged.connect( - self.tableWidgetItemSelectionChanged) + self.tableWidget.currentCellChanged.connect(self.tableWidgetCellChanged) + self.tableWidget.currentItemChanged.connect(self.tableWidgetItemChanged) + self.tableWidget.itemSelectionChanged.connect(self.tableWidgetItemSelectionChanged) self.tableWidget.cellDoubleClicked.connect(self.tableWidgetCellDoubleClicked) self.tableWidget.model().dataChanged.connect(self._dataChangedEvent) @@ -66,7 +63,8 @@ def init_form(self): self.tableWidget.horizontalHeader().setVisible(False) if plusFunction is None and minusFunction is None: - self.bottomBar.hide() + self.plusButton.hide() + self.minusButton.hide() elif plusFunction is None: self.plusButton.hide() self.minusButton.pressed.connect(minusFunction) diff --git a/pyforms/gui/controls/ControlTreeView.py b/pyforms/gui/controls/ControlTreeView.py index a164265..0187534 100644 --- a/pyforms/gui/controls/ControlTreeView.py +++ b/pyforms/gui/controls/ControlTreeView.py @@ -3,124 +3,77 @@ from pyforms.gui.controls.ControlBase import ControlBase from AnyQt.QtWidgets import QTreeView, QAbstractItemView -from AnyQt.QtGui import QStandardItem, QStandardItemModel +from AnyQt.QtGui import QStandardItem, QStandardItemModel class ControlTreeView(ControlBase, QTreeView): - def __init__(self, *args, **kwargs): - QTreeView.__init__(self) - ControlBase.__init__(self, *args, **kwargs) - - def init_form(self): - self.setSelectionBehavior(QAbstractItemView.SelectRows) - self.header().hide() - self.setUniformRowHeights(True) - self.setDragDropMode(QAbstractItemView.InternalMove) - self.setDragEnabled(True) - self.setAcceptDrops(True) - - self.setModel(QStandardItemModel()) - self.model().itemChanged.connect(self.__item_changed_event) - - self.selectionChanged = self.selectionChanged - - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # populate data - """ - for i in range(3): - parent1 = QtGui.QStandardItem('Family {}. Some long status text for sp'.format(i)) - for j in range(3): - child1 = QtGui.QStandardItem('Child {}'.format(i*3+j)) - parent1.appendRow(child1) - model().appendRow(parent1) - # span container columns - view.setFirstColumnSpanned(i, view.rootIndex(), True) - """ - - def __item_changed_event(self, item): - self.item_changed_event(item) - - def item_changed_event(self, item): - pass - - def item_selection_changed_event(self): - pass - - def selectionChanged(self, selected, deselected): - super(QTreeView, self.form).selectionChanged(selected, deselected) - self.item_selection_changed_event() - - @property - def mouseSelectedRowsIndexes(self): - result = [] - for index in self.form.selectedIndexes(): - result.append(index.row()) - return list(set(result)) - - @property - def selected_row_index(self): - indexes = self.mouseSelectedRowsIndexes - if len(indexes) > 0: - return indexes[0] - else: - return None - - @property - def selectedItem(self): - for index in self.form.selectedIndexes(): - item = index.model().itemFromIndex(index) - return item - else: - return None - - @property - def cells(self): - results = [] - for row in range(self._model().rowCount()): - r = [] - for col in range(self._model().columnCount()): - r.append(self._model().item(row, col)) - if len(r) > 0: results.append(r) - # print r, '---' - - return results - - def __add__(self, other): - if isinstance(other, TreeItem): - self._model().invisibleRootItem().appendRow(other) - - elif isinstance(other, list): - for x in other: - item = QStandardItem(x) - self._model().appendRow(item) - else: - item = QStandardItem(other) - self._model().appendRow(item) - - self.form.setFirstColumnSpanned(self._model().rowCount() - 1, self.form.rootIndex(), True) - return self - - def __sub__(self, other): - if isinstance(other, int): - if other < 0: - indexToRemove = self.selected_row_index - else: - indexToRemove = other - self.model().removeRow(indexToRemove) - return self - - @property - def value(self): - return self.form.model().invisibleRootItem() - return self.recursivelyReadRoot(root) - - @value.setter - def value(self, value): - for row in value: self += row - - def getAllSceneObjects(self): - return self._model().getChildrens() - - @property - def form(self): - return self + + default_width = None + + def __init__(self, *args, **kwargs): + QTreeView.__init__(self) + ControlBase.__init__(self, *args, **kwargs) + + self.item_selection_changed_event = kwargs.get('item_selection_changed_event', self.item_selection_changed_event) + self.item_double_clicked_event = kwargs.get('item_double_clicked_event', self.item_double_clicked_event) + + def init_form(self): + #self.header().hide() + self.setSelectionBehavior(QAbstractItemView.SelectRows) + self.setUniformRowHeights(True) + #self.setDragDropMode(QAbstractItemView.InternalMove) + #self.setDragEnabled(True) + #self.setAcceptDrops(True) + + self.value = QStandardItemModel() if self._value is None else self._value + self.selectionChanged = self.selectionChanged + + self.mouseDoubleClickEvent = self.__itemDoubleClicked + + def item_selection_changed_event(self, selected, deselected): + pass + + def item_double_clicked_event(self, evt): + pass + + ################################################### + ## OTHER FUNCTIONS ################################ + ################################################### + + def __itemDoubleClicked(self, evt): + self.item_double_clicked_event(evt) + + def selectionChanged(self, selected, deselected): + super(QTreeView, self.form).selectionChanged(selected, deselected) + self.item_selection_changed_event(selected, deselected) + + ################################################### + ## PROPERTIES ##################################### + ################################################### + + @property + def selected_row_index(self): + for index in self.selectedIndexes(): + return index.row() + return None + + @property + def selected_item(self): + for index in self.selectedIndexes(): + res = [] + while index.isValid(): + res.append( index.data() ) + index = index.parent() + return list(reversed(res)) + return None + + @property + def value(self): + return self.model() + + @value.setter + def value(self, value): self.setModel(value) + + + @property + def form(self): return self diff --git a/pyforms/gui/controls/code_editor.ui b/pyforms/gui/controls/code_editor.ui index 95f18bd..bf51fd5 100644 --- a/pyforms/gui/controls/code_editor.ui +++ b/pyforms/gui/controls/code_editor.ui @@ -14,11 +14,23 @@ Form - + + 0 + + + 0 + + + 0 + + 0 + + 2 + @@ -50,19 +62,57 @@ - - - false + + + Qt::Horizontal + + + QSizePolicy::Maximum - - - 0 - 0 - + + + 40 + 10 + + + + + + + + false Save + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + false + + + Discart + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + diff --git a/pyforms/gui/controls/list.ui b/pyforms/gui/controls/list.ui index 3e2ffdf..760ab06 100644 --- a/pyforms/gui/controls/list.ui +++ b/pyforms/gui/controls/list.ui @@ -1,7 +1,7 @@ - Form - + ControlList + 0 @@ -35,17 +35,150 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 - - - TextLabel + + + + 0 + 0 + + + + + 0 + 28 + - - Qt::AlignCenter + + + 16777215 + 28 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 28 + + + + TextLabel + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 0 + + + + + + + + 0 + 0 + + + + + 28 + 28 + + + + + 18 + 75 + true + + + + + + + + + 28 + 28 + + + + true + + + + + + + + 0 + 0 + + + + + 28 + 28 + + + + + 18 + 75 + true + + + + - + + + + 28 + 28 + + + + true + + + + @@ -79,51 +212,6 @@ - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 16 - 16 - - - - - - - - - - - - - 16 - 16 - - - - + - - - - - - diff --git a/pyforms/gui/settings.py b/pyforms/gui/settings.py index 95ade7a..d833613 100644 --- a/pyforms/gui/settings.py +++ b/pyforms/gui/settings.py @@ -21,6 +21,7 @@ def path(filename): state=QIcon.On) PYFORMS_ICON_CODEEDITOR_SAVE = QIcon(qApp.style().standardPixmap(QStyle.SP_DialogSaveButton)) +PYFORMS_ICON_CODEEDITOR_DISCART = QIcon(qApp.style().standardPixmap(QStyle.SP_DialogDiscardButton)) PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_IN = QPixmap(path(os.path.join("Controls", "uipics", "zoom_in.png"))) PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_OUT = QPixmap(path(os.path.join("Controls", "uipics", "zoom_in.png"))) From 5d1b9e282aae33a5f9a6a3df348dc0f49a6931dc Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 27 Mar 2018 17:16:18 +0100 Subject: [PATCH 57/66] Fix bug in the ControlList --- pyforms/gui/controls/ControlList.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyforms/gui/controls/ControlList.py b/pyforms/gui/controls/ControlList.py index 2426a4f..0968a42 100644 --- a/pyforms/gui/controls/ControlList.py +++ b/pyforms/gui/controls/ControlList.py @@ -336,7 +336,7 @@ def label(self): @label.setter def label(self, value): - if value != '': + if value.strip() != '': self.labelWidget.setText(value) else: self.labelWidget.hide() From d6e9b01999ca54f8143ff2bb577eb081a97498a0 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Fri, 30 Mar 2018 23:36:08 +0100 Subject: [PATCH 58/66] Add toolbox --- pyforms/controls.py | 1 + pyforms/gui/appmanager.py | 356 +++++++++++----------- pyforms/gui/basewidget.py | 3 +- pyforms/gui/controls/ControlToolButton.py | 96 ++++++ 4 files changed, 283 insertions(+), 173 deletions(-) create mode 100644 pyforms/gui/controls/ControlToolButton.py diff --git a/pyforms/controls.py b/pyforms/controls.py index 1198a2c..77cdbfa 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -7,6 +7,7 @@ from pyforms.gui.controls.ControlText import ControlText from pyforms.gui.controls.ControlBoundingSlider import ControlBoundingSlider from pyforms.gui.controls.ControlButton import ControlButton + from pyforms.gui.controls.ControlToolButton import ControlToolButton from pyforms.gui.controls.ControlCheckBoxList import ControlCheckBoxList from pyforms.gui.controls.ControlCheckBox import ControlCheckBox from pyforms.gui.controls.ControlCombo import ControlCombo diff --git a/pyforms/gui/appmanager.py b/pyforms/gui/appmanager.py index ae76633..4ad5c7c 100644 --- a/pyforms/gui/appmanager.py +++ b/pyforms/gui/appmanager.py @@ -1,9 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- from pyforms.gui.controls.ControlDockWidget import ControlDockWidget -from AnyQt.QtWidgets import QMainWindow, QDockWidget, QAction, QApplication -from AnyQt import QtCore, _api -from AnyQt.QtGui import QIcon +from AnyQt.QtWidgets import QMainWindow, QDockWidget, QAction, QApplication, QToolBar +from AnyQt import QtCore, _api +from AnyQt.QtGui import QIcon from pyforms.utils.settings_manager import conf import sys, os, platform, logging @@ -11,188 +11,200 @@ logger = logging.getLogger(__name__) class StandAloneContainer(QMainWindow): - def __init__(self, ClassObject): - super(QMainWindow, self).__init__() - - w = ClassObject() - w.app_main_window = self - self._widget = w - - if len(w.mainmenu) > 0: - w._mainmenu = self.__initMainMenu(w.mainmenu) - - w.init_form() - - if _api.USED_API == _api.QT_API_PYQT5: - self.layout().setContentsMargins(conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN) - elif _api.USED_API == _api.QT_API_PYQT4: - self.layout().setMargin(conf.PYFORMS_MAINWINDOW_MARGIN) - - self.setCentralWidget(w) - self.setWindowTitle(w.title) - - docks = {} - for name, item in w.controls.items(): - if isinstance(item, ControlDockWidget): - if item.side not in docks: - docks[item.side] = [] - docks[item.side].append((name, item)) - - for key, widgets in docks.items(): - side = QtCore.Qt.RightDockWidgetArea - if key == 'left': - side = QtCore.Qt.LeftDockWidgetArea - elif key == 'right': - side = QtCore.Qt.RightDockWidgetArea - elif key == 'top': - side = QtCore.Qt.TopDockWidgetArea - elif key == 'bottom': - side = QtCore.Qt.BottomDockWidgetArea - else: - side = QtCore.Qt.LeftDockWidgetArea - - if isinstance(widgets, list): - widgets = sorted(widgets, key=lambda x: x[1].order) - - for name, widget in widgets: - dock = QDockWidget(self) - dock.setFeatures( - QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) - dock.setObjectName(name) - - if _api.USED_API == _api.QT_API_PYQT5: - dock.setContentsMargins(0,0,0,0) - widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) - elif _api.USED_API == _api.QT_API_PYQT4: - dock.setMargin(0) - widget.form.layout().setMargin(widget.margin) - - # print dock.objectName(),1 - dock.setWidget(widget.form) - dock.setWindowTitle(widget.label) - widget.dock = dock - if not widget._show: dock.hide() - - self.addDockWidget(side, dock) - else: - dock = QDockWidget(self) - dock.setFeatures( - QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) - # dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) - - if _api.USED_API == _api.QT_API_PYQT5: - widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) - elif _api.USED_API == _api.QT_API_PYQT5: - widget.form.layout().setMargin(widget.margin) - - # print dock.objectName(), 2 - dock.setObjectName(name) - dock.setWidget(widget.form) - self.addDockWidget(side, dock) - dock.setWindowTitle(widget.label) - widget.dock = dock - if not widget._show: dock.hide() - - if conf.PYFORMS_STYLESHEET: - stylesheet_files = [conf.PYFORMS_STYLESHEET] - - p = platform.system() - if p == 'Windows' and conf.PYFORMS_STYLESHEET_WINDOWS: - stylesheet_files.append(conf.PYFORMS_STYLESHEET_WINDOWS) - elif p == 'Darwin' and conf.PYFORMS_STYLESHEET_DARWIN: - stylesheet_files.append(conf.PYFORMS_STYLESHEET_DARWIN) - elif p == 'Linux' and conf.PYFORMS_STYLESHEET_LINUX: - stylesheet_files.append(conf.PYFORMS_STYLESHEET_LINUX) - - logger.debug('Import stylesheets: {0}'.format(stylesheet_files)) - self.loadStyleSheetFile(stylesheet_files) - - - def closeEvent(self, event): - self._widget.closeEvent(event) - - def __initMainMenu(self, options, keys={}): - menubar = self.menuBar() - for menuIndex, m in enumerate(options): - for key, menus in m.items(): - menu = menubar.addMenu(key) - for subMenuIndex, m1 in enumerate(menus): - if isinstance(m1, str) and m1 == "-": - menu.addSeparator() - else: - for text, func in m1.items(): - if text != 'icon': - action = QAction(text, self) - if 'icon' in m1.keys(): - action.setIconVisibleInMenu(True) - action.setIcon(QIcon(m1['icon'])) - if func: - action.triggered.connect(func) - menu.addAction(action) - options[menuIndex][key][subMenuIndex][text] = action - break - return options - - def loadStyleSheetFile(self, files): - content = '' - for filename in files: - infile = open(filename, 'r') - content += infile.read() + '\n' - infile.close() - - self.setStyleSheet(content) + def __init__(self, ClassObject): + super(QMainWindow, self).__init__() + + w = ClassObject() + w.app_main_window = self + self._widget = w + + if len(w.mainmenu) > 0: + w._mainmenu = self.__initMainMenu(w.mainmenu) + + w.init_form() + + if _api.USED_API == _api.QT_API_PYQT5: + self.layout().setContentsMargins(conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN,conf.PYFORMS_MAINWINDOW_MARGIN) + elif _api.USED_API == _api.QT_API_PYQT4: + self.layout().setMargin(conf.PYFORMS_MAINWINDOW_MARGIN) + + self.setCentralWidget(w) + self.setWindowTitle(w.title) + + docks = {} + for name, item in w.controls.items(): + if isinstance(item, ControlDockWidget): + if item.side not in docks: + docks[item.side] = [] + docks[item.side].append((name, item)) + + #Construct the toolbar + if len(w.toolbar)>0: + tb = QToolBar(self) + self.addToolBar(tb) + for item in w.toolbar: + if isinstance(item, str) and item in ['|','-']: + tb.addSeparator() + else: + tb.addWidget(item.form) + + + for key, widgets in docks.items(): + side = QtCore.Qt.RightDockWidgetArea + if key == 'left': + side = QtCore.Qt.LeftDockWidgetArea + elif key == 'right': + side = QtCore.Qt.RightDockWidgetArea + elif key == 'top': + side = QtCore.Qt.TopDockWidgetArea + elif key == 'bottom': + side = QtCore.Qt.BottomDockWidgetArea + else: + side = QtCore.Qt.LeftDockWidgetArea + + if isinstance(widgets, list): + widgets = sorted(widgets, key=lambda x: x[1].order) + + for name, widget in widgets: + dock = QDockWidget(self) + dock.setFeatures( + QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) + dock.setObjectName(name) + + if _api.USED_API == _api.QT_API_PYQT5: + dock.setContentsMargins(0,0,0,0) + widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) + elif _api.USED_API == _api.QT_API_PYQT4: + dock.setMargin(0) + widget.form.layout().setMargin(widget.margin) + + # print dock.objectName(),1 + dock.setWidget(widget.form) + dock.setWindowTitle(widget.label) + widget.dock = dock + if not widget._show: dock.hide() + + self.addDockWidget(side, dock) + else: + dock = QDockWidget(self) + dock.setFeatures( + QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable) + # dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) + + if _api.USED_API == _api.QT_API_PYQT5: + widget.form.layout().setContentsMargins(widget.margin,widget.margin,widget.margin,widget.margin) + elif _api.USED_API == _api.QT_API_PYQT5: + widget.form.layout().setMargin(widget.margin) + + # print dock.objectName(), 2 + dock.setObjectName(name) + dock.setWidget(widget.form) + self.addDockWidget(side, dock) + dock.setWindowTitle(widget.label) + widget.dock = dock + if not widget._show: dock.hide() + + if conf.PYFORMS_STYLESHEET: + stylesheet_files = [conf.PYFORMS_STYLESHEET] + + p = platform.system() + if p == 'Windows' and conf.PYFORMS_STYLESHEET_WINDOWS: + stylesheet_files.append(conf.PYFORMS_STYLESHEET_WINDOWS) + elif p == 'Darwin' and conf.PYFORMS_STYLESHEET_DARWIN: + stylesheet_files.append(conf.PYFORMS_STYLESHEET_DARWIN) + elif p == 'Linux' and conf.PYFORMS_STYLESHEET_LINUX: + stylesheet_files.append(conf.PYFORMS_STYLESHEET_LINUX) + + logger.debug('Import stylesheets: {0}'.format(stylesheet_files)) + self.loadStyleSheetFile(stylesheet_files) + + + def closeEvent(self, event): + self._widget.closeEvent(event) + + def __initMainMenu(self, options, keys={}): + menubar = self.menuBar() + for menuIndex, m in enumerate(options): + for key, menus in m.items(): + menu = menubar.addMenu(key) + for subMenuIndex, m1 in enumerate(menus): + if isinstance(m1, str) and m1 == "-": + menu.addSeparator() + else: + for text, func in m1.items(): + if text != 'icon': + action = QAction(text, self) + if 'icon' in m1.keys(): + action.setIconVisibleInMenu(True) + action.setIcon(QIcon(m1['icon'])) + if func: + action.triggered.connect(func) + menu.addAction(action) + options[menuIndex][key][subMenuIndex][text] = action + break + return options + + def loadStyleSheetFile(self, files): + content = '' + for filename in files: + infile = open(filename, 'r') + content += infile.read() + '\n' + infile.close() + + self.setStyleSheet(content) def execute_test_file(myapp): - import argparse - parser = argparse.ArgumentParser() - parser.add_argument("test_file", help="File with the tests script") - args = parser.parse_args() + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("test_file", help="File with the tests script") + args = parser.parse_args() - with open(args.test_file) as f: - global_vars = globals() - local_vars = locals() - code = compile(f.read(), args.test_file, 'exec') - exec(code, global_vars, local_vars) + with open(args.test_file) as f: + global_vars = globals() + local_vars = locals() + code = compile(f.read(), args.test_file, 'exec') + exec(code, global_vars, local_vars) -def start_app(ClassObject, geometry=None): - from pyforms.utils.settings_manager import conf +def start_app(ClassObject, geometry=None, stylesheet=None): + from pyforms.utils.settings_manager import conf - app = QApplication(sys.argv) + app = QApplication(sys.argv) - conf += 'pyforms.gui.settings' + conf += 'pyforms.gui.settings' - mainwindow = StandAloneContainer(ClassObject) + mainwindow = StandAloneContainer(ClassObject) - myapp = mainwindow.centralWidget() + myapp = mainwindow.centralWidget() - if geometry is not None: - mainwindow.show() - mainwindow.setGeometry(*geometry) - else: - mainwindow.showMaximized() + if geometry is not None: + mainwindow.show() + mainwindow.setGeometry(*geometry) + else: + mainwindow.showMaximized() - if conf.PYFORMS_QUALITY_TESTS_PATH is not None: - import argparse - parser = argparse.ArgumentParser() - parser.add_argument("--test", help="File with the tests script") - args = parser.parse_args() + if conf.PYFORMS_QUALITY_TESTS_PATH is not None: + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("--test", help="File with the tests script") + args = parser.parse_args() - if args.test: - TEST_PATH = os.path.join(conf.PYFORMS_QUALITY_TESTS_PATH, args.test) - TEST_FILE_PATH = os.path.join(TEST_PATH, args.test + '.py') - DATA_PATH = os.path.join(TEST_PATH, 'data', sys.platform) - INPUT_DATA_PATH = os.path.join(DATA_PATH, 'input-data') - OUTPUT_DATA_PATH = os.path.join(DATA_PATH, 'output-data') - EXPECTED_DATA_PATH = os.path.join(DATA_PATH, 'expected-data') + if args.test: + TEST_PATH = os.path.join(conf.PYFORMS_QUALITY_TESTS_PATH, args.test) + TEST_FILE_PATH = os.path.join(TEST_PATH, args.test + '.py') + DATA_PATH = os.path.join(TEST_PATH, 'data', sys.platform) + INPUT_DATA_PATH = os.path.join(DATA_PATH, 'input-data') + OUTPUT_DATA_PATH = os.path.join(DATA_PATH, 'output-data') + EXPECTED_DATA_PATH = os.path.join(DATA_PATH, 'expected-data') - with open(TEST_FILE_PATH) as f: - global_vars = {} # globals() - local_vars = locals() - code = compile(f.read(), TEST_FILE_PATH, 'exec') + with open(TEST_FILE_PATH) as f: + global_vars = {} # globals() + local_vars = locals() + code = compile(f.read(), TEST_FILE_PATH, 'exec') - exec(code, global_vars, local_vars) + exec(code, global_vars, local_vars) - app.exec_() - return myapp + if stylesheet: app.setStyleSheet(stylesheet) + app.exec_() + return myapp diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index d7d35eb..fbbfbf7 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -80,7 +80,8 @@ def __init__(self, *args, **kwargs): self.title = title self.has_progress = False - self._mainmenu = [] + self.toolbar = [] + self._mainmenu = [] self._splitters = [] self._tabs = [] self._formset = None diff --git a/pyforms/gui/controls/ControlToolButton.py b/pyforms/gui/controls/ControlToolButton.py new file mode 100644 index 0000000..0fd102c --- /dev/null +++ b/pyforms/gui/controls/ControlToolButton.py @@ -0,0 +1,96 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + + +from pyforms.utils.settings_manager import conf + +from AnyQt.QtCore import Qt +from AnyQt import uic +from AnyQt.QtWidgets import QToolButton, QSizePolicy +from AnyQt.QtGui import QIcon + +from pyforms.gui.controls.ControlBase import ControlBase + + +class ControlToolButton(ControlBase): + def __init__(self, *args, **kwargs): + self._checkable = kwargs.get('checkable', False) + self._maxheight = kwargs.get('maxheight', None) + self._maxwidth = kwargs.get('maxwidth', None) + super(ControlToolButton, self).__init__(*args, **kwargs) + + default = kwargs.get('default', None) + if default: self.value = default + + icon = kwargs.get('icon', None) + if icon: self.icon = icon + + + + def init_form(self): + self._form = QToolButton() + if self._maxwidth: self._form.setMaximumWidth(self._maxwidth) + if self._maxheight: self._form.setMaximumHeight(self._maxheight) + self._form.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) + self._form.setCheckable(self._checkable) + self.label = self._label + self._form.setToolTip(self.help) + + def click(self): + self._form.click() + + def load_form(self, data, path=None): + pass + + def save_form(self, data, path=None): + pass + + ########################################################################## + + @property + def label(self): + return ControlBase.label.fget(self) + + @label.setter + def label(self, value): + ControlBase.label.fset(self, value) + if value is None: + self._form.setToolButtonStyle(Qt.ToolButtonIconOnly) + else: + self._form.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self._form.setText(self._label) + + @property + def icon(self): + return self._form.icon() + + @icon.setter + def icon(self, value): + if isinstance(value, (str, bytes)): + self._form.setIcon(QIcon(value)) + else: + self._form.setIcon(value) + + ########################################################################## + + @property + def value(self): + return None + + @value.setter + def value(self, value): + try: + self._form.clicked.disconnect() # ignore previous signals if any + except TypeError as err: + # http://stackoverflow.com/questions/21586643/pyqt-widget-connect-and-disconnect + pass + self._form.clicked[bool].connect(value) + + @property + def checked(self): + return self._form.isChecked() + + @checked.setter + def checked(self, value): + self._form.setChecked(value) From 8e6da45f22589d444812be730b2d2acb5f0f7a50 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 3 Apr 2018 09:45:52 +0100 Subject: [PATCH 59/66] Add input double and input int --- pyforms/gui/basewidget.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index fbbfbf7..6e39bce 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -387,6 +387,22 @@ def input_text(self, msg, title='', default=None): else: return None + def input_double(self, msg, title='', default=None): + text, ok = QInputDialog.getDouble(self, title, msg, text=default) + if ok: + return float(text) + else: + return None + + + def input_int(self, msg, title='', default=None): + text, ok = QInputDialog.getInt(self, title, msg, text=default) + if ok: + return int(text) + else: + return None + + def question(self, msg, title=None, ): m = QMessageBox(QMessageBox.Question, title, msg, QMessageBox.Yes | QMessageBox.No) @@ -434,6 +450,8 @@ def alert_popup(self, msg, title='', buttons=None, handler=None): return self.message_popup(msg, title, buttons, handler, msg_type='alert') + + ########################################################################## ############ GUI functions ############################################### ########################################################################## From 9c6594bd3f6de2a85e507a9a60255d3b2ef8b205 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Wed, 4 Apr 2018 11:17:18 +0100 Subject: [PATCH 60/66] Add ControlTableView --- pyforms/controls.py | 1 + pyforms/gui/controls/ControlTableView.py | 66 ++++++++ pyforms/gui/controls/table-view.ui | 198 +++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 pyforms/gui/controls/ControlTableView.py create mode 100644 pyforms/gui/controls/table-view.ui diff --git a/pyforms/controls.py b/pyforms/controls.py index 77cdbfa..b2d355a 100644 --- a/pyforms/controls.py +++ b/pyforms/controls.py @@ -24,6 +24,7 @@ from pyforms.gui.controls.ControlSlider import ControlSlider from pyforms.gui.controls.ControlTextArea import ControlTextArea from pyforms.gui.controls.ControlToolBox import ControlToolBox + from pyforms.gui.controls.ControlTableView import ControlTableView from pyforms.gui.controls.ControlTree import ControlTree from pyforms.gui.controls.ControlTreeView import ControlTreeView from pyforms.gui.controls.control_event_timeline.ControlEventTimeline import ControlEventTimeline diff --git a/pyforms/gui/controls/ControlTableView.py b/pyforms/gui/controls/ControlTableView.py new file mode 100644 index 0000000..0946a0f --- /dev/null +++ b/pyforms/gui/controls/ControlTableView.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" pyforms.gui.controls.ControlList + +""" +import logging +import os + +from pyforms.utils.settings_manager import conf + +from AnyQt import QtCore, uic +from AnyQt.QtWidgets import QTableView, QAbstractItemView +from AnyQt.QtGui import QIcon + +from pyforms.gui.basewidget import BaseWidget +from pyforms.gui.controls.ControlBase import ControlBase + +logger = logging.getLogger(__name__) + + +class ControlTableView(ControlBase, QTableView): + """ This class represents a wrapper to the table widget + It allows to implement a list view + """ + + CELL_VALUE_BEFORE_CHANGE = None # store value when cell is double clicked + + def __init__(self, *args, **kwargs): + QTableView.__init__(self) + ControlBase.__init__(self, *args, **kwargs) + + if kwargs.get('select_entire_row', False): + self.setSelectionBehavior(QAbstractItemView.SelectRows) + + + ########################################################################## + ############ EVENTS ###################################################### + ########################################################################## + + + ########################################################################## + ############ PROPERTIES ################################################## + ########################################################################## + + + + @property + def value(self): + return self.model() + + @value.setter + def value(self, value): + self.setModel(value) + + + + + @property + def form(self): + return self + + + ########################################################################## + ############ PRIVATE FUNCTIONS ########################################### + ########################################################################## diff --git a/pyforms/gui/controls/table-view.ui b/pyforms/gui/controls/table-view.ui new file mode 100644 index 0000000..3d765ad --- /dev/null +++ b/pyforms/gui/controls/table-view.ui @@ -0,0 +1,198 @@ + + + ControlList + + + + 0 + 0 + 471 + 168 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Form + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 28 + + + + + 16777215 + 28 + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 28 + + + + TextLabel + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 0 + + + + + + + + 0 + 0 + + + + + 28 + 28 + + + + + 18 + 75 + true + + + + + + + + + 28 + 28 + + + + true + + + + + + + + 0 + 0 + + + + + 28 + 28 + + + + + 18 + 75 + true + + + + - + + + + 28 + 28 + + + + true + + + + + + + + + + false + + + Qt::NoPen + + + 0 + + + 100 + + + false + + + true + + + 0 + + + false + + + + + + + + From 35cf7bd8b6bae1cba6a4c9c6f7515dcdb6925a46 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Wed, 4 Apr 2018 11:20:53 +0100 Subject: [PATCH 61/66] Fix bug related with the input_double and input_int --- pyforms/gui/basewidget.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index 6e39bce..c1935d4 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -387,16 +387,15 @@ def input_text(self, msg, title='', default=None): else: return None - def input_double(self, msg, title='', default=None): - text, ok = QInputDialog.getDouble(self, title, msg, text=default) + def input_double(self, msg, title='', default=0, min=-2147483647, max=2147483647, decimals=1): + text, ok = QInputDialog.getDouble(self, title, msg, value=default, min=min, max=max, decimals=decimals) if ok: return float(text) else: return None - - - def input_int(self, msg, title='', default=None): - text, ok = QInputDialog.getInt(self, title, msg, text=default) + + def input_int(self, msg, title='', default=0, min=-2147483647, max=2147483647): + text, ok = QInputDialog.getInt(self, title, msg, value=default, min=min, max=max) if ok: return int(text) else: From 83ccd1be8981f615a93611d85055e425fb8b27db Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 5 Apr 2018 11:14:19 +0100 Subject: [PATCH 62/66] For show widget on ControlEmptyWidget --- pyforms/gui/controls/ControlEmptyWidget.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pyforms/gui/controls/ControlEmptyWidget.py b/pyforms/gui/controls/ControlEmptyWidget.py index 443b6ba..7fb92c1 100644 --- a/pyforms/gui/controls/ControlEmptyWidget.py +++ b/pyforms/gui/controls/ControlEmptyWidget.py @@ -50,9 +50,16 @@ def value(self, value): if isinstance(value, list): for w in value: self.form.layout().addWidget(w.form) + if not hasattr(w, 'about_to_be_shown'): + w.about_to_be_shown = True + w.show() + del w.about_to_be_shown else: self.form.layout().addWidget(value.form) - + if not hasattr(value, 'about_to_be_shown'): + value.about_to_be_shown = True + value.show() + del value.about_to_be_shown # The init_form should be called only for the BaseWidget if isinstance(value, BaseWidget) and not value._formLoaded: From 368f8eb2ef55b9715d105624baac1a02211e9b8a Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 5 Apr 2018 16:25:30 +0100 Subject: [PATCH 63/66] Improve Find plugins errors messages --- pyforms/utils/plugins_finder.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/pyforms/utils/plugins_finder.py b/pyforms/utils/plugins_finder.py index 0fb2b84..7211d26 100644 --- a/pyforms/utils/plugins_finder.py +++ b/pyforms/utils/plugins_finder.py @@ -40,19 +40,21 @@ def find_class(self, class_full_name): class_name = values[-1] module_name = ('.' + '.'.join(values[:-1])) if len(values) > 1 else '' module = __import__(plugin + module_name, fromlist=['']) - class_def = getattr(module, class_name) - res.append(class_def) - except ImportError: + try: + class_def = getattr(module, class_name) + res.append(class_def) + except AttributeError: + if not conf.PYFORMS_SILENT_PLUGINS_FINDER: + logger.error('Error importing model {0} {1} {2}'.format(str(plugin), str(package_name), str(class_name)), exc_info=True) + + except ModuleNotFoundError: if not conf.PYFORMS_SILENT_PLUGINS_FINDER: - logger.error( - 'Error importing model {0} {1} {2}'.format(str(plugin), str(package_name), str(class_name)), - exc_info=True) - pass + logger.error('Error importing model {0} {1} {2}'.format(str(plugin), str(package_name), str(class_name)), exc_info=True) + except: - if not conf.PYFORMS_SILENT_PLUGINS_FINDER: - logger.error( - 'Error importing model {0} {1} {2}'.format(str(plugin), str(package_name), str(class_name)), - exc_info=True) + logger.error( + 'Error importing model {0} {1} {2}'.format(str(plugin), str(package_name), str(class_name)), + exc_info=True) pass return res From 6acc01bbd7a88cadbb62e089f5bb49310164866c Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Thu, 5 Apr 2018 16:48:43 +0100 Subject: [PATCH 64/66] Addd values to combobox --- pyforms/gui/controls/ControlCombo.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyforms/gui/controls/ControlCombo.py b/pyforms/gui/controls/ControlCombo.py index f9f388e..254edd0 100644 --- a/pyforms/gui/controls/ControlCombo.py +++ b/pyforms/gui/controls/ControlCombo.py @@ -155,6 +155,10 @@ def current_index(self): def current_index(self, value): self._combo.setCurrentIndex(value) + @property + def values(self): + return self._items.values() + @property def items(self): return self._items.items() From 81776b0fd705a30c77b186412b7019c846250f74 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Mon, 9 Apr 2018 14:07:09 +0100 Subject: [PATCH 65/66] Fix issue with code editor on windows --- pyforms/gui/controls/ControlTreeView.py | 14 +++++++++----- pyforms/utils/plugins_finder.py | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pyforms/gui/controls/ControlTreeView.py b/pyforms/gui/controls/ControlTreeView.py index 0187534..aec05bb 100644 --- a/pyforms/gui/controls/ControlTreeView.py +++ b/pyforms/gui/controls/ControlTreeView.py @@ -26,9 +26,11 @@ def init_form(self): #self.setAcceptDrops(True) self.value = QStandardItemModel() if self._value is None else self._value - self.selectionChanged = self.selectionChanged + + #self.selectionChanged = self.__selectionChanged + self.mouseDoubleClickEvent = self.__itemDoubleClicked - self.mouseDoubleClickEvent = self.__itemDoubleClicked + self.selectionModel().selectionChanged.connect(self.__selectionChanged) def item_selection_changed_event(self, selected, deselected): pass @@ -43,10 +45,11 @@ def item_double_clicked_event(self, evt): def __itemDoubleClicked(self, evt): self.item_double_clicked_event(evt) - def selectionChanged(self, selected, deselected): - super(QTreeView, self.form).selectionChanged(selected, deselected) + def __selectionChanged(self, selected, deselected): + #def selectionChanged(self, selected, deselected): self.item_selection_changed_event(selected, deselected) - + #super(QTreeView, self.form).selectionChanged(selected, deselected) + ################################################### ## PROPERTIES ##################################### ################################################### @@ -62,6 +65,7 @@ def selected_item(self): for index in self.selectedIndexes(): res = [] while index.isValid(): + print( index.data() ) res.append( index.data() ) index = index.parent() return list(reversed(res)) diff --git a/pyforms/utils/plugins_finder.py b/pyforms/utils/plugins_finder.py index 7211d26..67d7605 100644 --- a/pyforms/utils/plugins_finder.py +++ b/pyforms/utils/plugins_finder.py @@ -47,7 +47,7 @@ def find_class(self, class_full_name): if not conf.PYFORMS_SILENT_PLUGINS_FINDER: logger.error('Error importing model {0} {1} {2}'.format(str(plugin), str(package_name), str(class_name)), exc_info=True) - except ModuleNotFoundError: + except ImportError: if not conf.PYFORMS_SILENT_PLUGINS_FINDER: logger.error('Error importing model {0} {1} {2}'.format(str(plugin), str(package_name), str(class_name)), exc_info=True) From e6a438e9703a3d197d4753584d62b63b86b20db5 Mon Sep 17 00:00:00 2001 From: Ricardo Ribeiro Date: Tue, 10 Apr 2018 14:14:42 +0100 Subject: [PATCH 66/66] update the function question --- pyforms/gui/basewidget.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/pyforms/gui/basewidget.py b/pyforms/gui/basewidget.py index c1935d4..c098193 100644 --- a/pyforms/gui/basewidget.py +++ b/pyforms/gui/basewidget.py @@ -402,14 +402,28 @@ def input_int(self, msg, title='', default=0, min=-2147483647, max=2147483647): return None - def question(self, msg, title=None, ): - m = QMessageBox(QMessageBox.Question, title, msg, - QMessageBox.Yes | QMessageBox.No) + def question(self, msg, title=None, buttons=['no', 'yes']): + btns = None + for btn in buttons: + if btn.lower()=='cancel': + b = QMessageBox.Cancel + elif btn.lower()=='no': + b = QMessageBox.No + elif btn.lower()=='yes': + b = QMessageBox.Yes + + if btns is None: + btns=b + else: btns |= b + + m = QMessageBox(QMessageBox.Question, title, msg, btns) reply = m.exec() - if reply == QMessageBox.Yes or reply == QMessageBox.No: - return reply == QMessageBox.Yes - else: - return None + + if reply==QMessageBox.Cancel: return 'cancel' + elif reply==QMessageBox.No: return 'no' + elif reply==QMessageBox.Yes: return 'yes' + + return None def message(self, msg, title=None, msg_type=None): if msg_type=='success':