瀏覽代碼

Merge branch '84-remove-old-code' into 'master'

Resolve "remove old code"

Closes #84

See merge request troebs/pycs!78
Eric Tröbs 4 年之前
父節點
當前提交
71f7df258b

+ 0 - 26
main.py

@@ -1,26 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-
-from PyQt5 import QtWidgets
-
-from pycs.ui import MainWindow
-
-
-def main(args):
-    app = QtWidgets.QApplication(args)
-    window = MainWindow()
-    window.show()
-
-    if len(args) > 1:
-        window.project_open(args[1])
-    if len(args) > 2:
-        window.predict_via_dialog(args[2:])
-
-    retval = app.exec_()
-    return retval
-
-
-if __name__ == '__main__':
-    retval = main(sys.argv)
-    sys.exit(retval)

+ 0 - 5
pycs/project/__init__.py

@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-"""project:  Encapsulates a project with all its properties."""
-
-from .project import Project

+ 0 - 95
pycs/project/project.py

@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-
-"""project:  Encapsulates a project with all its properties."""
-
-import json
-import os
-
-from pycs.pipeline.tf1 import Pipeline
-from ..utils import Errorable
-from ..utils import Video
-
-
-class Project(Errorable):
-    def __init__(self, project_file, config=None):
-        Errorable.__init__(self)
-        self._update_ui_fn = lambda: None
-
-        new = config is not None
-
-        # (1) Check if directory exists
-        self.__project_file = project_file
-        self.__project_path, self.__project_filename = os.path.split(project_file)
-
-        if not os.path.exists(self.__project_path) and not new:
-            self._report_error("Cannot open directory: %s" % self.__project_path)
-            return
-        elif not os.path.exists(self.__project_path) and new:
-            try:
-                os.mkdir(self.__project_path)
-            except:
-                self._report_error("Cannot create directory: %s" % self.__project_path)
-                return
-
-        # (2) Load project json
-        if new:
-            self._config = config
-        else:
-            try:
-                with open(self.__project_file, 'r') as c:
-                    self._config = json.load(c)
-            except:
-                self._report_error("Cannot open configuration for project: %s" % self.__project_path)
-                return
-
-        # (3) Load detection/extraction pipeline
-        pipeline_config = self._config["pipeline"]
-
-        self._pipeline = Pipeline(pipeline_config)
-        self._err_children += [self._pipeline]
-
-    def save(self):
-        try:
-            with open(self.__project_file, 'w') as c:
-                json.dump(self._config, c, indent=2)
-        except:
-            self._report_error("Cannot save configuration for project: %s" % self.__project_path)
-
-    def execute(self, jobs, callback=lambda progress: True):
-        all_subjobs = []
-        for job in jobs:
-            job['prediction'] = {}
-            job['jobinfo'] = {}
-            for subjob in job['jobs']:
-                if job['filetype'] == 'image':
-                    pipeline_subjob = {'filetype': 'image',
-                                       'filename': job['filename'],
-                                       'prediction': job['prediction'],
-                                       'jobinfo': job['jobinfo'],
-                                       'subjob': subjob}
-                    all_subjobs += [pipeline_subjob]
-                # TODO split video into frames
-                elif job['filetype'] == 'video':
-                    cap = Video(job['filename'])
-                    if cap.framecount > 0:
-                        job['prediction-by-frame'] = [{} for frame in range(cap.framecount)]
-                        job['jobinfo-by-frame'] = [{} for frame in range(cap.framecount)]
-                        for frame in range(cap.framecount):
-                            pipeline_subjob = {'filetype': 'video',
-                                               'cap': cap,
-                                               'frame': frame,
-                                               'filename': job['filename'],
-                                               'prediction': job['prediction-by-frame'][frame],
-                                               'jobinfo': job['jobinfo-by-frame'][frame],
-                                               'subjob': subjob}
-                            all_subjobs += [pipeline_subjob]
-
-        self._pipeline.execute(all_subjobs, callback)
-        callback(1)
-
-    def close(self):
-        self.detector.close()
-        self.features.close()
-
-    def close(self):
-        self._pipeline.close()

+ 0 - 13
pycs/ui/AboutDialog.py

@@ -1,13 +0,0 @@
-#!/usr/bin/env python
-
-import os
-
-from PyQt5 import uic, QtWidgets
-
-
-class AboutDialog(QtWidgets.QDialog):
-    def __init__(self, **kwargs):
-        super(AboutDialog, self).__init__(**kwargs)
-
-        spath = os.path.dirname(__file__)
-        uic.loadUi(os.path.join(spath, 'AboutDialog.ui'), self)

+ 0 - 125
pycs/ui/AboutDialog.ui

@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>AboutDialog</class>
-    <widget class="QDialog" name="AboutDialog">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>582</width>
-                <height>696</height>
-            </rect>
-        </property>
-        <property name="windowTitle">
-            <string>About Carpe Simiam</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout">
-            <item>
-                <layout class="QHBoxLayout" name="horizontalLayout">
-                    <item>
-                        <layout class="QVBoxLayout" name="verticalLayout_2">
-                            <item>
-                                <widget class="QGraphicsView" name="graphicsView">
-                                    <property name="minimumSize">
-                                        <size>
-                                            <width>500</width>
-                                            <height>500</height>
-                                        </size>
-                                    </property>
-                                    <property name="maximumSize">
-                                        <size>
-                                            <width>500</width>
-                                            <height>500</height>
-                                        </size>
-                                    </property>
-                                    <property name="styleSheet">
-                                        <string notr="true">background:transparent</string>
-                                    </property>
-                                    <property name="verticalScrollBarPolicy">
-                                        <enum>Qt::ScrollBarAlwaysOff</enum>
-                                    </property>
-                                    <property name="horizontalScrollBarPolicy">
-                                        <enum>Qt::ScrollBarAlwaysOff</enum>
-                                    </property>
-                                </widget>
-                            </item>
-                            <item>
-                                <widget class="QLabel" name="label">
-                                    <property name="text">
-                                        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;div style=&quot;&quot;&gt;&lt;p&gt;Copyright (C) 2017&lt;br/&gt;Clemens-Alexander
-                                            Brust&lt;br/&gt;Computer Vision Group&lt;br/&gt;Friedrich Schiller University Jena&lt;/p&gt;&lt;p&gt;Carpe Simiam
-                                            uses the following projects:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px;
-                                            margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px;
-                                            margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;https://www.csie.ntu.edu.tw/~cjlin/liblinear/&quot;&gt;&lt;span
-                                            style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;liblinear&lt;/span&gt;&lt;/a&gt; by Chih-Jena Lin
-                                            at National Taiwan University (&lt;a href=&quot;https://www.csie.ntu.edu.tw/~cjlin/liblinear/COPYRIGHT&quot;&gt;&lt;span
-                                            style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;BSD License&lt;/span&gt;&lt;/a&gt;)&lt;br/&gt;&lt;/li&gt;&lt;li
-                                            style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0;
-                                            text-indent:0px;&quot;&gt;&lt;a href=&quot;https://github.com/cvjena/cn24&quot;&gt;&lt;span style=&quot;
-                                            text-decoration: underline; color:#0000ff;&quot;&gt;CN24&lt;/span&gt;&lt;/a&gt; by Clemens-Alexander Brust at
-                                            Friedrich Schiller University Jena (&lt;a href=&quot;https://github.com/cvjena/cn24/blob/master/LICENSE&quot;&gt;&lt;span
-                                            style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;BSD License&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;
-                                            &lt;/div&gt;
-                                            &lt;/body&gt;&lt;/html&gt;
-                                        </string>
-                                    </property>
-                                    <property name="alignment">
-                                        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-                                    </property>
-                                    <property name="wordWrap">
-                                        <bool>true</bool>
-                                    </property>
-                                </widget>
-                            </item>
-                        </layout>
-                    </item>
-                </layout>
-            </item>
-            <item>
-                <widget class="QDialogButtonBox" name="buttonBox">
-                    <property name="orientation">
-                        <enum>Qt::Horizontal</enum>
-                    </property>
-                    <property name="standardButtons">
-                        <set>QDialogButtonBox::Close</set>
-                    </property>
-                </widget>
-            </item>
-        </layout>
-    </widget>
-    <resources/>
-    <connections>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>accepted()</signal>
-            <receiver>AboutDialog</receiver>
-            <slot>accept()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>248</x>
-                    <y>254</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>157</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>rejected()</signal>
-            <receiver>AboutDialog</receiver>
-            <slot>reject()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>316</x>
-                    <y>260</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>286</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-    </connections>
-</ui>

+ 0 - 91
pycs/ui/AnnotatedImageView.py

@@ -1,91 +0,0 @@
-"""AnnotatedImageView:  Displays images with bounding boxes etc."""
-
-from PyQt5 import QtWidgets, QtGui, QtCore
-
-from ..utils import Video
-
-
-class AnnotatedImageView(QtWidgets.QGraphicsView):
-    def __init__(self, parent):
-        super(AnnotatedImageView, self).__init__(parent=parent)
-
-        self._scene = QtWidgets.QGraphicsScene()
-        self.setScene(self._scene)
-
-        self._rect = QtCore.QRectF(0, 0, 0, 0)
-
-        self.setRenderHint(QtGui.QPainter.Antialiasing)
-
-        self._image = None
-        self._current_video = None
-
-    def display(self, prediction, mode='prediction'):
-        self._scene.clear()
-        if prediction['filetype'] == 'image':
-            self._image = QtGui.QImage(prediction['filename'])
-            item = QtWidgets.QGraphicsPixmapItem(QtGui.QPixmap.fromImage(self._image))
-            self._scene.addItem(item)
-            self._scene.setSceneRect(item.boundingRect())
-            self._rect = item.boundingRect()
-
-            if mode in prediction.keys():
-                self._overlay(prediction[mode])
-
-        elif prediction['filetype'] == 'video':
-            if 'cap' in prediction.keys():
-                cap = prediction['cap']
-            else:
-                cap = Video(prediction['filename'])
-
-            if 'frame' in prediction.keys():
-                frame = prediction['frame']
-            else:
-                frame = 0
-
-            video_frame = cap.get_frame(frame)
-            if video_frame is not None:
-                self._image = QtGui.QImage(video_frame,
-                                           video_frame.shape[1], video_frame.shape[0],
-                                           video_frame.shape[2] * video_frame.shape[1], QtGui.QImage.Format_RGB888)
-
-                item = QtWidgets.QGraphicsPixmapItem(QtGui.QPixmap.fromImage(self._image))
-                self._scene.addItem(item)
-                self._scene.setSceneRect(item.boundingRect())
-                self._rect = item.boundingRect()
-
-                if 'prediction-by-frame' in prediction.keys():
-                    self._overlay(prediction['prediction-by-frame'][frame])
-
-        self.refit_display()
-
-    def _overlay(self, prediction):
-        if 'faces' in prediction.keys():
-            self._overlay_faces(prediction['faces'])
-
-    def _overlay_faces(self, faces):
-        box_background = QtGui.QColor(255, 255, 255, 51)
-        box_border = QtGui.QColor(0, 0, 0, 1)
-        width = float(self._image.width())
-        height = float(self._image.height())
-
-        for face in faces:
-            self._scene.addRect(face['x'] * width, face['y'] * height, face['w'] * width, face['h'] * height,
-                                QtGui.QPen(QtGui.QBrush(box_border), 3.0),
-                                QtGui.QBrush(box_background))
-
-    def refit_display(self):
-        if self._rect is None:
-            self.resetTransform()
-        else:
-            self.fitInView(self._rect, QtCore.Qt.KeepAspectRatio)
-
-    def resizeEvent(self, event: QtGui.QResizeEvent):
-        self.refit_display()
-        QtWidgets.QGraphicsView.resizeEvent(self, event)
-
-    def reset(self):
-        self._scene.clear()
-        self._image = None
-        self._current_video = None
-        self._rect = None
-        # TODO display context action

+ 0 - 52
pycs/ui/AnnotatedInteractiveImageView.py

@@ -1,52 +0,0 @@
-from pycs.ui.AnnotatedImageView import AnnotatedImageView
-
-
-class AnnotatedInteractiveImageView(AnnotatedImageView):
-    def __init__(self, parent, click_handler=None):
-        super().__init__(parent)
-        self.__click_handler = click_handler
-
-    def mousePressEvent(self, event):
-        """
-        handle click event, get point and emit to parent node
-        :param event:
-        :return:
-        """
-
-        # do not execute if no click handler is given
-        if self.__click_handler is None:
-            return
-
-        # get clicked point
-        pos = event.pos()
-        point_x, point_y = pos.x() / self.width(), pos.y() / self.height()
-
-        # get image and box dimensions
-        image_width, image_height = self._image.width(), self._image.height()
-        box_width, box_height = self.width(), self.height()
-
-        maximum_width, maximum_height = max(image_width, box_width), max(image_height, box_height)
-
-        # determine orientation
-        # horizontal
-        if image_width / image_height >= box_width / box_height:
-            # calculate top margin
-            image_height, box_height = maximum_width / image_width * image_height, maximum_width / box_width * box_height
-            top = (box_height - image_height) / 2
-
-            # click is inside the image
-            if top <= point_y * box_height <= box_height - top:
-                off = top / box_height
-                rat = 1 - 2 * off
-                self.__click_handler(point_x, (point_y - off) / rat, event)
-
-        # vertical
-        else:
-            # calculate left margin
-            image_width, box_width = maximum_height / image_height * image_width, maximum_height / box_height * box_width
-            left = (box_width - image_width) / 2
-
-            if left <= point_x * box_width <= box_width - left:
-                off = left / box_width
-                rat = 1 - 2 * off
-                self.__click_handler((point_x - off) / rat, point_y, event)

+ 0 - 117
pycs/ui/ChimpManagementDialog.ui

@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>ChimpManagementDialog</class>
-    <widget class="QDialog" name="ChimpManagementDialog">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>512</width>
-                <height>443</height>
-            </rect>
-        </property>
-        <property name="windowTitle">
-            <string>Manage Individuals</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout">
-            <item>
-                <widget class="QTableWidget" name="individualTable">
-                    <property name="cornerButtonEnabled">
-                        <bool>false</bool>
-                    </property>
-                    <attribute name="verticalHeaderVisible">
-                        <bool>false</bool>
-                    </attribute>
-                    <column>
-                        <property name="text">
-                            <string>Name</string>
-                        </property>
-                    </column>
-                    <column>
-                        <property name="text">
-                            <string>Age</string>
-                        </property>
-                    </column>
-                    <column>
-                        <property name="text">
-                            <string>Age Group</string>
-                        </property>
-                    </column>
-                    <column>
-                        <property name="text">
-                            <string>Gender</string>
-                        </property>
-                    </column>
-                    <column>
-                        <property name="text">
-                            <string># Ex.</string>
-                        </property>
-                    </column>
-                </widget>
-            </item>
-            <item>
-                <layout class="QHBoxLayout" name="horizontalLayout">
-                    <item>
-                        <widget class="QPushButton" name="addButton">
-                            <property name="text">
-                                <string>Add Individual</string>
-                            </property>
-                        </widget>
-                    </item>
-                    <item>
-                        <widget class="QPushButton" name="deleteButton">
-                            <property name="text">
-                                <string>Delete Individual</string>
-                            </property>
-                        </widget>
-                    </item>
-                    <item>
-                        <widget class="QDialogButtonBox" name="buttonBox">
-                            <property name="orientation">
-                                <enum>Qt::Horizontal</enum>
-                            </property>
-                            <property name="standardButtons">
-                                <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-                            </property>
-                        </widget>
-                    </item>
-                </layout>
-            </item>
-        </layout>
-    </widget>
-    <resources/>
-    <connections>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>accepted()</signal>
-            <receiver>ChimpManagementDialog</receiver>
-            <slot>accept()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>248</x>
-                    <y>254</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>157</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>rejected()</signal>
-            <receiver>ChimpManagementDialog</receiver>
-            <slot>reject()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>316</x>
-                    <y>260</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>286</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-    </connections>
-</ui>

+ 0 - 97
pycs/ui/LabelDialog.py

@@ -1,97 +0,0 @@
-import os
-
-from PyQt5 import uic, QtWidgets, QtCore
-
-from pycs.ui.AnnotatedInteractiveImageView import AnnotatedInteractiveImageView
-
-
-class LabelDialog(QtWidgets.QDialog):
-    def __init__(self, predictions, **kwargs):
-        # call parent constructor
-        super(LabelDialog, self).__init__(**kwargs)
-
-        # handle properties
-        self.__predictions = predictions
-        self.__current = -1
-
-        # load ui
-        spath = os.path.dirname(__file__)
-        uic.loadUi(os.path.join(spath, 'LabelDialog.ui'), self)
-
-        self.button_next.clicked.connect(self._next)
-        self.button_previous.clicked.connect(self._prev)
-
-        # add annotated image view
-        self.__image = AnnotatedInteractiveImageView(self, self.click)
-        self.gridLayout.addWidget(self.__image)
-
-        # call next image function to display first item
-        self._next()
-
-    def _next(self):
-        """
-        displays next item
-        """
-        if len(self.__predictions) > 0:
-            self.__current += 1
-            if self.__current >= len(self.__predictions):
-                self.__current = 0
-
-            self.__image.display(self.__predictions[self.__current])
-
-    def _prev(self):
-        """
-        displays previous item
-        """
-        if len(self.__predictions) > 0:
-            self.__current -= 1
-            if self.__current <= 0:
-                self.__current = len(self.__predictions) - 1
-
-            self.__image.display(self.__predictions[self.__current])
-
-    def click(self, x, y, event):
-        """
-        handles clicks on images
-        :param x: x position in [0, 1]
-        :param y: y position in [0, 1]
-        :param event: actual QMouseEvent object
-        """
-
-        # return if there is no prediction
-        if len(self.__predictions) == 0:
-            return
-
-        # add label object to current prediction
-        if 'label' not in self.__predictions[self.__current].keys():
-            self.__predictions[self.__current]['label'] = {
-                'faces': [{
-                    'x1': None,
-                    'y1': None,
-                    'x2': None,
-                    'y2': None
-                }]
-            }
-
-        face = self.__predictions[self.__current]['label']['faces'][0]
-
-        # set data depending on click
-        if event.button() == QtCore.Qt.LeftButton:
-            face['x1'] = x
-            face['y1'] = y
-        elif event.button() == QtCore.Qt.RightButton:
-            face['x2'] = x
-            face['y2'] = y
-
-        # return if not at least two points selected
-        if face['x1'] is None or face['y1'] is None or face['x2'] is None or face['y2'] is None:
-            return
-
-        # detect upper left point and calculate width and height
-        face['x'] = min(face['x1'], face['x2'])
-        face['y'] = min(face['y1'], face['y2'])
-        face['w'] = max(face['x1'], face['x2']) - face['x']
-        face['h'] = max(face['y1'], face['y2']) - face['y']
-
-        # display rectangle
-        self.__image.display(self.__predictions[self.__current], mode='label')

+ 0 - 56
pycs/ui/LabelDialog.ui

@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>AboutDialog</class>
-    <widget class="QDialog" name="AboutDialog">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>582</width>
-                <height>703</height>
-            </rect>
-        </property>
-        <property name="windowTitle">
-            <string>Labeling Session</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
-            <item>
-                <layout class="QGridLayout" name="gridLayout"/>
-            </item>
-            <item>
-                <layout class="QHBoxLayout" name="horizontalLayout">
-                    <item>
-                        <widget class="QPushButton" name="button_previous">
-                            <property name="text">
-                                <string>Voriges</string>
-                            </property>
-                        </widget>
-                    </item>
-                    <item>
-                        <widget class="QPushButton" name="button_ok">
-                            <property name="text">
-                                <string>OK</string>
-                            </property>
-                        </widget>
-                    </item>
-                    <item>
-                        <widget class="QPushButton" name="button_cancel">
-                            <property name="text">
-                                <string>Abbrechen</string>
-                            </property>
-                        </widget>
-                    </item>
-                    <item>
-                        <widget class="QPushButton" name="button_next">
-                            <property name="text">
-                                <string>Nächstes</string>
-                            </property>
-                        </widget>
-                    </item>
-                </layout>
-            </item>
-        </layout>
-    </widget>
-    <resources/>
-    <connections/>
-</ui>

+ 0 - 259
pycs/ui/LabelSessionDialog.ui

@@ -1,259 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>LabelSessionDialog</class>
-    <widget class="QDialog" name="LabelSessionDialog">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>587</width>
-                <height>412</height>
-            </rect>
-        </property>
-        <property name="windowTitle">
-            <string>Label Images</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout">
-            <item>
-                <widget class="QGroupBox" name="filesBox">
-                    <property name="title">
-                        <string>Images</string>
-                    </property>
-                    <layout class="QVBoxLayout" name="verticalLayout_2">
-                        <item>
-                            <widget class="QListWidget" name="filesList"/>
-                        </item>
-                        <item>
-                            <layout class="QHBoxLayout" name="horizontalLayout">
-                                <item>
-                                    <widget class="QPushButton" name="removeButton">
-                                        <property name="text">
-                                            <string>Remove Image</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="list-remove">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <widget class="QPushButton" name="addVideoButton">
-                                        <property name="enabled">
-                                            <bool>true</bool>
-                                        </property>
-                                        <property name="text">
-                                            <string>Add Video...</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="video-x-generic">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <widget class="QPushButton" name="addImagesButton">
-                                        <property name="text">
-                                            <string>Add Images...</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="list-add">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                            </layout>
-                        </item>
-                    </layout>
-                </widget>
-            </item>
-            <item>
-                <widget class="QGroupBox" name="paramsBox">
-                    <property name="title">
-                        <string>Settings</string>
-                    </property>
-                    <layout class="QFormLayout" name="formLayout">
-                        <item row="0" column="0">
-                            <widget class="QLabel" name="detectionThresholdLabel">
-                                <property name="text">
-                                    <string>Detection Threshold</string>
-                                </property>
-                            </widget>
-                        </item>
-                        <item row="2" column="0">
-                            <widget class="QLabel" name="unknownLabel">
-                                <property name="text">
-                                    <string>Unknown Individual Threshold</string>
-                                </property>
-                            </widget>
-                        </item>
-                        <item row="0" column="1">
-                            <layout class="QVBoxLayout" name="verticalLayout_3">
-                                <item>
-                                    <widget class="QSlider" name="detectionThresholdSlider">
-                                        <property name="minimum">
-                                            <number>0</number>
-                                        </property>
-                                        <property name="maximum">
-                                            <number>100</number>
-                                        </property>
-                                        <property name="orientation">
-                                            <enum>Qt::Horizontal</enum>
-                                        </property>
-                                        <property name="invertedAppearance">
-                                            <bool>false</bool>
-                                        </property>
-                                        <property name="tickPosition">
-                                            <enum>QSlider::TicksBelow</enum>
-                                        </property>
-                                        <property name="tickInterval">
-                                            <number>5</number>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <layout class="QHBoxLayout" name="horizontalLayout_2">
-                                        <item>
-                                            <widget class="QLabel" name="label">
-                                                <property name="text">
-                                                    <string>Low</string>
-                                                </property>
-                                            </widget>
-                                        </item>
-                                        <item>
-                                            <spacer name="horizontalSpacer">
-                                                <property name="orientation">
-                                                    <enum>Qt::Horizontal</enum>
-                                                </property>
-                                                <property name="sizeHint" stdset="0">
-                                                    <size>
-                                                        <width>40</width>
-                                                        <height>20</height>
-                                                    </size>
-                                                </property>
-                                            </spacer>
-                                        </item>
-                                        <item>
-                                            <widget class="QLabel" name="label_3">
-                                                <property name="text">
-                                                    <string>High</string>
-                                                </property>
-                                            </widget>
-                                        </item>
-                                    </layout>
-                                </item>
-                            </layout>
-                        </item>
-                        <item row="2" column="1">
-                            <layout class="QVBoxLayout" name="verticalLayout_4">
-                                <item>
-                                    <widget class="QSlider" name="unknownSlider">
-                                        <property name="minimum">
-                                            <number>0</number>
-                                        </property>
-                                        <property name="maximum">
-                                            <number>100</number>
-                                        </property>
-                                        <property name="singleStep">
-                                            <number>1</number>
-                                        </property>
-                                        <property name="pageStep">
-                                            <number>10</number>
-                                        </property>
-                                        <property name="orientation">
-                                            <enum>Qt::Horizontal</enum>
-                                        </property>
-                                        <property name="tickPosition">
-                                            <enum>QSlider::TicksBelow</enum>
-                                        </property>
-                                        <property name="tickInterval">
-                                            <number>5</number>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <layout class="QHBoxLayout" name="horizontalLayout_3">
-                                        <item>
-                                            <widget class="QLabel" name="label_2">
-                                                <property name="text">
-                                                    <string>Low</string>
-                                                </property>
-                                            </widget>
-                                        </item>
-                                        <item>
-                                            <spacer name="horizontalSpacer_2">
-                                                <property name="orientation">
-                                                    <enum>Qt::Horizontal</enum>
-                                                </property>
-                                                <property name="sizeHint" stdset="0">
-                                                    <size>
-                                                        <width>40</width>
-                                                        <height>20</height>
-                                                    </size>
-                                                </property>
-                                            </spacer>
-                                        </item>
-                                        <item>
-                                            <widget class="QLabel" name="label_4">
-                                                <property name="text">
-                                                    <string>High</string>
-                                                </property>
-                                            </widget>
-                                        </item>
-                                    </layout>
-                                </item>
-                            </layout>
-                        </item>
-                    </layout>
-                </widget>
-            </item>
-            <item>
-                <widget class="QDialogButtonBox" name="buttonBox">
-                    <property name="orientation">
-                        <enum>Qt::Horizontal</enum>
-                    </property>
-                    <property name="standardButtons">
-                        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-                    </property>
-                </widget>
-            </item>
-        </layout>
-    </widget>
-    <resources/>
-    <connections>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>accepted()</signal>
-            <receiver>LabelSessionDialog</receiver>
-            <slot>accept()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>248</x>
-                    <y>254</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>157</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>rejected()</signal>
-            <receiver>LabelSessionDialog</receiver>
-            <slot>reject()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>316</x>
-                    <y>260</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>286</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-    </connections>
-</ui>

+ 0 - 117
pycs/ui/LabeledImagesDialog.ui

@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>LabeledImagesDialog</class>
-    <widget class="QDialog" name="LabeledImagesDialog">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>855</width>
-                <height>590</height>
-            </rect>
-        </property>
-        <property name="sizePolicy">
-            <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-            </sizepolicy>
-        </property>
-        <property name="windowTitle">
-            <string>Dialog</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout_2">
-            <item>
-                <layout class="QHBoxLayout" name="horizontalLayout_2">
-                    <item>
-                        <widget class="QGroupBox" name="groupBox">
-                            <property name="title">
-                                <string>Status</string>
-                            </property>
-                            <layout class="QHBoxLayout" name="horizontalLayout">
-                                <item>
-                                    <widget class="QTextBrowser" name="logText"/>
-                                </item>
-                            </layout>
-                        </widget>
-                    </item>
-                    <item>
-                        <layout class="QVBoxLayout" name="verticalLayout">
-                            <item>
-                                <widget class="QPushButton" name="importIndividualsButton">
-                                    <property name="text">
-                                        <string>Import Individuals</string>
-                                    </property>
-                                </widget>
-                            </item>
-                            <item>
-                                <widget class="QPushButton" name="processSamplesButton">
-                                    <property name="text">
-                                        <string>Process Samples</string>
-                                    </property>
-                                </widget>
-                            </item>
-                            <item>
-                                <spacer name="verticalSpacer">
-                                    <property name="orientation">
-                                        <enum>Qt::Vertical</enum>
-                                    </property>
-                                    <property name="sizeHint" stdset="0">
-                                        <size>
-                                            <width>20</width>
-                                            <height>40</height>
-                                        </size>
-                                    </property>
-                                </spacer>
-                            </item>
-                        </layout>
-                    </item>
-                </layout>
-            </item>
-            <item>
-                <widget class="QDialogButtonBox" name="buttonBox">
-                    <property name="orientation">
-                        <enum>Qt::Horizontal</enum>
-                    </property>
-                    <property name="standardButtons">
-                        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-                    </property>
-                </widget>
-            </item>
-        </layout>
-    </widget>
-    <resources/>
-    <connections>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>accepted()</signal>
-            <receiver>LabeledImagesDialog</receiver>
-            <slot>accept()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>248</x>
-                    <y>254</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>157</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>rejected()</signal>
-            <receiver>LabeledImagesDialog</receiver>
-            <slot>reject()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>316</x>
-                    <y>260</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>286</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-    </connections>
-</ui>

+ 0 - 335
pycs/ui/MainWindow.py

@@ -1,335 +0,0 @@
-import json
-import os
-
-from PyQt5 import uic, QtWidgets, QtCore, QtGui
-
-from . import AboutDialog
-from .LabelDialog import LabelDialog
-from .NewProjectWizard import NewProjectWizard
-from ..project import Project
-from ..utils import Video
-
-
-class MainWindow:
-    # Properties
-    def _set_project(self, project):
-        self.__project = project
-        if project is not None:
-            project._update_ui_fn = lambda: self._update_ui()
-        self._update_ui()
-
-    def _get_project(self):
-        return self.__project
-
-    _project = property(fget=_get_project, fset=_set_project)
-
-    def _has_project(self):
-        if self.__project is not None:
-            return True
-        else:
-            return False
-
-    def _set_predictions(self, predictions):
-        self.__predictions = predictions
-        self._update_prediction_ui()
-
-    def _get_predictions(self):
-        return self.__predictions
-
-    _predictions = property(fget=_get_predictions, fset=_set_predictions)
-
-    def _project_needs_saving(self):
-        return True
-
-    # Constructor
-    def __init__(self, **kwargs):
-        # initialize window
-        self.ui = QtWidgets.QMainWindow(**kwargs)
-
-        # set object properties
-        self.__project = None
-        self.__predictions = []
-
-        # load ui from corresponding file
-        spath = os.path.dirname(__file__)
-        uic.loadUi(os.path.join(spath, 'MainWindow.ui'), self.ui)
-
-        # prepare some more ui stuff
-        self.ui.statusLabel = QtWidgets.QLabel(self.ui)
-        self.ui.statusBar.addPermanentWidget(self.ui.statusLabel)
-
-        self.ui.timerThread = QtCore.QThread(self.ui)
-
-        self.ui.timer = QtCore.QTimer()
-        self.ui.timer.setInterval(2000)
-        self.ui.timer.moveToThread(self.ui.timerThread)
-
-        # connect actions
-        # File
-        self.ui.actionNew.triggered.connect(self._project_new)
-        self.ui.actionOpen.triggered.connect(self.project_open)
-        self.ui.actionClose.triggered.connect(self._project_try_closing)
-        self.ui.actionSave.triggered.connect(self._project_save)
-        self.ui.actionQuit.triggered.connect(self._file_quit)
-
-        # Labeling
-        self.ui.actionStart_Labeling_Session.triggered.connect(self._start_labeling_session)
-        self.ui.startLabelingSessionButton.clicked.connect(self._start_labeling_session)
-
-        # Help
-        self.ui.actionAbout.triggered.connect(self._help_about)
-
-        self.ui.actionPredict_Images.triggered.connect(self.predict_via_dialog)
-        self.ui.predictButton.clicked.connect(self.predict_via_dialog)
-
-        self.ui.imageThumbnailGallery.currentRowChanged.connect(self._prediction_row_changed)
-
-        self._update_ui()
-        self._update_prediction_ui()
-
-        # TODO delete me
-        # self._project = Project('test-project')
-
-    def _update_ui(self):
-        # Status text
-        if self._has_project():
-            status_text = "OK"
-            if self._project.last_error is not None:
-                status_text = self._project.last_error
-        else:
-            status_text = "No project loaded."
-
-        self.ui.pipelineStatusLabel.setText(status_text)
-
-        # Action availability
-        project_only_actions = [self.ui.actionSave,
-                                self.ui.actionSave_As,
-                                self.ui.actionClose,
-                                self.ui.actionImport_Labeled_Faces,
-                                self.ui.actionImport_Labeled_Images,
-                                self.ui.startLabelingSessionButton,
-                                self.ui.actionStart_Labeling_Session,
-                                self.ui.actionManage_Individuals,
-                                self.ui.actionPredict_Images,
-                                self.ui.predictButton,
-                                self.ui.actionUpdate_Model,
-                                self.ui.updateButton,
-                                self.ui.actionValidate_Model,
-                                self.ui.clearPredictionsButton,
-                                self.ui.exportCSVButton]
-
-        for action in project_only_actions:
-            action.setEnabled(self._has_project())
-
-    def show(self):
-        return self.ui.show()
-
-    #####################
-    # Project lifecycle #
-    #####################
-    def _project_try_closing(self):
-        if self._has_project():
-            if self._project_needs_saving():
-                # Ask user
-                box = QtWidgets.QMessageBox()
-                box.setText('The current project has unsaved changes. Would you like to save them?')
-                box.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Cancel)
-                retval = box.exec_()
-                if retval == QtWidgets.QMessageBox.Yes:
-                    self._project.save()
-                    if self._project.last_error is not None:
-                        error_string = self._project.last_error
-                        QtWidgets.QMessageBox.warning(self.ui, 'Error', 'Error while saving (see log for details): %s'
-                                                      % error_string)
-                        self._project.reset_error()
-                        return False
-                elif retval == QtWidgets.QMessageBox.No:
-                    pass
-                elif retval == QtWidgets.QMessageBox.Cancel:
-                    return False
-
-            self._project.close()
-            self._project = None
-            return True
-        else:
-            return True
-
-    def _project_new(self):
-        retval = self._project_try_closing()
-        if retval:
-            w = NewProjectWizard(self.ui)
-            w_retval = w.exec_()
-            if w_retval:
-                self._project = Project(w.project_root, w.project_config)
-
-    def project_open(self, path=False):
-        """
-        opens a project by either using the optional parameter path or
-        or the value the user enters using the ui file dialog
-
-        :param path: path to project.json
-        """
-
-        # check if there is an open project with unsaved changes
-        retval = self._project_try_closing()
-        if not retval:
-            return
-
-        # copy path to selection or question user if not given
-        if path is not False:
-            selection = path
-        else:
-            selection, _ = QtWidgets.QFileDialog.getOpenFileName(self.ui, 'Select Project Folder', filter='project.json')
-
-        # check if path exists and open project
-        if len(selection) > 0 and os.path.exists(selection):
-            self._project = Project(selection)
-            if self._project.last_error is not None:
-                error_string = self._project.last_error
-                try:
-                    QtWidgets.QMessageBox.warning(self.ui, 'Error', 'Error while opening (see log for details): %s'
-                                                  % error_string)
-                    self._project.close()
-                except:
-                    pass
-                self._project = None
-        elif len(selection) > 0:  # Project file does not exist
-            QtWidgets.QMessageBox.warning(self.ui, 'Error', 'Could not find project file: %s' % selection)
-
-    def _project_save(self):
-        self._project.save()
-        if self._project.last_error is not None:
-            error_string = self._project.last_error
-            QtWidgets.QMessageBox.warning(self.ui, 'Error', 'Error while saving (see log for details): %s'
-                                          % error_string)
-            self._project.reset_error()
-
-    def _file_quit(self):
-        # TODO: warning if there are any unsaved changes
-        self.close()
-
-    def _start_labeling_session(self):
-        labeling = LabelDialog(self._predictions)
-        labeling.exec_()
-
-    def _help_about(self):
-        about = AboutDialog()
-        about.exec_()
-
-    #####################################
-    # Prediction actions and management #
-    #####################################
-    def predict_via_dialog(self, selection=False):
-        """
-        loads images from given paths or ui file dialog
-        :param selection: array of image paths
-        :return:
-        """
-
-        # valid image and video extensions
-        image_extensions = ['.jpg', '.png', '.jpeg']
-        video_extensions = ['.mp4', '.avi', '.mkv', '.mpg', '.mpeg']
-
-        # ask user for input
-        if selection is False:
-            name_list = ' '.join(['*' + extension for extension in image_extensions + video_extensions])
-            extensions = f'All supported files ({name_list})'
-
-            selection, _ = QtWidgets.QFileDialog.getOpenFileNames(self.ui, 'Select Files To Add', filter=extensions)
-
-        # load jobs
-        jobs = []
-
-        for filename in selection:
-            _, extension = os.path.splitext(filename)
-            extension = extension.lower()
-
-            if extension in image_extensions:
-                jobs.append({
-                    'filename': filename,
-                    'filetype': 'image',
-                    'jobs': ['detect-faces']
-                })
-            elif extension in video_extensions:
-                jobs.append({
-                    'filename': filename,
-                    'filetype': 'image',
-                    'jobs': ['detect-faces']
-                })
-
-        progress_dialog = QtWidgets.QProgressDialog('Executing prediction jobs...', 'Abort', 0, 1000, self.ui)
-        progress_dialog.setWindowModality(QtCore.Qt.WindowModal)
-
-        def callback(progress):
-            progress_dialog.setValue(int(progress * 1000))
-            for i in range(10):
-                QtWidgets.QApplication.processEvents()
-
-        self._project.execute(jobs, callback=callback)
-
-        progress_dialog.close()
-        self._predictions += jobs
-
-    def _update_prediction_ui(self):
-        # TODO implement better sync
-        self.ui.imageThumbnailGallery.clear()
-        for prediction in self._predictions:
-            filename = prediction['filename']
-            if prediction['filetype'] == 'image':
-                icon = QtGui.QIcon(filename)
-                item = QtWidgets.QListWidgetItem(icon, os.path.basename(filename))
-            else:
-                item = QtWidgets.QListWidgetItem(os.path.basename(filename))
-            self.ui.imageThumbnailGallery.addItem(item)
-            self._prediction_row_changed(self.ui.imageThumbnailGallery.currentRow())
-
-        if len(self._predictions) == 0:
-            self._prediction_row_changed(-1)
-
-    def _prediction_row_changed(self, row):
-        if row in range(len(self._predictions)):
-            prediction = self._predictions[row]
-            self._setup_video_slider(prediction)
-            self._display_prediction(prediction)
-        else:
-            self._setup_video_slider({'filetype': 'empty'})
-            self._display_prediction({'filetype': 'empty'})
-
-    def _setup_video_slider(self, prediction):
-        if prediction['filetype'] == 'video':
-            video_cap = Video(prediction['filename'])
-            if video_cap.last_error is None:
-                self.ui.frameNumber.setDecMode()
-                self.ui.frameNumber.display(0)
-                self.ui.frameNumber.setDigitCount(5)
-                self.ui.frameNumber.show()
-
-                self.ui.frameSlider.show()
-                self.ui.frameSlider.setValue(0)
-                self.ui.frameSlider.setMinimum(0)
-                self.ui.frameSlider.setMaximum(video_cap.framecount - 1)
-
-                self.ui.frameSlider.valueChanged.connect(
-                    lambda value, _prediction=prediction:
-                    [self._display_prediction(dict(frame=value, cap=video_cap, **_prediction)),
-                     self.ui.frameNumber.display(value)])
-            else:
-                self._disable_video_slider()
-        else:
-            self._disable_video_slider()
-
-    def _disable_video_slider(self):
-        self.ui.frameSlider.setValue(0)
-        try:
-            self.ui.frameSlider.valueChanged.disconnect()
-        except:
-            pass
-        self.ui.frameSlider.hide()
-        self.ui.frameNumber.hide()
-
-    def _display_prediction(self, prediction):
-        self.ui.annotatedImageView.display(prediction)
-        filtered_dict = {i: prediction[i] for i in prediction if i != 'cap'}
-        if 'cap' in prediction.keys():
-            filtered_dict['cap'] = '[VideoCapture]'
-        self.ui.predictionDebugText.setPlainText(json.dumps(filtered_dict, indent=2, skipkeys=True))

+ 0 - 444
pycs/ui/MainWindow.ui

@@ -1,444 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>MainWindow</class>
-    <widget class="QMainWindow" name="MainWindow">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>970</width>
-                <height>624</height>
-            </rect>
-        </property>
-        <property name="windowTitle">
-            <string>Carpe Simiam</string>
-        </property>
-        <widget class="QWidget" name="centralWidget">
-            <layout class="QHBoxLayout" name="horizontalLayout">
-                <item>
-                    <layout class="QVBoxLayout" name="verticalLayout_2">
-                        <item>
-                            <widget class="AnnotatedImageView" name="annotatedImageView">
-                                <property name="sizePolicy">
-                                    <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                                        <horstretch>0</horstretch>
-                                        <verstretch>0</verstretch>
-                                    </sizepolicy>
-                                </property>
-                            </widget>
-                        </item>
-                        <item>
-                            <layout class="QHBoxLayout" name="frameCtrlLayout">
-                                <item>
-                                    <widget class="QLCDNumber" name="frameNumber"/>
-                                </item>
-                                <item>
-                                    <widget class="QSlider" name="frameSlider">
-                                        <property name="orientation">
-                                            <enum>Qt::Horizontal</enum>
-                                        </property>
-                                    </widget>
-                                </item>
-                            </layout>
-                        </item>
-                    </layout>
-                </item>
-                <item>
-                    <layout class="QVBoxLayout" name="verticalLayout">
-                        <item>
-                            <widget class="QListWidget" name="imageThumbnailGallery">
-                                <property name="sizePolicy">
-                                    <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
-                                        <horstretch>0</horstretch>
-                                        <verstretch>0</verstretch>
-                                    </sizepolicy>
-                                </property>
-                                <property name="minimumSize">
-                                    <size>
-                                        <width>0</width>
-                                        <height>0</height>
-                                    </size>
-                                </property>
-                                <property name="maximumSize">
-                                    <size>
-                                        <width>16777215</width>
-                                        <height>16777215</height>
-                                    </size>
-                                </property>
-                                <property name="iconSize">
-                                    <size>
-                                        <width>96</width>
-                                        <height>54</height>
-                                    </size>
-                                </property>
-                                <property name="viewMode">
-                                    <enum>QListView::ListMode</enum>
-                                </property>
-                                <property name="uniformItemSizes">
-                                    <bool>true</bool>
-                                </property>
-                            </widget>
-                        </item>
-                        <item>
-                            <layout class="QHBoxLayout" name="horizontalLayout_2">
-                                <item>
-                                    <widget class="QPushButton" name="clearPredictionsButton">
-                                        <property name="text">
-                                            <string>Clear Predictions</string>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <widget class="QPushButton" name="exportCSVButton">
-                                        <property name="text">
-                                            <string>Export as CSV...</string>
-                                        </property>
-                                    </widget>
-                                </item>
-                            </layout>
-                        </item>
-                    </layout>
-                </item>
-            </layout>
-        </widget>
-        <widget class="QMenuBar" name="menuBar">
-            <property name="geometry">
-                <rect>
-                    <x>0</x>
-                    <y>0</y>
-                    <width>970</width>
-                    <height>28</height>
-                </rect>
-            </property>
-            <widget class="QMenu" name="menuFile">
-                <property name="title">
-                    <string>Pro&amp;ject</string>
-                </property>
-                <addaction name="actionNew"/>
-                <addaction name="actionOpen"/>
-                <addaction name="separator"/>
-                <addaction name="actionSave"/>
-                <addaction name="actionSave_As"/>
-                <addaction name="separator"/>
-                <addaction name="actionClose"/>
-                <addaction name="separator"/>
-                <addaction name="actionQuit"/>
-            </widget>
-            <widget class="QMenu" name="menuHelp">
-                <property name="title">
-                    <string>He&amp;lp</string>
-                </property>
-                <addaction name="actionAbout"/>
-            </widget>
-            <widget class="QMenu" name="menuData">
-                <property name="title">
-                    <string>&amp;Data</string>
-                </property>
-                <addaction name="actionPredict_Images"/>
-                <addaction name="separator"/>
-                <addaction name="actionStart_Labeling_Session"/>
-                <addaction name="actionManage_Individuals"/>
-                <addaction name="separator"/>
-                <addaction name="actionImport_Labeled_Faces"/>
-                <addaction name="actionImport_Labeled_Images"/>
-                <addaction name="separator"/>
-                <addaction name="actionUpdate_Model"/>
-                <addaction name="actionValidate_Model"/>
-            </widget>
-            <addaction name="menuFile"/>
-            <addaction name="menuData"/>
-            <addaction name="menuHelp"/>
-        </widget>
-        <widget class="QDockWidget" name="statusWidget">
-            <attribute name="dockWidgetArea">
-                <number>1</number>
-            </attribute>
-            <widget class="QWidget" name="dockWidgetContents_2">
-                <layout class="QVBoxLayout" name="verticalLayout_3">
-                    <item>
-                        <layout class="QVBoxLayout" name="verticalLayout_5">
-                            <item>
-                                <widget class="QLabel" name="pipelineStatusLabel">
-                                    <property name="text">
-                                        <string/>
-                                    </property>
-                                </widget>
-                            </item>
-                        </layout>
-                    </item>
-                    <item>
-                        <spacer name="verticalSpacer_2">
-                            <property name="orientation">
-                                <enum>Qt::Vertical</enum>
-                            </property>
-                            <property name="sizeHint" stdset="0">
-                                <size>
-                                    <width>20</width>
-                                    <height>20</height>
-                                </size>
-                            </property>
-                        </spacer>
-                    </item>
-                    <item>
-                        <widget class="QGroupBox" name="quickAccessBox">
-                            <property name="title">
-                                <string>Quick Tasks</string>
-                            </property>
-                            <layout class="QVBoxLayout" name="verticalLayout_4">
-                                <item>
-                                    <widget class="QPushButton" name="predictButton">
-                                        <property name="text">
-                                            <string>Predict...</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="media-playback-start">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <widget class="QPushButton" name="startLabelingSessionButton">
-                                        <property name="text">
-                                            <string>Label...</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="list-add">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <widget class="QPushButton" name="updateButton">
-                                        <property name="text">
-                                            <string>Update Model</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="view-refresh">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                            </layout>
-                        </widget>
-                    </item>
-                </layout>
-            </widget>
-        </widget>
-        <widget class="QStatusBar" name="statusBar"/>
-        <widget class="QToolBar" name="toolBar">
-            <property name="windowTitle">
-                <string>toolBar</string>
-            </property>
-            <attribute name="toolBarArea">
-                <enum>TopToolBarArea</enum>
-            </attribute>
-            <attribute name="toolBarBreak">
-                <bool>false</bool>
-            </attribute>
-            <addaction name="actionNew"/>
-            <addaction name="actionOpen"/>
-            <addaction name="actionSave"/>
-            <addaction name="separator"/>
-            <addaction name="actionPredict_Images"/>
-            <addaction name="actionManage_Individuals"/>
-            <addaction name="separator"/>
-            <addaction name="actionUpdate_Model"/>
-            <addaction name="separator"/>
-            <addaction name="actionAbout"/>
-        </widget>
-        <widget class="QDockWidget" name="dockWidget">
-            <property name="windowTitle">
-                <string>Deb&amp;ug Output</string>
-            </property>
-            <attribute name="dockWidgetArea">
-                <number>1</number>
-            </attribute>
-            <widget class="QWidget" name="dockWidgetContents">
-                <layout class="QHBoxLayout" name="horizontalLayout_3">
-                    <item>
-                        <widget class="QPlainTextEdit" name="predictionDebugText">
-                            <property name="font">
-                                <font>
-                                    <family>Courier</family>
-                                    <pointsize>8</pointsize>
-                                </font>
-                            </property>
-                            <property name="lineWrapMode">
-                                <enum>QPlainTextEdit::NoWrap</enum>
-                            </property>
-                            <property name="readOnly">
-                                <bool>true</bool>
-                            </property>
-                        </widget>
-                    </item>
-                </layout>
-            </widget>
-        </widget>
-        <action name="actionAbout">
-            <property name="icon">
-                <iconset theme="help-browser">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;About</string>
-            </property>
-        </action>
-        <action name="actionOpen">
-            <property name="icon">
-                <iconset theme="document-open">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Open...</string>
-            </property>
-            <property name="shortcut">
-                <string>Ctrl+O</string>
-            </property>
-        </action>
-        <action name="actionSave">
-            <property name="icon">
-                <iconset theme="document-save">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Save</string>
-            </property>
-            <property name="shortcut">
-                <string>Ctrl+S</string>
-            </property>
-        </action>
-        <action name="actionSave_As">
-            <property name="icon">
-                <iconset theme="document-save-as">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>Sa&amp;ve As...</string>
-            </property>
-            <property name="shortcut">
-                <string>Ctrl+Shift+S</string>
-            </property>
-        </action>
-        <action name="actionClose">
-            <property name="icon">
-                <iconset theme="document-close">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Close</string>
-            </property>
-            <property name="shortcut">
-                <string>Ctrl+W</string>
-            </property>
-        </action>
-        <action name="actionQuit">
-            <property name="icon">
-                <iconset theme="system-log-out">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Quit</string>
-            </property>
-            <property name="shortcut">
-                <string>Ctrl+Q</string>
-            </property>
-        </action>
-        <action name="actionNew">
-            <property name="checkable">
-                <bool>false</bool>
-            </property>
-            <property name="icon">
-                <iconset theme="document-new">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;New</string>
-            </property>
-            <property name="iconText">
-                <string>New</string>
-            </property>
-            <property name="shortcut">
-                <string>Ctrl+N</string>
-            </property>
-        </action>
-        <action name="actionImport_Labeled_Faces">
-            <property name="icon">
-                <iconset>
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Import Labeled Faces...</string>
-            </property>
-        </action>
-        <action name="actionManage_Individuals">
-            <property name="icon">
-                <iconset theme="document-properties">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Manage Individuals...</string>
-            </property>
-        </action>
-        <action name="actionPredict_Images">
-            <property name="icon">
-                <iconset theme="media-playback-start">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Predict Images...</string>
-            </property>
-        </action>
-        <action name="actionUpdate_Model">
-            <property name="icon">
-                <iconset theme="view-refresh">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Update Model</string>
-            </property>
-        </action>
-        <action name="actionValidate_Model">
-            <property name="text">
-                <string>&amp;Validate Model...</string>
-            </property>
-        </action>
-        <action name="actionImport_Labeled_Images">
-            <property name="text">
-                <string>Import &amp;Labeled Images...</string>
-            </property>
-        </action>
-        <action name="actionStart_Labeling_Session">
-            <property name="icon">
-                <iconset theme="list-add">
-                    <normaloff>.</normaloff>.
-                </iconset>
-            </property>
-            <property name="text">
-                <string>&amp;Start Labeling Session...</string>
-            </property>
-        </action>
-    </widget>
-    <customwidgets>
-        <customwidget>
-            <class>AnnotatedImageView</class>
-            <extends>QGraphicsView</extends>
-            <header>pycs.ui.AnnotatedImageView</header>
-        </customwidget>
-    </customwidgets>
-    <resources/>
-    <connections/>
-</ui>

+ 0 - 224
pycs/ui/NewProjectWizard.py

@@ -1,224 +0,0 @@
-#!/usr/bin/env python
-
-"""NewProjectWizard:  Wizard to create new projects."""
-
-import os
-
-from PyQt5 import QtWidgets, QtGui
-
-
-class NewProjectWizard(QtWidgets.QWizard):
-    def _get_project_config(self):
-        return self._project_config
-
-    project_config = property(_get_project_config)
-
-    def _get_project_root(self):
-        return self._project_root
-
-    project_root = property(_get_project_root)
-
-    def __init__(self, parent=None):
-        self._project_config = None
-        self._project_root = None
-        QtWidgets.QWizard.__init__(self, parent=parent)
-
-        self.addPage(IntroductionPage(self))
-        self.addPage(ProjectFolderPage(self))
-        self.addPage(ModelPage(self))
-        self.addPage(DonePage(self))
-
-        self.setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap(':/icons/banner.jpg'))
-        self.setWindowTitle('New Project')
-
-
-# (0) Introduction
-class IntroductionPage(QtWidgets.QWizardPage):
-    def __init__(self, parent=None):
-        QtWidgets.QWizardPage.__init__(self, parent=parent)
-
-        self.setTitle('Introduction')
-        self.setPixmap(QtWidgets.QWizard.WatermarkPixmap, QtGui.QPixmap(':/icons/banner.jpg'))
-
-        label = QtWidgets.QLabel('This wizard will create a new project. Please verify that the '
-                                 'following prerequisites are available to you: <ul>'
-                                 '<li>Carpe Simiam Model Distribution v1.0</li></ul>')
-        label.setWordWrap(True)
-
-        layout = QtWidgets.QVBoxLayout()
-        layout.addWidget(label)
-
-        self.setLayout(layout)
-
-
-# (1) Project Folder
-class ProjectFolderPage(QtWidgets.QWizardPage):
-    def __init__(self, parent=None):
-        QtWidgets.QWizardPage.__init__(self, parent=parent)
-
-        self._valid = False
-
-        self.setTitle('Project Details')
-        self.setSubTitle('')
-
-        projectNameLabel = QtWidgets.QLabel("Project name:")
-        projectNameLineEdit = QtWidgets.QLineEdit()
-        projectNameLabel.setBuddy(projectNameLineEdit)
-
-        projectDescriptionLabel = QtWidgets.QLabel("Project description:")
-        projectDescriptionLineEdit = QtWidgets.QLineEdit()
-        projectDescriptionLabel.setBuddy(projectDescriptionLineEdit)
-
-        projectFolderLabel = QtWidgets.QLabel("Project folder:")
-        self.projectFolderLineEdit = QtWidgets.QLineEdit()
-        projectFolderLabel.setBuddy(self.projectFolderLineEdit)
-        self.validationLabel = QtWidgets.QLabel()
-        self.validationLabel.setStyleSheet("QLabel{ color: red }")
-
-        projectFolderButton = QtWidgets.QPushButton("Browse...")
-        projectFolderButton.clicked.connect(self.onProjectFolderBrowse)
-        self.projectFolderLineEdit.textChanged.connect(self.onProjectFolderChanged)
-
-        layout = QtWidgets.QVBoxLayout()
-        folderLine = QtWidgets.QHBoxLayout()
-
-        layout.addWidget(projectNameLabel)
-        layout.addWidget(projectNameLineEdit)
-        layout.addWidget(projectDescriptionLabel)
-        layout.addWidget(projectDescriptionLineEdit)
-
-        layout.addWidget(projectFolderLabel)
-        layout.addLayout(folderLine)
-        layout.addWidget(self.validationLabel)
-        folderLine.addWidget(self.projectFolderLineEdit)
-        folderLine.addWidget(projectFolderButton)
-
-        self.setLayout(layout)
-        self.registerField("projectFolder*", self.projectFolderLineEdit)
-        self.registerField("projectName*", projectNameLineEdit)
-        self.registerField("projectDescription", projectDescriptionLineEdit)
-
-    def onProjectFolderBrowse(self):
-        selection = QtWidgets.QFileDialog.getExistingDirectory(self, 'Select Project Folder')
-        if len(selection) > 0:
-            self.projectFolderLineEdit.setText(selection)
-
-    def onProjectFolderChanged(self):
-        def validate(text):
-            if len(text) == 0:
-                return 'Please enter a valid destination for your project.'
-            elif not os.path.exists(text):
-                return 'The specified folder does not exist.'
-            elif len(os.listdir(text)) > 0:
-                return 'The specified folder is not empty.'
-            return None
-
-        result = validate(self.projectFolderLineEdit.text())
-        self._valid = result is None
-        if result is not None:
-            self.validationLabel.setText(str(result))
-        else:
-            self.validationLabel.setText('')
-
-    def validatePage(self):
-        self.onProjectFolderChanged()
-        return self._valid and QtWidgets.QWizardPage.validatePage(self)
-
-
-# (2) Model Distribution
-class ModelPage(QtWidgets.QWizardPage):
-    def __init__(self, parent=None):
-        QtWidgets.QWizardPage.__init__(self, parent=parent)
-        self._valid = False
-
-        self.setTitle("Model Distribution")
-        self.setSubTitle("Specify the folder where the Carpe Simiam Model Distribution v1.0 is located.")
-
-        # self.setCommitPage(True)
-
-        modelFolderLabel = QtWidgets.QLabel("Model distribution folder:")
-        modelFolderLineEdit = QtWidgets.QLineEdit()
-        modelFolderLabel.setBuddy(modelFolderLineEdit)
-        validationLabel = QtWidgets.QLabel("")
-        validationLabel.setStyleSheet("QLabel{ color: red }")
-
-        modelFolderButton = QtWidgets.QPushButton("Browse...")
-        modelFolderButton.clicked.connect(self.onModelFolderBrowse)
-        modelFolderLineEdit.textChanged.connect(self.onModelFolderChanged)
-
-        layout = QtWidgets.QVBoxLayout()
-        folderLine = QtWidgets.QHBoxLayout()
-        layout.addWidget(modelFolderLabel)
-        layout.addLayout(folderLine)
-        layout.addWidget(validationLabel)
-        folderLine.addWidget(modelFolderLineEdit)
-        folderLine.addWidget(modelFolderButton)
-
-        self.setLayout(layout)
-        self.registerField("modelFolder*", modelFolderLineEdit)
-
-        self.modelFolderLineEdit = modelFolderLineEdit
-        self.validationLabel = validationLabel
-
-    def onModelFolderBrowse(self):
-        selection = QtWidgets.QFileDialog.getExistingDirectory(self, 'Select Model Distribution Folder')
-        if len(selection) > 0:
-            self.modelFolderLineEdit.setText(selection)
-
-    def onModelFolderChanged(self):
-        def validate(text):
-            if len(text) == 0:
-                return 'Please enter a valid model distribution location.'
-            if not os.path.exists(text):
-                return 'The specified folder does not exist.'
-            if "distribution.json" not in os.listdir(text):
-                return 'The specified folder does not contain a model distribution'
-            return None
-
-        result = validate(self.modelFolderLineEdit.text())
-        self._valid = result is None
-        if result is not None:
-            self.validationLabel.setText(str(result))
-        else:
-            self.validationLabel.setText('')
-
-    def validatePage(self):
-        return self._valid and QtWidgets.QWizardPage.validatePage(self)
-
-
-# (4) Done
-class DonePage(QtWidgets.QWizardPage):
-    def initializePage(self):
-        # Collect fields
-        w = self.wizard()
-        w._project_config = {
-            'description': self.field('projectDescription'),
-            'name': self.field('projectName'),
-            'pipeline': {
-                'model-distribution': self.field('modelFolder')
-            }
-        }
-        w._project_root = self.field('projectFolder')
-
-        # TODO insert summary of project here
-        done_message = "" \
-                       "<p>You can now take the following steps to get started:" \
-                       "<ul><li>Add individuals to the population. To do this, " \
-                       "select <em>Data</em> &gt; <em>Manage Individuals...</em></li>" \
-                       "<li>Import labeled data for training. Choose the appropriate " \
-                       "entry from the <em>Data</em> menu.</li>" \
-                       "<li>Run prediction on images using the <em>Predict Images...</em> button.</li>" \
-                       "</ul></p><p>Configuration:<br>" + str(w._project_config) + "</p>"
-
-        self.doneLabel.setText(done_message)
-
-    def __init__(self, parent=None):
-        QtWidgets.QWizardPage.__init__(self, parent=parent)
-
-        self.doneLabel = QtWidgets.QLabel('Done.')
-        self.doneLabel.setWordWrap(True)
-
-        layout = QtWidgets.QVBoxLayout()
-        layout.addWidget(self.doneLabel)
-
-        self.setLayout(layout)

+ 0 - 71
pycs/ui/PredictionDialog.py

@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-
-"""PredictionDialog:  Dialog to select images and videos to predict."""
-
-import os
-
-from PyQt5 import uic, QtWidgets, QtGui, QtCore
-
-
-class PredictionDialog:
-    FileTypeRole = QtCore.Qt.UserRole + 1
-    FileNameRole = QtCore.Qt.UserRole + 2
-
-    image_extensions = ['.jpg', '.png', '.jpeg']
-    video_extensions = ['.mp4', '.avi', '.mkv', '.mpg', '.mpeg']
-
-    def _get_jobs(self):
-        def to_job(item: QtGui.QStandardItem):
-            filename = item.data(self.FileNameRole)
-            filetype = item.data(self.FileTypeRole)
-            return {'filename': filename, 'filetype': filetype, 'jobs': ['detect-faces']}
-
-        return list(map(to_job, [self.model.item(index) for index in range(self.model.rowCount())]))
-
-    jobs = property(fget=_get_jobs)
-
-    def __init__(self, **kwargs):
-        self.ui = QtWidgets.QDialog(**kwargs)
-
-        spath = os.path.dirname(__file__)
-        uic.loadUi(os.path.join(spath, 'PredictionDialog.ui'), self.ui)
-
-        self.model = QtGui.QStandardItemModel()
-        self.ui.filesList.setModel(self.model)
-
-        # self.add_image('/home/brust/demonstrations/carpe-simiam/images/Alexandra_V110_5_09-08-10.png')
-        # self.add_video('/home/brust/demonstrations/carpe-simiam/images/cut.avi')
-
-        self.ui.addFileButton.clicked.connect(self._add_files)
-
-    def _add_files(self):
-        extensions = 'All supported files (' + \
-                     (' '.join(['*' + extension for extension in self.image_extensions + self.video_extensions])) + \
-                     ')'
-
-        selection = QtWidgets.QFileDialog.getOpenFileNames(self.ui, 'Select Files To Add', filter=extensions)
-        for filename in selection[0]:
-            _, extension = os.path.splitext(filename)
-            extension = extension.lower()
-
-            if extension in self.image_extensions:
-                self.add_image(filename)
-            elif extension in self.video_extensions:
-                self.add_video(filename)
-
-    def exec_(self):
-        return self.ui.exec_()
-
-    def add_image(self, image):
-        # TODO Check for existence
-        item = QtGui.QStandardItem(QtGui.QIcon(image), os.path.basename(image))
-        item.setData('image', self.FileTypeRole)
-        item.setData(image, self.FileNameRole)
-        self.model.appendRow(item)
-
-    def add_video(self, video):
-        # TODO Check for existence
-        item = QtGui.QStandardItem(QtGui.QIcon(video), os.path.basename(video))
-        item.setData('video', self.FileTypeRole)
-        item.setData(video, self.FileNameRole)
-        self.model.appendRow(item)

+ 0 - 114
pycs/ui/PredictionDialog.ui

@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>PredictionDialog</class>
-    <widget class="QDialog" name="PredictionDialog">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>587</width>
-                <height>412</height>
-            </rect>
-        </property>
-        <property name="windowTitle">
-            <string>Predict Images</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout">
-            <item>
-                <widget class="QGroupBox" name="filesBox">
-                    <property name="title">
-                        <string>Images</string>
-                    </property>
-                    <layout class="QVBoxLayout" name="verticalLayout_2">
-                        <item>
-                            <widget class="QListView" name="filesList">
-                                <property name="iconSize">
-                                    <size>
-                                        <width>32</width>
-                                        <height>32</height>
-                                    </size>
-                                </property>
-                                <property name="uniformItemSizes">
-                                    <bool>true</bool>
-                                </property>
-                            </widget>
-                        </item>
-                        <item>
-                            <layout class="QHBoxLayout" name="horizontalLayout">
-                                <item>
-                                    <widget class="QPushButton" name="removeButton">
-                                        <property name="text">
-                                            <string>Remove File</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="list-remove">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                                <item>
-                                    <widget class="QPushButton" name="addFileButton">
-                                        <property name="text">
-                                            <string>Add File...</string>
-                                        </property>
-                                        <property name="icon">
-                                            <iconset theme="list-add">
-                                                <normaloff>.</normaloff>.
-                                            </iconset>
-                                        </property>
-                                    </widget>
-                                </item>
-                            </layout>
-                        </item>
-                    </layout>
-                </widget>
-            </item>
-            <item>
-                <widget class="QDialogButtonBox" name="buttonBox">
-                    <property name="orientation">
-                        <enum>Qt::Horizontal</enum>
-                    </property>
-                    <property name="standardButtons">
-                        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-                    </property>
-                </widget>
-            </item>
-        </layout>
-    </widget>
-    <resources/>
-    <connections>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>accepted()</signal>
-            <receiver>PredictionDialog</receiver>
-            <slot>accept()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>248</x>
-                    <y>254</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>157</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-        <connection>
-            <sender>buttonBox</sender>
-            <signal>rejected()</signal>
-            <receiver>PredictionDialog</receiver>
-            <slot>reject()</slot>
-            <hints>
-                <hint type="sourcelabel">
-                    <x>316</x>
-                    <y>260</y>
-                </hint>
-                <hint type="destinationlabel">
-                    <x>286</x>
-                    <y>274</y>
-                </hint>
-            </hints>
-        </connection>
-    </connections>
-</ui>

+ 0 - 99
pycs/ui/ProgressDialog.ui

@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
-    <class>ProgressDialog</class>
-    <widget class="QDialog" name="ProgressDialog">
-        <property name="geometry">
-            <rect>
-                <x>0</x>
-                <y>0</y>
-                <width>692</width>
-                <height>85</height>
-            </rect>
-        </property>
-        <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-            </sizepolicy>
-        </property>
-        <property name="minimumSize">
-            <size>
-                <width>692</width>
-                <height>85</height>
-            </size>
-        </property>
-        <property name="maximumSize">
-            <size>
-                <width>692</width>
-                <height>85</height>
-            </size>
-        </property>
-        <property name="cursor">
-            <cursorShape>WaitCursor</cursorShape>
-        </property>
-        <property name="contextMenuPolicy">
-            <enum>Qt::NoContextMenu</enum>
-        </property>
-        <property name="windowTitle">
-            <string>Carpe Simiam</string>
-        </property>
-        <property name="modal">
-            <bool>true</bool>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout">
-            <item>
-                <widget class="QLabel" name="statusText">
-                    <property name="text">
-                        <string>TextLabel</string>
-                    </property>
-                </widget>
-            </item>
-            <item>
-                <widget class="QProgressBar" name="progressBar">
-                    <property name="value">
-                        <number>24</number>
-                    </property>
-                </widget>
-            </item>
-            <item>
-                <layout class="QHBoxLayout" name="horizontalLayout">
-                    <item>
-                        <widget class="QLabel" name="timeRemainingLabel">
-                            <property name="text">
-                                <string/>
-                            </property>
-                        </widget>
-                    </item>
-                    <item>
-                        <spacer name="horizontalSpacer">
-                            <property name="orientation">
-                                <enum>Qt::Horizontal</enum>
-                            </property>
-                            <property name="sizeHint" stdset="0">
-                                <size>
-                                    <width>40</width>
-                                    <height>20</height>
-                                </size>
-                            </property>
-                        </spacer>
-                    </item>
-                    <item>
-                        <widget class="QPushButton" name="cancelButton">
-                            <property name="text">
-                                <string>Cancel</string>
-                            </property>
-                            <property name="default">
-                                <bool>true</bool>
-                            </property>
-                            <property name="flat">
-                                <bool>false</bool>
-                            </property>
-                        </widget>
-                    </item>
-                </layout>
-            </item>
-        </layout>
-    </widget>
-    <resources/>
-    <connections/>
-</ui>

+ 0 - 6
pycs/ui/__init__.py

@@ -1,6 +0,0 @@
-#!/usr/bin/env python
-
-"""ui:  All dialogs and windows in Carpe Simiam."""
-
-from .AboutDialog import AboutDialog
-from .MainWindow import MainWindow

+ 0 - 6
pycs/utils/__init__.py

@@ -1,6 +0,0 @@
-#!/usr/bin/env python
-
-"""__init__.py:  General utilities."""
-
-from .errorable import Errorable
-from .video import Video

+ 0 - 68
pycs/utils/errorable.py

@@ -1,68 +0,0 @@
-#!/usr/bin/env python
-
-"""errorable:  Base class for classes with error state."""
-
-import logging
-import sys
-
-
-class Errorable:
-    def __init__(self):
-        self._update_ui_fn = lambda: None
-        self._last_error = None
-        self._err_children = []
-
-    def reset_error(self):
-        self.last_error = None
-
-    def get_last_error(self):
-        errors = ""
-        for child in self._err_children:
-            if child.last_error is not None:
-                if len(errors) > 0:
-                    errors += ", %s" % child.last_error
-                else:
-                    errors += "%s" % child.last_error
-        if self._last_error is not None:
-            if len(errors) > 0:
-                errors += ", %s" % self._last_error
-            else:
-                errors += "%s" % self._last_error
-        if len(errors) == 0:
-            return None
-        else:
-            return errors
-
-    def set_last_error(self, error):
-        self._last_error = error
-        if error is None:
-            for child in self._err_children:
-                child.last_error = None
-
-    last_error = property(get_last_error, set_last_error)
-
-    def _report_error(self, error=None):
-        if error is None:
-            error_str = 'General error'
-        else:
-            error_str = str(error)
-
-        self.last_error = error_str
-
-        # (1) Get exception info (if any)
-        t = sys.exc_info()[0]
-        v = sys.exc_info()[1]
-
-        # (2) Get calling stack frame
-        try:
-            caller = str(sys._getframe(1).f_code.co_name)
-
-        except:
-            caller = "Unknown"
-
-        logging.error("Error in %s" % caller)
-        logging.error(str(error))
-        if t is not None:
-            logging.error("Underlying: %s, %s" % (t, v))
-
-        self._update_ui_fn()

+ 0 - 43
pycs/utils/video.py

@@ -1,43 +0,0 @@
-#!/usr/bin/env python
-
-"""video:  Description."""
-
-from json import JSONEncoder
-
-import cv2
-
-from .errorable import Errorable
-
-
-class Video(Errorable, JSONEncoder):
-    framecount = property(fget=lambda self: self._framecount)
-
-    def get_frame(self, frame):
-        self._cap.set(cv2.CAP_PROP_POS_FRAMES, frame)
-        retval, image = self._cap.read()
-        if not retval:
-            self._report_error('OpenCV error prevents reading of frame!')
-            return None
-        else:
-            rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
-
-            return rgb
-
-    def __init__(self, filename):
-        Errorable.__init__(self)
-
-        self._filename = filename
-        self._framecount = -1
-        try:
-            self._cap = cv2.VideoCapture(self._filename)
-            if not self._cap.isOpened():
-                raise Exception
-            self._framecount = int(self._cap.get(cv2.CAP_PROP_FRAME_COUNT))
-        except:
-            self._report_error('Error opening %s' % filename)
-
-    def close(self):
-        self._cap.release()
-
-    def default(self, o):
-        return 'CAPTURE'