Example #1
0
    def setUp(self):
        '''
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and TalkEditorApp object.
        TalkEditorApp.show() causes the UI to be rendered.
        '''
        settings.configdir = tempfile.mkdtemp()

        self.app = QtGui.QApplication([])
        self.talk_editor = TalkEditorApp()
        self.talk_editor.show()
Example #2
0
def launch_talkeditor():
    """Launch the Talk Editor GUI if no arguments are passed"""
    from PyQt4.QtGui import QApplication
    from freeseer.frontend.talkeditor.talkeditor import TalkEditorApp

    profile = settings.profile_manager.get()
    config = profile.get_config('freeseer.conf', settings.FreeseerConfig,
                                storage_args=['Global'], read_only=True)
    db = profile.get_database()

    app = QApplication(sys.argv)
    main = TalkEditorApp(config, db)
    main.show()
    sys.exit(app.exec_())
Example #3
0
def launch_talkeditor():
    """Launch the Talk Editor GUI if no arguments are passed"""
    from PyQt4.QtGui import QApplication
    from freeseer.frontend.talkeditor.talkeditor import TalkEditorApp

    profile = settings.profile_manager.get()
    config = profile.get_config('freeseer.conf',
                                settings.FreeseerConfig,
                                storage_args=['Global'],
                                read_only=True)
    db = profile.get_database()

    app = QApplication(sys.argv)
    main = TalkEditorApp(config, db)
    main.show()
    sys.exit(app.exec_())
Example #4
0
    def setUp(self):
        '''
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and TalkEditorApp object.
        TalkEditorApp.show() causes the UI to be rendered.
        '''
        self.profile_manager = ProfileManager(tempfile.mkdtemp())
        profile = self.profile_manager.get('testing')
        config = profile.get_config('freeseer.conf', settings.FreeseerConfig,
                                    storage_args=['Global'], read_only=True)
        db = profile.get_database()

        self.app = QtGui.QApplication([])
        self.talk_editor = TalkEditorApp(config, db)
        self.talk_editor.show()
Example #5
0
	def setUp(self):
		'''
		Stardard init method: runs before each test_* method

		Initializes a QtGui.QApplication and TalkEditorApp object.
		TalkEditorApp.show() causes the UI to be rendered.
		'''

		self.app = QtGui.QApplication([])
		self.talk_editor = TalkEditorApp()
		self.talk_editor.show()
Example #6
0
    def setUp(self):
        '''
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and TalkEditorApp object.
        TalkEditorApp.show() causes the UI to be rendered.
        '''
        self.profile_manager = ProfileManager(tempfile.mkdtemp())
        profile = self.profile_manager.get('testing')
        config = profile.get_config('freeseer.conf', settings.FreeseerConfig,
                                    storage_args=['Global'], read_only=True)
        db = profile.get_database()

        self.app = QtGui.QApplication([])
        self.talk_editor = TalkEditorApp(config, db)
        self.talk_editor.show()
Example #7
0
class TestTalkEditorApp(unittest.TestCase):
	'''
	Test suite to verify the functionality of the TalkEditorApp class.

	Tests interact like an end user (using QtTest). Expect the app to be rendered.

	'''

	def setUp(self):
		'''
		Stardard init method: runs before each test_* method

		Initializes a QtGui.QApplication and TalkEditorApp object.
		TalkEditorApp.show() causes the UI to be rendered.
		'''

		self.app = QtGui.QApplication([])
		self.talk_editor = TalkEditorApp()
		self.talk_editor.show()


	def test_add_talk(self):
		''' 
		Tests a user creating a talk and adding it.
		'''

		QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton, Qt.Qt.LeftButton)
		self.assertFalse(self.talk_editor.editorWidget.isVisible())	
		self.assertTrue(self.talk_editor.addTalkWidget.isVisible())

		mTitle = "This is a test"
		mPresenter = "Me, myself, and I"
		mEvent = "0 THIS St."
		mRoom = "Room 13"

		# populate talk data (date and time are prepopulated)
		self.talk_editor.addTalkWidget.titleLineEdit.setText(mTitle)
		self.talk_editor.addTalkWidget.presenterLineEdit.setText(mPresenter)
		self.talk_editor.addTalkWidget.eventLineEdit.setText(mEvent)
		self.talk_editor.addTalkWidget.roomLineEdit.setText(mRoom)

		# add in the talk
		QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.addButton, Qt.Qt.LeftButton)

		# find our talk (ensure it was added)
		found = False
		row_count = self.talk_editor.editorWidget.editor.model().rowCount() - 1
		while row_count >= 0 and not found: # should be at the end, but you never know
			if self.talk_editor.editorWidget.editor.model().index(row_count, 1).data() == mTitle and \
				self.talk_editor.editorWidget.editor.model().index(row_count, 2).data() == mPresenter and \
				self.talk_editor.editorWidget.editor.model().index(row_count, 5).data() == mEvent and \
				self.talk_editor.editorWidget.editor.model().index(row_count, 6).data() == mRoom:
				found = True
				# TODO: Select this row
			row_count -= 1

		self.assertTrue(found, "Couldn't find talk just inserted...")

		# now delete the talk we just created
		QtTest.QTest.mouseClick(self.talk_editor.editorWidget.removeButton, Qt.Qt.LeftButton);

	def test_add_talk_cancel(self):
		'''
		Tests a user creating a talk, but cancelling it instead of adding it.
		'''

		QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton, Qt.Qt.LeftButton)
		self.assertFalse(self.talk_editor.editorWidget.isVisible())	
		self.assertTrue(self.talk_editor.addTalkWidget.isVisible())

		QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.cancelButton, Qt.Qt.LeftButton)
		self.assertFalse(self.talk_editor.addTalkWidget.isVisible())
		self.assertTrue(self.talk_editor.editorWidget.isVisible())

	def test_close_talkeditor(self):
		'''
		Tests the "close" button. 
		Although we close the app using this button after every test (in tearDown()), 
		we are not guaranteed a valid test case in tearDown().
		'''	

		QtTest.QTest.mouseClick(self.talk_editor.editorWidget.closeButton, Qt.Qt.LeftButton)
		self.assertFalse(self.talk_editor.editorWidget.isVisible())


	def test_clear_all_talks(self):
		'''
		Tests the "clear" button on the main window.
		'''

		if self.talk_editor.editorWidget.editor.model().rowCount() == 0:
			QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton, Qt.Qt.LeftButton)
			mTitle = "This is a test"
			mPresenter = "Me, myself, and I"
			mEvent = "0 THIS St."
			mRoom = "Room 13"
			# populate talk data
			self.talk_editor.addTalkWidget.titleLineEdit.setText(mTitle)
			self.talk_editor.addTalkWidget.presenterLineEdit.setText(mPresenter)
			self.talk_editor.addTalkWidget.eventLineEdit.setText(mEvent)
			self.talk_editor.addTalkWidget.roomLineEdit.setText(mRoom)

			# date and time are prepopulated 

			# add in the talk
			QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.addButton, Qt.Qt.LeftButton)

		# we need at least 1 talk
		self.assertTrue(self.talk_editor.editorWidget.editor.model().rowCount() > 0)

		# TODO: ROADBLOCK
		# Clicking "clear" causes a pop-up confirmation box to appear.
		# However, there is no link to this popup from inside the talk_editor

		# hit the clear button, hit no. No changes
		#QtTest.QTest.mouseClick(self.talk_editor.editorWidget.clearButton, Qt.Qt.LeftButton)
		# TODO: get the pop-up box's focus and click the button

		# hit the clear button, hit yes. Empty DB	
		#QtTest.QTest.mouseClick(self.talk_editor.editorWidget.clearButton, Qt.Qt.LeftButton)
		# TODO: get the pop-up box's focus and click the button

	def test_file_menu_quit(self):
		'''
		Tests TalkEditorApp's File->Quit
		'''

		self.assertTrue(self.talk_editor.isVisible())

		# File->Quit
		self.talk_editor.actionExit.trigger()
		self.assertFalse(self.talk_editor.isVisible())

	def test_help_menu_about(self):
		'''
		Tests TalkEditorApp's Help->About
		'''

		self.assertTrue(self.talk_editor.isVisible())

		# Help->About
		self.talk_editor.actionAbout.trigger()
		self.assertFalse(self.talk_editor.hasFocus())
		self.assertTrue(self.talk_editor.aboutDialog.isVisible())

		# Click "Close"
		QtTest.QTest.mouseClick(self.talk_editor.aboutDialog.closeButton, Qt.Qt.LeftButton)
		self.assertFalse(self.talk_editor.aboutDialog.isVisible())

	
	def tearDown(self):
		'''
		Standard tear down method. Runs after each test_* method.

		This method closes the TalkEditorApp by clicking the "close" button
		'''

		QtTest.QTest.mouseClick(self.talk_editor.editorWidget.closeButton, Qt.Qt.LeftButton)
Example #8
0
    def __init__(self, profile, config):
        FreeseerApp.__init__(self)

        self.db = profile.get_database()
        self.config = config
        self.controller = RecordingController(profile, self.db, self.config)

        self.recently_recorded_video = None

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.autoRecordWidget = AutoRecordWidget()
        self.configToolApp = ConfigToolApp(profile, config)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self.config, self.db)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        # Initialize variables for auto-recording
        self.singleID = None
        self.timeUntilStart = None
        self.timeUntilEnd = None
        self.autoTalks = None
        self.recorded = False
        self.beforeStartTimer = QtCore.QTimer(self)
        self.beforeStartTimer.timeout.connect(self.start_single_record)
        self.beforeEndTimer = QtCore.QTimer(self)
        self.beforeEndTimer.timeout.connect(self.single_auto_record)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.actionAutoRecord = QtGui.QAction(self)
        leaveButtonShortcut = "Ctrl+R"
        self.actionAutoRecord.setShortcut(leaveButtonShortcut)
        self.actionAutoRecord.setCheckable(True)
        self.actionAutoRecord.setObjectName(_fromUtf8("actionAutoRecord"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)
        self.menuOptions.addAction(self.actionAutoRecord)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(
            _fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL('triggered()'),
                     self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL('triggered()'),
                     self.toggle_record_button)
        self.connect(
            self.systray,
            QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
            self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(self.mainWidget.eventComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.load_rooms_from_event)
        self.connect(self.mainWidget.roomComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.load_dates_from_event_room)
        self.connect(self.mainWidget.dateComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.load_talks_from_date)
        self.connect(self.mainWidget.talkComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.set_talk_tooltip)
        self.connect(self.mainWidget.standbyButton,
                     QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.disengageButton,
                     QtCore.SIGNAL("clicked()"),
                     functools.partial(self.standby, state=False))
        self.connect(self.mainWidget.recordButton, QtCore.SIGNAL('clicked()'),
                     self.record)
        self.connect(self.mainWidget.pauseButton,
                     QtCore.SIGNAL('toggled(bool)'), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox,
                     QtCore.SIGNAL('toggled(bool)'),
                     self.toggle_audio_feedback)
        self.connect(self.mainWidget.playButton, QtCore.SIGNAL('clicked()'),
                     self.play_video)

        self.connect(self.autoRecordWidget.leaveButton,
                     QtCore.SIGNAL('clicked()'),
                     functools.partial(self.auto_record, state=False))
        self.autoRecordWidget.leaveButton.setShortcut(leaveButtonShortcut)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL('triggered()'),
                     self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL('triggered()'),
                     self.open_talkeditor)
        self.connect(self.actionAutoRecord, QtCore.SIGNAL('toggled(bool)'),
                     self.auto_record)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL('triggered()'),
                     self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL('triggered()'),
                     self.show_report_widget)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton,
                     QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.pauseButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.pauseButton.setFocus()

        self.retranslate()
Example #9
0
class TestTalkEditorApp(unittest.TestCase):
    '''
    Test suite to verify the functionality of the TalkEditorApp class.

    Tests interact like an end user (using QtTest). Expect the app to be rendered.

    '''

    def setUp(self):
        '''
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and TalkEditorApp object.
        TalkEditorApp.show() causes the UI to be rendered.
        '''
        self.profile_manager = ProfileManager(tempfile.mkdtemp())
        profile = self.profile_manager.get('testing')
        config = profile.get_config('freeseer.conf', settings.FreeseerConfig,
                                    storage_args=['Global'], read_only=True)
        db = profile.get_database()

        self.app = QtGui.QApplication([])
        self.talk_editor = TalkEditorApp(config, db)
        self.talk_editor.show()

    def tearDown(self):
        '''
        Standard tear down method. Runs after each test_* method.

        This method closes the TalkEditorApp by clicking the "close" button
        '''
        shutil.rmtree(self.profile_manager._base_folder)

        del self.app
        del self.talk_editor.app

    # def test_add_talk(self):
    #     '''
    #     Tests a user creating a talk and adding it.
    #     '''

    #     QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton, Qt.Qt.LeftButton)
    #     self.assertFalse(self.talk_editor.editorWidget.isVisible())
    #     self.assertTrue(self.talk_editor.addTalkWidget.isVisible())

    #     mTitle = "This is a test"
    #     mPresenter = "Me, myself, and I"
    #     mEvent = "0 THIS St."
    #     mRoom = "Room 13"

    #     # populate talk data (date and time are prepopulated)
    #     self.talk_editor.addTalkWidget.titleLineEdit.setText(mTitle)
    #     self.talk_editor.addTalkWidget.presenterLineEdit.setText(mPresenter)
    #     self.talk_editor.addTalkWidget.eventLineEdit.setText(mEvent)
    #     self.talk_editor.addTalkWidget.roomLineEdit.setText(mRoom)

    #     # add in the talk
    #     QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.addButton, Qt.Qt.LeftButton)

    #     # find our talk (ensure it was added)
    #     found = False
    #     row_count = self.talk_editor.editorWidget.editor.model().rowCount() - 1
    #     while row_count >= 0 and not found:  # should be at the end, but you never know
    #         if self.talk_editor.editorWidget.editor.model().index(row_count, 1).data() == mTitle and \
    #                 self.talk_editor.editorWidget.editor.model().index(row_count, 2).data() == mPresenter and \
    #                 self.talk_editor.editorWidget.editor.model().index(row_count, 5).data() == mEvent and \
    #                 self.talk_editor.editorWidget.editor.model().index(row_count, 6).data() == mRoom:
    #                 found = True
    #                 # TODO: Select this row
    #         row_count -= 1

    #     self.assertTrue(found, "Couldn't find talk just inserted...")

    #     # now delete the talk we just created
    #     QtTest.QTest.mouseClick(self.talk_editor.editorWidget.removeButton, Qt.Qt.LeftButton)

    def test_file_menu_quit(self):
        '''
        Tests TalkEditorApp's File->Quit
        '''

        self.assertTrue(self.talk_editor.isVisible())

        # File->Quit
        self.talk_editor.actionExit.trigger()
        self.assertFalse(self.talk_editor.isVisible())

    def test_help_menu_about(self):
        '''
        Tests TalkEditorApp's Help->About
        '''

        self.assertTrue(self.talk_editor.isVisible())

        # Help->About
        self.talk_editor.actionAbout.trigger()
        self.assertFalse(self.talk_editor.hasFocus())
        self.assertTrue(self.talk_editor.aboutDialog.isVisible())

        # Click "Close"
        QtTest.QTest.mouseClick(self.talk_editor.aboutDialog.closeButton, Qt.Qt.LeftButton)
        self.assertFalse(self.talk_editor.aboutDialog.isVisible())
Example #10
0
    def __init__(self):
        FreeseerApp.__init__(self)

        self.controller = RecordingController()
        self.config = self.controller.config
        self.db = self.controller.db

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.clientWidget = ClientDialog(self.config.configdir, self.db)
        self.configToolApp = ConfigToolApp(self)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(_fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        self.actionClient = QtGui.QAction(self)
        self.actionClient.setIcon(self.icon)
        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        # Hide the controller client configuration screen for Freeseer 3.0.0
        # release. This feature's not ready for public use so lets keep it
        # hidden for now.
        # self.menuFile.insertAction(self.actionExit, self.actionClient)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL("triggered()"), self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL("triggered()"), self.toggle_record_button)
        self.connect(self.systray, QtCore.SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(
            self.mainWidget.eventComboBox,
            QtCore.SIGNAL("currentIndexChanged(const QString&)"),
            self.load_rooms_from_event,
        )
        self.connect(
            self.mainWidget.roomComboBox,
            QtCore.SIGNAL("currentIndexChanged(const QString&)"),
            self.load_dates_from_event_room,
        )
        self.connect(
            self.mainWidget.dateComboBox,
            QtCore.SIGNAL("currentIndexChanged(const QString&)"),
            self.load_talks_from_date,
        )
        self.connect(
            self.mainWidget.talkComboBox, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.set_talk_tooltip
        )
        self.connect(self.mainWidget.standbyPushButton, QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.recordPushButton, QtCore.SIGNAL("toggled(bool)"), self.record)
        self.connect(self.mainWidget.pauseToolButton, QtCore.SIGNAL("toggled(bool)"), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox, QtCore.SIGNAL("toggled(bool)"), self.toggle_audio_feedback)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL("triggered()"), self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL("triggered()"), self.open_talkeditor)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL("triggered()"), self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL("triggered()"), self.show_report_widget)
        self.connect(self.actionClient, QtCore.SIGNAL("triggered()"), self.show_client_widget)

        # GUI Disabling/Enabling Connections
        self.connect(
            self.mainWidget.recordPushButton, QtCore.SIGNAL("toggled(bool)"), self.mainWidget.pauseToolButton.setEnabled
        )

        # Client Connections
        self.connect(self.clientWidget.socket, QtCore.SIGNAL("readyRead()"), self.getAction)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton, QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.recordPushButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.recordPushButton.setFocus()

        self.retranslate()
Example #11
0
class RecordApp(FreeseerApp):
    """Freeseer's main GUI class."""
    def __init__(self, profile, config):
        FreeseerApp.__init__(self)

        self.db = profile.get_database()
        self.config = config
        self.controller = RecordingController(profile, self.db, self.config)

        self.recently_recorded_video = None

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.autoRecordWidget = AutoRecordWidget()
        self.configToolApp = ConfigToolApp(profile, config)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self.config, self.db)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        # Initialize variables for auto-recording
        self.singleID = None
        self.timeUntilStart = None
        self.timeUntilEnd = None
        self.autoTalks = None
        self.recorded = False
        self.beforeStartTimer = QtCore.QTimer(self)
        self.beforeStartTimer.timeout.connect(self.start_single_record)
        self.beforeEndTimer = QtCore.QTimer(self)
        self.beforeEndTimer.timeout.connect(self.single_auto_record)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.actionAutoRecord = QtGui.QAction(self)
        leaveButtonShortcut = "Ctrl+R"
        self.actionAutoRecord.setShortcut(leaveButtonShortcut)
        self.actionAutoRecord.setCheckable(True)
        self.actionAutoRecord.setObjectName(_fromUtf8("actionAutoRecord"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)
        self.menuOptions.addAction(self.actionAutoRecord)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(
            _fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL('triggered()'),
                     self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL('triggered()'),
                     self.toggle_record_button)
        self.connect(
            self.systray,
            QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
            self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(self.mainWidget.eventComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.load_rooms_from_event)
        self.connect(self.mainWidget.roomComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.load_dates_from_event_room)
        self.connect(self.mainWidget.dateComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.load_talks_from_date)
        self.connect(self.mainWidget.talkComboBox,
                     QtCore.SIGNAL('currentIndexChanged(const QString&)'),
                     self.set_talk_tooltip)
        self.connect(self.mainWidget.standbyButton,
                     QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.disengageButton,
                     QtCore.SIGNAL("clicked()"),
                     functools.partial(self.standby, state=False))
        self.connect(self.mainWidget.recordButton, QtCore.SIGNAL('clicked()'),
                     self.record)
        self.connect(self.mainWidget.pauseButton,
                     QtCore.SIGNAL('toggled(bool)'), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox,
                     QtCore.SIGNAL('toggled(bool)'),
                     self.toggle_audio_feedback)
        self.connect(self.mainWidget.playButton, QtCore.SIGNAL('clicked()'),
                     self.play_video)

        self.connect(self.autoRecordWidget.leaveButton,
                     QtCore.SIGNAL('clicked()'),
                     functools.partial(self.auto_record, state=False))
        self.autoRecordWidget.leaveButton.setShortcut(leaveButtonShortcut)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL('triggered()'),
                     self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL('triggered()'),
                     self.open_talkeditor)
        self.connect(self.actionAutoRecord, QtCore.SIGNAL('toggled(bool)'),
                     self.auto_record)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL('triggered()'),
                     self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL('triggered()'),
                     self.show_report_widget)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton,
                     QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.pauseButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.pauseButton.setFocus()

        self.retranslate()

    ###
    ### Translation Related
    ###
    def retranslate(self):
        self.setWindowTitle(
            self.app.translate(
                "RecordApp",
                "Freeseer - portable presentation recording station"))
        #
        # Reusable Strings
        #
        self.standbyString = self.app.translate("RecordApp", "Standby")
        self.disengageString = self.app.translate("RecordApp",
                                                  "Leave record-mode")
        self.standbyTooltipString = self.app.translate(
            "RecordApp", "Sets up the system for recording")
        self.disengageTooltipString = self.app.translate(
            "RecordApp",
            "Go back to edit talk information or select a different talk")
        self.autoRecordString = self.app.translate("RecordApp", "Auto Record")
        self.recordString = self.app.translate("RecordApp", "Record")
        self.pauseString = self.app.translate("RecordApp", "Pause")
        self.resumeString = self.app.translate("RecordApp", "Resume")
        self.stopString = self.app.translate("RecordApp", "Stop")
        self.stopAutoString = self.app.translate("RecordApp",
                                                 "Stop Auto Record")
        self.hideWindowString = self.app.translate("RecordApp",
                                                   "Hide Main Window")
        self.showWindowString = self.app.translate("RecordApp",
                                                   "Show Main Window")
        self.playVideoString = self.app.translate("RecordApp", "Play")

        # Status Bar messages
        self.idleString = self.app.translate("RecordApp", "Idle.")
        self.readyString = self.app.translate("RecordApp", "Ready.")
        self.recordingString = self.app.translate("RecordApp", "Recording")
        self.pausedString = self.app.translate("RecordApp",
                                               "Recording Paused.")
        self.freeSpaceString = self.app.translate("RecordApp", "Free Space:")
        self.elapsedTimeString = self.app.translate("RecordApp",
                                                    "Elapsed Time:")
        # --- End Reusable Strings

        if self.mainWidget.is_recording and self.mainWidget.pauseButton.isChecked(
        ):
            self.mainWidget.statusLabel.setText(self.pausedString)
        elif self.mainWidget.is_recording and (
                not self.mainWidget.pauseButton.isChecked()):
            self.mainWidget.statusLabel.setText(self.recordingString)
        elif self.mainWidget.standbyButton.isChecked():
            self.mainWidget.statusLabel.setText(self.readyString)
        elif self.actionAutoRecord.isChecked():
            self.mainWidget.statusLabel.setText(self.autoRecordString)
        else:
            self.mainWidget.statusLabel.setText(u"{} {} --- {} ".format(
                self.freeSpaceString, get_free_space(self.config.videodir),
                self.idleString))

        #
        # Menubar
        #
        self.menuOptions.setTitle(self.app.translate("RecordApp", "&Options"))
        self.actionConfigTool.setText(
            self.app.translate("RecordApp", "&Configuration"))
        self.actionTalkEditor.setText(
            self.app.translate("RecordApp", "&Edit Talks"))
        self.actionAutoRecord.setText(self.autoRecordString)
        self.actionOpenVideoFolder.setText(
            self.app.translate("RecordApp", "&Open Video Directory"))
        self.actionReport.setText(self.app.translate("RecordApp", "&Report"))
        # --- End Menubar

        #
        # Systray
        #
        self.visibilityAction.setText(self.hideWindowString)
        self.recordAction.setText(self.recordString)
        # --- End Systray

        #
        # RecordingWidget
        #
        self.mainWidget.disengageButton.setText(self.disengageString)
        self.mainWidget.standbyButton.setText(self.standbyString)
        self.mainWidget.standbyButton.setToolTip(self.standbyTooltipString)
        self.mainWidget.disengageButton.setToolTip(self.disengageTooltipString)
        if self.mainWidget.is_recording:
            self.mainWidget.recordButton.setToolTip(self.stopString)
        else:
            self.mainWidget.recordButton.setToolTip(self.recordString)
        self.mainWidget.pauseButton.setText(self.pauseString)
        self.mainWidget.pauseButton.setToolTip(self.pauseString)
        self.mainWidget.eventLabel.setText(
            self.app.translate("RecordApp", "Event"))
        self.mainWidget.roomLabel.setText(
            self.app.translate("RecordApp", "Room"))
        self.mainWidget.dateLabel.setText(
            self.app.translate("RecordApp", "Date"))
        self.mainWidget.talkLabel.setText(
            self.app.translate("RecordApp", "Talk"))
        # --- End RecordingWidget

        #
        # ReportWidget
        #
        self.reportWidget.setWindowTitle(
            self.app.translate("RecordApp", "Reporting Tool"))
        self.reportWidget.titleLabel.setText(
            self.app.translate("RecordApp", "Title:"))
        self.reportWidget.speakerLabel.setText(
            self.app.translate("RecordApp", "Speaker:"))
        self.reportWidget.eventLabel.setText(
            self.app.translate("RecordApp", "Event:"))
        self.reportWidget.roomLabel.setText(
            self.app.translate("RecordApp", "Room:"))
        self.reportWidget.startTimeLabel.setText(
            self.app.translate("RecordApp", "Start Time:"))
        self.reportWidget.endTimeLabel.setText(
            self.app.translate("RecordApp", "End Time:"))
        self.reportWidget.commentLabel.setText(
            self.app.translate("RecordApp", "Comment"))
        self.reportWidget.releaseCheckBox.setText(
            self.app.translate("RecordApp", "Release Received"))
        self.reportWidget.closeButton.setText(
            self.app.translate("RecordApp", "Close"))
        self.reportWidget.reportButton.setText(
            self.app.translate("RecordApp", "Report"))

        # Logic for translating the report options
        noissues = self.app.translate("RecordApp", "No Issues")
        noaudio = self.app.translate("RecordApp", "No Audio")
        novideo = self.app.translate("RecordApp", "No Video")
        noaudiovideo = self.app.translate("RecordApp", "No Audio/Video")
        self.reportWidget.options = [noissues, noaudio, novideo, noaudiovideo]
        self.reportWidget.reportCombo.clear()
        for i in self.reportWidget.options:
            self.reportWidget.reportCombo.addItem(i)
        # --- End ReportWidget

    ###
    ### UI Logic
    ###

    def load_settings(self):
        """Load settings for Freeseer"""
        log.info('Loading settings...')

        # Load default language.
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talks as a SQL Data Model.
        self.load_event_list()

    def current_presentation(self):
        """Creates a presentation object of the current presentation.

        Current presentation is the currently selected title on the GUI.
        """
        #i = self.mainWidget.talkComboBox.currentIndex()
        #p_id = self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()
        return self.db.get_presentation(self.current_presentation_id())

    def current_presentation_id(self):
        """Returns the current selected presentation ID."""
        i = self.mainWidget.talkComboBox.currentIndex()
        return self.mainWidget.talkComboBox.model().index(i, 1).data(
            QtCore.Qt.DisplayRole).toString()

    def standby(self, state):
        """Prepares the GStreamer pipelines for recording

        Sets the pipeline to paused state so that initiating a recording
        does not have a delay due to GStreamer initialization.
        """
        def toggle_gui(state):
            """Toggles GUI components when standby is pressed"""
            if state:
                self.mainWidget.standbyButton.setHidden(state)
                self.mainWidget.disengageButton.setVisible(state)
            else:
                self.mainWidget.disengageButton.setVisible(state)
                self.mainWidget.standbyButton.setHidden(state)

            self.mainWidget.recordButton.setEnabled(state)
            self.mainWidget.eventComboBox.setDisabled(state)
            self.mainWidget.roomComboBox.setDisabled(state)
            self.mainWidget.dateComboBox.setDisabled(state)
            self.mainWidget.talkComboBox.setDisabled(state)
            self.mainWidget.audioFeedbackCheckbox.setDisabled(state)

        if state:  # Prepare the pipelines
            if self.load_backend():
                toggle_gui(True)
                self.controller.pause()
                self.mainWidget.statusLabel.setText(u"{} {} --- {} ".format(
                    self.freeSpaceString, get_free_space(self.config.videodir),
                    self.readyString))
            else:
                toggle_gui(False)
                self.mainWidget.standbyButton.setChecked(False)
        else:
            toggle_gui(False)
            self.controller.stop()
            self.mainWidget.standbyButton.setChecked(False)

        self.mainWidget.playButton.setEnabled(False)

    def record(self):
        """The logic for recording and stopping recording."""

        if self.mainWidget.is_recording:  # Start Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo_rec.png")
            sysIcon2 = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon2)
            self.controller.record()
            self.mainWidget.recordButton.setToolTip(self.stopString)
            self.mainWidget.disengageButton.setEnabled(False)
            self.mainWidget.pauseButton.setEnabled(True)
            self.recordAction.setText(self.stopString)

            # Hide if auto-hide is set.
            if self.config.auto_hide:
                self.hide_window()
                self.visibilityAction.setText(self.showWindowString)
                log.debug(
                    'auto-hide is enabled, main window is now hidden in systray.'
                )

            # Start timer.
            self.timer.start(1000)

        else:  # Stop Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo.png")
            sysIcon = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon)
            self.controller.stop()
            self.mainWidget.pauseButton.setChecked(False)
            self.mainWidget.recordButton.setToolTip(self.recordString)
            self.mainWidget.disengageButton.setEnabled(True)
            self.mainWidget.pauseButton.setEnabled(False)
            self.recordAction.setText(self.recordString)
            self.mainWidget.audioSlider.setValue(0)
            self.mainWidget.statusLabel.setText(u"{} {} --- {} ".format(
                self.freeSpaceString, get_free_space(self.config.videodir),
                self.idleString))

            # Finally set the standby button back to unchecked position.
            self.standby(False)

            # Stop and reset timer.
            self.timer.stop()
            self.reset_timer()

            #Show playback button
            self.mainWidget.playButton.setVisible(True)
            self.mainWidget.playButton.setEnabled(True)

            # Select next talk if there is one within 15 minutes.
            if self.current_event and self.current_room:
                starttime = QtCore.QDateTime().currentDateTime()
                stoptime = starttime.addSecs(900)
                talkid = self.db.get_talk_between_time(self.current_event,
                                                       self.current_room,
                                                       starttime.toString(),
                                                       stoptime.toString())

                if talkid is not None:
                    for i in range(self.mainWidget.talkComboBox.count()):
                        if talkid == self.mainWidget.talkComboBox.model(
                        ).index(i, 1).data(QtCore.Qt.DisplayRole).toString():
                            self.mainWidget.talkComboBox.setCurrentIndex(i)

    def _enable_disable_gui(self, state):
        """Disables GUI components when Auto Record is pressed, and enables them when Auto Record is released"""
        self.mainWidget.standbyButton.setDisabled(state)
        self.mainWidget.eventComboBox.setDisabled(state)
        self.mainWidget.roomComboBox.setDisabled(state)
        self.mainWidget.dateComboBox.setDisabled(state)
        self.mainWidget.talkComboBox.setDisabled(state)
        self.mainWidget.audioFeedbackCheckbox.setDisabled(state)

    def stop_auto_record_gui(self):
        """Sets the gui for stopping the auto record"""
        self.autoRecordWidget.stop_timer()
        self.autoRecordWidget.close()
        self._enable_disable_gui(False)
        self.recorded = False
        self.actionAutoRecord.setChecked(False)

    def auto_record(self, state):
        """Starts automated recording"""
        if state:
            # If there is a room selected, then it's possible to auto-record
            if self.current_room:
                self.autoTalks = self.db.get_talks_by_room_and_time(
                    self.current_room)
                # Start recording if there are talks in database that can be auto-recorded
                if self.autoTalks.next():
                    # Set the cursor back to before the first record so that single_auto_record works properly
                    self.autoTalks.previous()
                    self._enable_disable_gui(True)
                    self.single_auto_record()
                else:
                    # Dialog for no talks to auto-record
                    QtGui.QMessageBox.information(
                        self, 'No Talks to Record',
                        'There are no upcoming talks to auto-record in this room',
                        QtGui.QMessageBox.Ok)
                    self.actionAutoRecord.setChecked(False)

            else:
                # Dialog that pops up when no room is selected
                QtGui.QMessageBox.information(
                    self, 'No Room Selected',
                    'Please select a room to auto-record',
                    QtGui.QMessageBox.Ok)
                self.actionAutoRecord.setChecked(False)
        else:
            self.beforeStartTimer.stop()
            self.beforeEndTimer.stop()
            self.controller.stop()
            self.stop_auto_record_gui()

        self.mainWidget.playButton.setEnabled(False)

    def single_auto_record(self):
        """Completes one display and record cycle of the auto-record feature.

        Stops the recording of the last talk if it exists, displays the countdown until the start of
        the next talk, and when the talk begins, records the talk while displaying the countdown until
        the end of the talk.
        """
        if self.recorded:
            self.controller.stop()
            self.recorded = False
            log.debug("Auto-recording for the current talk stopped.")

        if self.autoTalks.next():
            starttime = QtCore.QTime.fromString(
                self.autoTalks.value(8).toString())
            endtime = QtCore.QTime.fromString(
                self.autoTalks.value(9).toString())
            currenttime = QtCore.QTime.currentTime()

            if currenttime <= starttime:
                self.singleID = self.autoTalks.value(0).toString()
                title = self.autoTalks.value(1).toString()
                speaker = self.autoTalks.value(2).toString()

                # Time (in seconds) until recording for the talk starts
                self.timeUntilStart = currenttime.secsTo(starttime)
                # Time (in seconds) from the starttime to endtime of this talk
                self.timeUntilEnd = starttime.secsTo(endtime)

                # Display fullscreen countdown and talk info until talk starts
                self.autoRecordWidget.set_recording(False)
                self.autoRecordWidget.set_display_message(title, speaker)
                self.autoRecordWidget.start_timer(self.timeUntilStart)
                self.autoRecordWidget.showFullScreen()

                # Wait for talk to start, then change display and start recording
                self.beforeStartTimer.setInterval(
                    (self.timeUntilStart + 1) * 1000)
                self.beforeStartTimer.setSingleShot(True)
                self.beforeStartTimer.start()
            else:
                # Start time has already passed, so move on to next talk
                self.single_auto_record()
        else:
            self.stop_auto_record_gui()

    def start_single_record(self):
        """Begins the auto-recording of a single talk while displaying the countdown on screen"""
        self.autoRecordWidget.set_recording(True)
        self.autoRecordWidget.set_display_message()
        self.autoRecordWidget.start_timer(self.timeUntilEnd)
        if self.controller.record_talk_id(self.singleID):
            log.debug("Auto-recording for the current talk started.")
            self.recorded = True
        self.beforeEndTimer.setInterval((self.timeUntilEnd + 1) * 1000)
        self.beforeEndTimer.setSingleShot(True)
        self.beforeEndTimer.start()

    def pause(self, state):
        """Pause the recording"""
        if state:  # Pause Recording.
            self.controller.pause()
            log.info("Recording paused.")
            self.mainWidget.pauseButton.setToolTip(self.resumeString)
            self.mainWidget.statusLabel.setText(self.pausedString)
            self.timer.stop()
        elif self.mainWidget.is_recording:
            self.controller.record()
            log.info("Recording unpaused.")
            self.mainWidget.pauseButton.setToolTip(self.pauseString)
            self.timer.start(1000)

    def load_backend(self):
        """Prepares the backend for recording"""
        if self.current_presentation():
            presentation = self.current_presentation()

        # If current presentation is no existant (empty talk database)
        # use a default recording name.
        else:
            presentation = Presentation(title=unicode("default"))

        initialized, self.recently_recorded_video = self.controller.load_backend(
            presentation)
        if initialized:
            return True
        else:
            return False  # Error something failed while loading the backend

    def update_timer(self):
        """Updates the Elapsed Time displayed.

        Uses the statusLabel for the display.
        """
        frmt_time = "%d:%02d" % (self.time_minutes, self.time_seconds)
        self.time_seconds += 1
        if self.time_seconds == 60:
            self.time_seconds = 0
            self.time_minutes += 1

        self.mainWidget.statusLabel.setText(u"{} {} --- {} {} --- {}".format(
            self.elapsedTimeString, frmt_time, self.freeSpaceString,
            get_free_space(self.config.videodir), self.recordingString))

    def reset_timer(self):
        """Resets the Elapsed Time."""
        self.time_minutes = 0
        self.time_seconds = 0

    def toggle_audio_feedback(self, enabled):
        """Enables or disables audio feedback according to checkbox state"""
        self.config.audio_feedback = enabled

    ###
    ### Talk Related
    ###

    def set_talk_tooltip(self, talk):
        self.mainWidget.talkComboBox.setToolTip(talk)

    def load_event_list(self):
        model = self.db.get_events_model()
        self.mainWidget.eventComboBox.setModel(model)

    def load_rooms_from_event(self, event):
        #self.disconnect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

        self.current_event = event

        model = self.db.get_rooms_model(self.current_event)
        self.mainWidget.roomComboBox.setModel(model)

        #self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

    def load_dates_from_event_room(self, change):
        event = str(self.mainWidget.eventComboBox.currentText())
        room = str(self.mainWidget.roomComboBox.currentText())
        model = self.db.get_dates_from_event_room_model(event, room)
        self.mainWidget.dateComboBox.setModel(model)

    def load_talks_from_date(self, date):
        self.current_room = str(self.mainWidget.roomComboBox.currentText())
        self.current_date = date

        model = self.db.get_talks_model(self.current_event, self.current_room,
                                        self.current_date)
        self.mainWidget.talkComboBox.setModel(model)

    ###
    ### Report Failure
    ###
    def show_report_widget(self):
        p = self.current_presentation()
        self.reportWidget.titleLabel2.setText(p.title)
        self.reportWidget.speakerLabel2.setText(p.speaker)
        self.reportWidget.eventLabel2.setText(p.event)
        self.reportWidget.roomLabel2.setText(p.room)
        self.reportWidget.startTimeLabel2.setText(p.startTime)
        self.reportWidget.endTimeLabel2.setText(p.endTime)

        # Get existing report if there is one.
        talk_id = self.current_presentation_id()
        f = self.db.get_report(talk_id)
        if f is not None:
            self.reportWidget.commentEdit.setText(f.comment)
            i = self.reportWidget.reportCombo.findText(f.indicator)
            self.reportWidget.reportCombo.setCurrentIndex(i)
            self.reportWidget.releaseCheckBox.setChecked(f.release)
        else:
            self.reportWidget.commentEdit.setText("")
            self.reportWidget.reportCombo.setCurrentIndex(0)
            self.reportWidget.releaseCheckBox.setChecked(False)

        self.reportWidget.show()

    def report(self):
        talk_id = self.current_presentation_id()
        i = self.reportWidget.reportCombo.currentIndex()

        failure = Failure(talk_id, self.reportWidget.commentEdit.text(),
                          self.reportWidget.options[i],
                          self.reportWidget.releaseCheckBox.isChecked())
        log.info("Report Failure: %s, %s, %s, release form? %s" %
                 (talk_id, self.reportWidget.commentEdit.text(),
                  self.reportWidget.options[i],
                  self.reportWidget.releaseCheckBox.isChecked()))

        self.db.insert_failure(failure)
        self.reportWidget.close()

    ###
    ### Misc.
    ###

    def _icon_activated(self, reason):
        if reason == QtGui.QSystemTrayIcon.Trigger:
            self.systray.menu.popup(QCursor.pos())
        if reason == QtGui.QSystemTrayIcon.DoubleClick:
            self.toggle_record_button()

    def hide_window(self):
        self.geometry = self.saveGeometry()
        self.hide()

    def show_window(self):
        if (self.geometry is not None):
            self.restoreGeometry(self.geometry)
        self.show()

    def toggle_window_visibility(self):
        """Toggles the visibility of the Recording Main Window."""
        if self.isHidden():
            self.show_window()
            self.visibilityAction.setText(self.hideWindowString)
        else:
            self.hide_window()
            self.visibilityAction.setText(self.showWindowString)

    def toggle_record_button(self):
        self.mainWidget.standbyButton.toggle()
        self.mainWidget.recordButton.toggle()

    def audio_feedback(self, value):
        self.mainWidget.audioSlider.setValue(value)

    def open_video_directory(self):
        if sys.platform.startswith("linux"):
            os.system("xdg-open %s" % self.config.videodir)
        elif sys.platform.startswith("win32"):
            os.system("explorer %s" % self.config.videodir)
        else:
            log.info("Error: This command is not supported on the current OS.")

    def closeEvent(self, event):
        log.info('Exiting freeseer...')
        event.accept()

    '''
    This function plays the most recently recorded video
    '''

    def play_video(self):
        if sys.platform.startswith("linux"):
            subprocess.call([
                "xdg-open", "{}/{}".format(self.config.videodir,
                                           self.recently_recorded_video)
            ])
        if sys.platform.startswith("win32"):
            os.system("start {}".format(
                os.path.join(self.config.videodir,
                             self.recently_recorded_video)))

    '''
    Client functions
    '''

    def show_client_widget(self):
        self.current_presentation()
        self.clientWidget.show()

    '''
    This function is for handling commands sent from the server to the client
    '''

    def getAction(self):
        message = self.clientWidget.socket.read(
            self.clientWidget.socket.bytesAvailable())
        if message == 'Record':
            self.mainWidget.standbyButton.toggle()
            self.mainWidget.recordButton.toggle()
            self.clientWidget.sendMessage('Started recording')
            log.info("Started recording by server's request")
        elif message == 'Stop':
            self.mainWidget.recordButton.toggle()
            log.info("Stopping recording by server's request")
        elif message == 'Pause' or 'Resume':
            self.mainWidget.pauseButton.toggle()
            if message == 'Pause':
                log.info("Paused recording by server's request")
            elif message == 'Resume':
                log.info("Resumed recording by server's request")

    ###
    ### Utility
    ###
    def open_configtool(self):
        self.configToolApp.show()

    def open_talkeditor(self):
        self.talkEditorApp.show()
        self.load_event_list()
Example #12
0
    def __init__(self, profile, config):
        super(RecordApp, self).__init__(config)

        self.db = profile.get_database()
        self.controller = RecordingController(profile, self.db, self.config)

        self.recently_recorded_video = None

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.autoRecordWidget = AutoRecordWidget()
        self.configToolApp = ConfigToolApp(profile, config)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self.config, self.db)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.logStatusWidget = LogStatusWidget(self.logDialog)
        self.statusBar().addPermanentWidget(self.logStatusWidget, 1)
        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        # Initialize variables for auto-recording
        self.singleID = None
        self.timeUntilStart = None
        self.timeUntilEnd = None
        self.autoTalks = None
        self.recorded = False
        self.beforeStartTimer = QtCore.QTimer(self)
        self.beforeStartTimer.timeout.connect(self.start_single_record)
        self.beforeEndTimer = QtCore.QTimer(self)
        self.beforeEndTimer.timeout.connect(self.single_auto_record)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.actionAutoRecord = QtGui.QAction(self)
        leaveButtonShortcut = "Ctrl+R"
        self.actionAutoRecord.setShortcut(leaveButtonShortcut)
        self.actionAutoRecord.setCheckable(True)
        self.actionAutoRecord.setObjectName(_fromUtf8("actionAutoRecord"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)
        self.menuOptions.addAction(self.actionAutoRecord)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(_fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL('triggered()'), self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL('triggered()'), self.toggle_record_button)
        self.connect(self.systray, QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(self.mainWidget.eventComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_rooms_from_event)
        self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_dates_from_event_room)
        self.connect(self.mainWidget.dateComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_date)
        self.connect(self.mainWidget.talkComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.set_talk_tooltip)
        self.connect(self.mainWidget.standbyButton, QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.disengageButton, QtCore.SIGNAL("clicked()"), functools.partial(self.standby, state=False))
        self.connect(self.mainWidget.recordButton, QtCore.SIGNAL('clicked()'), self.record)
        self.connect(self.mainWidget.pauseButton, QtCore.SIGNAL('toggled(bool)'), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox, QtCore.SIGNAL('toggled(bool)'), self.toggle_audio_feedback)
        self.connect(self.mainWidget.playButton, QtCore.SIGNAL('clicked()'), self.play_video)

        self.connect(self.autoRecordWidget.leaveButton, QtCore.SIGNAL('clicked()'), functools.partial(self.auto_record, state=False))
        self.autoRecordWidget.leaveButton.setShortcut(leaveButtonShortcut)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL('triggered()'), self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL('triggered()'), self.open_talkeditor)
        self.connect(self.actionAutoRecord, QtCore.SIGNAL('toggled(bool)'), self.auto_record)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL('triggered()'), self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL('triggered()'), self.show_report_widget)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton, QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.pauseButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.pauseButton.setFocus()

        self.retranslate()
Example #13
0
class RecordApp(FreeseerApp):
    """Freeseer's main GUI class."""

    def __init__(self):
        FreeseerApp.__init__(self)

        self.controller = RecordingController()
        self.config = self.controller.config
        self.db = self.controller.db

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.clientWidget = ClientDialog(self.config.configdir, self.db)
        self.configToolApp = ConfigToolApp(self)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(_fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        self.actionClient = QtGui.QAction(self)
        self.actionClient.setIcon(self.icon)
        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        # Hide the controller client configuration screen for Freeseer 3.0.0
        # release. This feature's not ready for public use so lets keep it
        # hidden for now.
        # self.menuFile.insertAction(self.actionExit, self.actionClient)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL("triggered()"), self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL("triggered()"), self.toggle_record_button)
        self.connect(self.systray, QtCore.SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(
            self.mainWidget.eventComboBox,
            QtCore.SIGNAL("currentIndexChanged(const QString&)"),
            self.load_rooms_from_event,
        )
        self.connect(
            self.mainWidget.roomComboBox,
            QtCore.SIGNAL("currentIndexChanged(const QString&)"),
            self.load_dates_from_event_room,
        )
        self.connect(
            self.mainWidget.dateComboBox,
            QtCore.SIGNAL("currentIndexChanged(const QString&)"),
            self.load_talks_from_date,
        )
        self.connect(
            self.mainWidget.talkComboBox, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.set_talk_tooltip
        )
        self.connect(self.mainWidget.standbyPushButton, QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.recordPushButton, QtCore.SIGNAL("toggled(bool)"), self.record)
        self.connect(self.mainWidget.pauseToolButton, QtCore.SIGNAL("toggled(bool)"), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox, QtCore.SIGNAL("toggled(bool)"), self.toggle_audio_feedback)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL("triggered()"), self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL("triggered()"), self.open_talkeditor)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL("triggered()"), self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL("triggered()"), self.show_report_widget)
        self.connect(self.actionClient, QtCore.SIGNAL("triggered()"), self.show_client_widget)

        # GUI Disabling/Enabling Connections
        self.connect(
            self.mainWidget.recordPushButton, QtCore.SIGNAL("toggled(bool)"), self.mainWidget.pauseToolButton.setEnabled
        )

        # Client Connections
        self.connect(self.clientWidget.socket, QtCore.SIGNAL("readyRead()"), self.getAction)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton, QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.recordPushButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.recordPushButton.setFocus()

        self.retranslate()

    ###
    ### Translation Related
    ###
    def retranslate(self):
        self.clientWidget.retranslate(self.current_language)

        self.setWindowTitle(self.app.translate("RecordApp", "Freeseer - portable presentation recording station"))
        #
        # Reusable Strings
        #
        self.standbyString = self.app.translate("RecordApp", "Standby")
        self.recordString = self.app.translate("RecordApp", "Record")
        self.pauseString = self.app.translate("RecordApp", "Pause")
        self.resumeString = self.app.translate("RecordApp", "Resume")
        self.stopString = self.app.translate("RecordApp", "Stop")
        self.hideWindowString = self.app.translate("RecordApp", "Hide Main Window")
        self.showWindowString = self.app.translate("RecordApp", "Show Main Window")

        # Status Bar messages
        self.idleString = self.app.translate("RecordApp", "Idle.")
        self.readyString = self.app.translate("RecordApp", "Ready.")
        self.recordingString = self.app.translate("RecordApp", "Recording...")
        self.pausedString = self.app.translate("RecordApp", "Recording Paused.")
        # --- End Reusable Strings

        if self.mainWidget.recordPushButton.isChecked() and self.mainWidget.pauseToolButton.isChecked():
            self.mainWidget.statusLabel.setText(self.pausedString)
        elif self.mainWidget.recordPushButton.isChecked() and (not self.mainWidget.pauseToolButton.isChecked()):
            self.mainWidget.statusLabel.setText(self.recordingString)
        elif self.mainWidget.standbyPushButton.isChecked():
            self.mainWidget.statusLabel.setText(self.readyString)
        else:
            self.mainWidget.statusLabel.setText(self.idleString)

        #
        # Menubar
        #
        self.menuOptions.setTitle(self.app.translate("RecordApp", "&Options"))
        self.actionConfigTool.setText(self.app.translate("RecordApp", "&ConfigTool"))
        self.actionTalkEditor.setText(self.app.translate("RecordApp", "Talk&Editor"))
        self.actionOpenVideoFolder.setText(self.app.translate("RecordApp", "&Open Video Directory"))
        self.actionClient.setText(self.app.translate("RecordApp", "&Connect to server"))
        self.actionReport.setText(self.app.translate("RecordApp", "&Report"))
        # --- End Menubar

        #
        # Systray
        #
        self.visibilityAction.setText(self.hideWindowString)
        self.recordAction.setText(self.recordString)
        # --- End Systray

        #
        # RecordingWidget
        #
        self.mainWidget.standbyPushButton.setText(self.standbyString)
        self.mainWidget.standbyPushButton.setToolTip(self.standbyString)
        if self.mainWidget.recordPushButton.isChecked():
            self.mainWidget.recordPushButton.setText(self.stopString)
            self.mainWidget.recordPushButton.setToolTip(self.stopString)
        else:
            self.mainWidget.recordPushButton.setText(self.recordString)
            self.mainWidget.recordPushButton.setToolTip(self.recordString)
        self.mainWidget.pauseToolButton.setText(self.pauseString)
        self.mainWidget.pauseToolButton.setToolTip(self.pauseString)
        self.mainWidget.eventLabel.setText(self.app.translate("RecordApp", "Event"))
        self.mainWidget.roomLabel.setText(self.app.translate("RecordApp", "Room"))
        self.mainWidget.dateLabel.setText(self.app.translate("RecordApp", "Date"))
        self.mainWidget.talkLabel.setText(self.app.translate("RecordApp", "Talk"))
        # --- End RecordingWidget

        #
        # ReportWidget
        #
        self.reportWidget.setWindowTitle(self.app.translate("RecordApp", "Reporting Tool"))
        self.reportWidget.titleLabel.setText(self.app.translate("RecordApp", "Title:"))
        self.reportWidget.speakerLabel.setText(self.app.translate("RecordApp", "Speaker:"))
        self.reportWidget.eventLabel.setText(self.app.translate("RecordApp", "Event:"))
        self.reportWidget.roomLabel.setText(self.app.translate("RecordApp", "Room:"))
        self.reportWidget.timeLabel.setText(self.app.translate("RecordApp", "Time:"))
        self.reportWidget.commentLabel.setText(self.app.translate("RecordApp", "Comment"))
        self.reportWidget.releaseCheckBox.setText(self.app.translate("RecordApp", "Release Received"))
        self.reportWidget.closeButton.setText(self.app.translate("RecordApp", "Close"))
        self.reportWidget.reportButton.setText(self.app.translate("RecordApp", "Report"))

        # Logic for translating the report options
        noissues = self.app.translate("RecordApp", "No Issues")
        noaudio = self.app.translate("RecordApp", "No Audio")
        novideo = self.app.translate("RecordApp", "No Video")
        noaudiovideo = self.app.translate("RecordApp", "No Audio/Video")
        self.reportWidget.options = [noissues, noaudio, novideo, noaudiovideo]
        self.reportWidget.reportCombo.clear()
        for i in self.reportWidget.options:
            self.reportWidget.reportCombo.addItem(i)
        # --- End ReportWidget

    ###
    ### UI Logic
    ###

    def load_settings(self):
        """Load settings for Freeseer"""
        log.info("Loading settings...")

        # Load default language.
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talks as a SQL Data Model.
        self.load_event_list()

    def current_presentation(self):
        """Creates a presentation object of the current presentation.
        
        Current presentation is the currently selected title on the GUI.
        """
        # i = self.mainWidget.talkComboBox.currentIndex()
        # p_id = self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()
        return self.db.get_presentation(self.current_presentation_id())

    def current_presentation_id(self):
        """Returns the current selected presentation ID."""
        i = self.mainWidget.talkComboBox.currentIndex()
        return self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()

    def standby(self, state):
        """Prepares the GStreamer pipelines for recording

        Sets the pipeline to paused state so that initiating a recording
        does not have a delay due to GStreamer initialization.
        """

        def toggle_gui(state):
            """Toggles GUI components when standby is pressed"""
            self.mainWidget.standbyPushButton.setHidden(state)
            self.mainWidget.recordPushButton.setVisible(state)
            self.mainWidget.recordPushButton.setEnabled(state)
            self.mainWidget.pauseToolButton.setVisible(state)
            self.mainWidget.eventComboBox.setDisabled(state)
            self.mainWidget.roomComboBox.setDisabled(state)
            self.mainWidget.dateComboBox.setDisabled(state)
            self.mainWidget.talkComboBox.setDisabled(state)
            self.mainWidget.audioFeedbackCheckbox.setDisabled(state)

        if state:  # Prepare the pipelines
            if self.load_backend():
                toggle_gui(True)
                self.controller.pause()
                self.mainWidget.statusLabel.setText(self.readyString)
            else:
                toggle_gui(False)
                self.mainWidget.standbyPushButton.setChecked(False)
        else:
            toggle_gui(False)
            self.mainWidget.standbyPushButton.setChecked(False)

    def record(self, state):
        """The logic for recording and stopping recording."""

        if state:  # Start Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo_rec.png")
            sysIcon2 = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon2)
            self.systray.showMessage("Recording", "RECORDING")
            self.controller.record()
            self.mainWidget.recordPushButton.setText(self.stopString)
            self.recordAction.setText(self.stopString)

            # Hide if auto-hide is set.
            if self.config.auto_hide == True:
                self.hide_window()
                self.visibilityAction.setText(self.showWindowString)
                log.debug("auto-hide is enabled, main window is now hidden in systray.")

            self.mainWidget.statusLabel.setText(self.recordingString)

            # Start timer.
            self.timer.start(1000)

        else:  # Stop Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo.png")
            sysIcon = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon)
            self.controller.stop()
            self.mainWidget.pauseToolButton.setChecked(False)
            self.mainWidget.recordPushButton.setText(self.recordString)
            self.recordAction.setText(self.recordString)
            self.mainWidget.audioSlider.setValue(0)

            # Finally set the standby button back to unchecked position.
            self.standby(False)

            # Stop and reset timer.
            self.timer.stop()
            self.reset_timer()

            # Select next talk if there is one within 15 minutes.
            if self.current_event and self.current_room:
                starttime = QtCore.QDateTime().currentDateTime()
                stoptime = starttime.addSecs(900)
                talkid = self.db.get_talk_between_time(
                    self.current_event, self.current_room, starttime.toString(), stoptime.toString()
                )
                if talkid is not None:
                    for i in range(self.mainWidget.talkComboBox.count()):
                        if (
                            talkid
                            == self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()
                        ):
                            self.mainWidget.talkComboBox.setCurrentIndex(i)

    def pause(self, state):
        """Pause the recording"""
        if state:  # Pause Recording.
            self.controller.pause()
            log.info("Recording paused.")
            self.mainWidget.pauseToolButton.setToolTip(self.resumeString)
            self.mainWidget.statusLabel.setText(self.pausedString)
            self.timer.stop()
        elif self.mainWidget.recordPushButton.isChecked():
            self.controller.record()
            log.info("Recording unpaused.")
            self.mainWidget.pauseToolButton.setToolTip(self.pauseString)
            self.mainWidget.statusLabel.setText(self.recordingString)
            self.timer.start(1000)

    def load_backend(self):
        """Prepares the backend for recording"""
        if self.current_presentation():
            presentation = self.current_presentation()

        # If current presentation is no existant (empty talk database)
        # use a default recording name.
        else:
            presentation = Presentation(title=unicode("default"))

        if self.controller.load_backend(presentation):
            return True
        else:
            return False  # Error something failed while loading the backend

    def update_timer(self):
        """Updates the Elapsed Time displayed.
        
        Uses the statusLabel for the display.
        """
        time = "%d:%02d" % (self.time_minutes, self.time_seconds)
        self.time_seconds += 1
        if self.time_seconds == 60:
            self.time_seconds = 0
            self.time_minutes += 1

        self.mainWidget.statusLabel.setText(
            "Free Space: %s --- Elapsed Time: %s" % (get_free_space(self.config.videodir), time)
        )

    def reset_timer(self):
        """Resets the Elapsed Time."""
        self.time_minutes = 0
        self.time_seconds = 0

    def toggle_audio_feedback(self, enabled):
        """Enables or disables audio feedback according to checkbox state"""
        self.config.audio_feedback = enabled

    ###
    ### Talk Related
    ###

    def set_talk_tooltip(self, talk):
        self.mainWidget.talkComboBox.setToolTip(talk)

    def load_event_list(self):
        model = self.db.get_events_model()
        self.mainWidget.eventComboBox.setModel(model)

    def load_rooms_from_event(self, event):
        # self.disconnect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

        self.current_event = event

        model = self.db.get_rooms_model(self.current_event)
        self.mainWidget.roomComboBox.setModel(model)

        # self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

    def load_dates_from_event_room(self, change):
        event = str(self.mainWidget.eventComboBox.currentText())
        room = str(self.mainWidget.roomComboBox.currentText())
        model = self.db.get_dates_from_event_room_model(event, room)
        self.mainWidget.dateComboBox.setModel(model)

    def load_talks_from_date(self, date):
        self.current_room = str(self.mainWidget.roomComboBox.currentText())
        self.current_date = date

        model = self.db.get_talks_model(self.current_event, self.current_room, self.current_date)
        self.mainWidget.talkComboBox.setModel(model)

    ###
    ### Report Failure
    ###
    def show_report_widget(self):
        p = self.current_presentation()
        self.reportWidget.titleLabel2.setText(p.title)
        self.reportWidget.speakerLabel2.setText(p.speaker)
        self.reportWidget.eventLabel2.setText(p.event)
        self.reportWidget.roomLabel2.setText(p.room)
        self.reportWidget.timeLabel2.setText(p.time)

        # Get existing report if there is one.
        talk_id = self.current_presentation_id()
        f = self.db.get_report(talk_id)
        if f is not None:
            self.reportWidget.commentEdit.setText(f.comment)
            i = self.reportWidget.reportCombo.findText(f.indicator)
            self.reportWidget.reportCombo.setCurrentIndex(i)
            self.reportWidget.releaseCheckBox.setChecked(f.release)
        else:
            self.reportWidget.commentEdit.setText("")
            self.reportWidget.reportCombo.setCurrentIndex(0)
            self.reportWidget.releaseCheckBox.setChecked(False)

        self.reportWidget.show()

    def report(self):
        talk_id = self.current_presentation_id()
        presentation = self.current_presentation()
        i = self.reportWidget.reportCombo.currentIndex()

        failure = Failure(
            talk_id,
            self.reportWidget.commentEdit.text(),
            self.reportWidget.options[i],
            self.reportWidget.releaseCheckBox.isChecked(),
        )
        log.info(
            "Report Failure: %s, %s, %s, release form? %s"
            % (
                talk_id,
                self.reportWidget.commentEdit.text(),
                self.reportWidget.options[i],
                self.reportWidget.releaseCheckBox.isChecked(),
            )
        )

        self.db.insert_failure(failure)
        self.reportWidget.close()

    ###
    ### Misc.
    ###

    def _icon_activated(self, reason):
        if reason == QtGui.QSystemTrayIcon.Trigger:
            self.systray.menu.popup(QCursor.pos())
        if reason == QtGui.QSystemTrayIcon.DoubleClick:
            self.toggle_record_button()

    def hide_window(self):
        self.geometry = self.saveGeometry()
        self.hide()

    def show_window(self):
        if self.geometry is not None:
            self.restoreGeometry(self.geometry)
        self.show()

    def toggle_window_visibility(self):
        """Toggles the visibility of the Recording Main Window."""
        if self.isHidden():
            self.show_window()
            self.visibilityAction.setText(self.hideWindowString)
        else:
            self.hide_window()
            self.visibilityAction.setText(self.showWindowString)

    def toggle_record_button(self):
        self.mainWidget.standbyPushButton.toggle()
        self.mainWidget.recordPushButton.toggle()

    def audio_feedback(self, value):
        self.mainWidget.audioSlider.setValue(value)

    def open_video_directory(self):
        if sys.platform.startswith("linux"):
            os.system("xdg-open %s" % self.config.videodir)
        elif sys.platform.startswith("win32"):
            os.system("explorer %s" % self.config.videodir)
        else:
            log.info("Error: This command is not supported on the current OS.")

    def closeEvent(self, event):
        log.info("Exiting freeseer...")
        event.accept()

    """
    Client functions
    """

    def show_client_widget(self):
        self.current_presentation()
        self.clientWidget.show()

    """
    This function is for handling commands sent from the server to the client
    """

    def getAction(self):
        message = self.clientWidget.socket.read(self.clientWidget.socket.bytesAvailable())
        if message == "Record":
            self.mainWidget.standbyPushButton.toggle()
            self.mainWidget.recordPushButton.toggle()
            self.clientWidget.sendMessage("Started recording")
            log.info("Started recording by server's request")
        elif message == "Stop":
            self.mainWidget.recordPushButton.toggle()
            log.info("Stopping recording by server's request")
        elif message == "Pause" or "Resume":
            self.mainWidget.pauseToolButton.toggle()
            if message == "Pause":
                log.info("Paused recording by server's request")
            elif message == "Resume":
                log.info("Resumed recording by server's request")

    ###
    ### Utility
    ###
    def open_configtool(self):
        self.configToolApp.show()

    def open_talkeditor(self):
        self.talkEditorApp.show()
Example #14
0
class RecordApp(FreeseerApp):
    """Freeseer's main GUI class."""

    def __init__(self, profile, config):
        super(RecordApp, self).__init__(config)

        self.db = profile.get_database()
        self.controller = RecordingController(profile, self.db, self.config)

        self.recently_recorded_video = None

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.autoRecordWidget = AutoRecordWidget()
        self.configToolApp = ConfigToolApp(profile, config)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self.config, self.db)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.logStatusWidget = LogStatusWidget(self.logDialog)
        self.statusBar().addPermanentWidget(self.logStatusWidget, 1)
        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        # Initialize variables for auto-recording
        self.singleID = None
        self.timeUntilStart = None
        self.timeUntilEnd = None
        self.autoTalks = None
        self.recorded = False
        self.beforeStartTimer = QtCore.QTimer(self)
        self.beforeStartTimer.timeout.connect(self.start_single_record)
        self.beforeEndTimer = QtCore.QTimer(self)
        self.beforeEndTimer.timeout.connect(self.single_auto_record)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.actionAutoRecord = QtGui.QAction(self)
        leaveButtonShortcut = "Ctrl+R"
        self.actionAutoRecord.setShortcut(leaveButtonShortcut)
        self.actionAutoRecord.setCheckable(True)
        self.actionAutoRecord.setObjectName(_fromUtf8("actionAutoRecord"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)
        self.menuOptions.addAction(self.actionAutoRecord)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(_fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL('triggered()'), self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL('triggered()'), self.toggle_record_button)
        self.connect(self.systray, QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(self.mainWidget.eventComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_rooms_from_event)
        self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_dates_from_event_room)
        self.connect(self.mainWidget.dateComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_date)
        self.connect(self.mainWidget.talkComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.set_talk_tooltip)
        self.connect(self.mainWidget.standbyButton, QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.disengageButton, QtCore.SIGNAL("clicked()"), functools.partial(self.standby, state=False))
        self.connect(self.mainWidget.recordButton, QtCore.SIGNAL('clicked()'), self.record)
        self.connect(self.mainWidget.pauseButton, QtCore.SIGNAL('toggled(bool)'), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox, QtCore.SIGNAL('toggled(bool)'), self.toggle_audio_feedback)
        self.connect(self.mainWidget.playButton, QtCore.SIGNAL('clicked()'), self.play_video)

        self.connect(self.autoRecordWidget.leaveButton, QtCore.SIGNAL('clicked()'), functools.partial(self.auto_record, state=False))
        self.autoRecordWidget.leaveButton.setShortcut(leaveButtonShortcut)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL('triggered()'), self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL('triggered()'), self.open_talkeditor)
        self.connect(self.actionAutoRecord, QtCore.SIGNAL('toggled(bool)'), self.auto_record)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL('triggered()'), self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL('triggered()'), self.show_report_widget)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton, QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.pauseButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.pauseButton.setFocus()

        self.retranslate()

    ###
    ### Translation Related
    ###
    def retranslate(self):
        self.setWindowTitle(self.app.translate("RecordApp", "Freeseer - portable presentation recording station"))
        #
        # Reusable Strings
        #
        self.standbyString = self.app.translate("RecordApp", "Standby")
        self.disengageString = self.app.translate("RecordApp", "Leave record-mode")
        self.standbyTooltipString = self.app.translate("RecordApp", "Sets up the system for recording")
        self.disengageTooltipString = self.app.translate("RecordApp", "Go back to edit talk information or select a different talk")
        self.autoRecordString = self.app.translate("RecordApp", "Auto Record")
        self.recordString = self.app.translate("RecordApp", "Record")
        self.pauseString = self.app.translate("RecordApp", "Pause")
        self.resumeString = self.app.translate("RecordApp", "Resume")
        self.stopString = self.app.translate("RecordApp", "Stop")
        self.stopAutoString = self.app.translate("RecordApp", "Stop Auto Record")
        self.hideWindowString = self.app.translate("RecordApp", "Hide Main Window")
        self.showWindowString = self.app.translate("RecordApp", "Show Main Window")
        self.playVideoString = self.app.translate("RecordApp", "Play")

        # Status Bar messages
        self.idleString = self.app.translate("RecordApp", "Idle.")
        self.readyString = self.app.translate("RecordApp", "Ready.")
        self.recordingString = self.app.translate("RecordApp", "Recording")
        self.pausedString = self.app.translate("RecordApp", "Recording Paused.")
        self.freeSpaceString = self.app.translate("RecordApp", "Free Space:")
        self.elapsedTimeString = self.app.translate("RecordApp", "Elapsed Time:")
        # --- End Reusable Strings

        if self.mainWidget.is_recording and self.mainWidget.pauseButton.isChecked():
            self.mainWidget.statusLabel.setText(self.pausedString)
        elif self.mainWidget.is_recording and (not self.mainWidget.pauseButton.isChecked()):
            self.mainWidget.statusLabel.setText(self.recordingString)
        elif self.mainWidget.standbyButton.isChecked():
            self.mainWidget.statusLabel.setText(self.readyString)
        elif self.actionAutoRecord.isChecked():
            self.mainWidget.statusLabel.setText(self.autoRecordString)
        else:
            self.mainWidget.statusLabel.setText(u"{} {} --- {} ".format(self.freeSpaceString,
                                                                        get_free_space(self.config.videodir),
                                                                        self.idleString))

        #
        # Menubar
        #
        self.menuOptions.setTitle(self.app.translate("RecordApp", "&Options"))
        self.actionConfigTool.setText(self.app.translate("RecordApp", "&Configuration"))
        self.actionTalkEditor.setText(self.app.translate("RecordApp", "&Edit Talks"))
        self.actionAutoRecord.setText(self.autoRecordString)
        self.actionOpenVideoFolder.setText(self.app.translate("RecordApp", "&Open Video Directory"))
        self.actionReport.setText(self.app.translate("RecordApp", "&Report"))
        # --- End Menubar

        #
        # Systray
        #
        self.visibilityAction.setText(self.hideWindowString)
        self.recordAction.setText(self.recordString)
        # --- End Systray

        #
        # RecordingWidget
        #
        self.mainWidget.disengageButton.setText(self.disengageString)
        self.mainWidget.standbyButton.setText(self.standbyString)
        self.mainWidget.standbyButton.setToolTip(self.standbyTooltipString)
        self.mainWidget.disengageButton.setToolTip(self.disengageTooltipString)
        if self.mainWidget.is_recording:
            self.mainWidget.recordButton.setToolTip(self.stopString)
        else:
            self.mainWidget.recordButton.setToolTip(self.recordString)
        self.mainWidget.pauseButton.setText(self.pauseString)
        self.mainWidget.pauseButton.setToolTip(self.pauseString)
        self.mainWidget.eventLabel.setText(self.app.translate("RecordApp", "Event"))
        self.mainWidget.roomLabel.setText(self.app.translate("RecordApp", "Room"))
        self.mainWidget.dateLabel.setText(self.app.translate("RecordApp", "Date"))
        self.mainWidget.talkLabel.setText(self.app.translate("RecordApp", "Talk"))
        # --- End RecordingWidget

        #
        # ReportWidget
        #
        self.reportWidget.setWindowTitle(self.app.translate("RecordApp", "Reporting Tool"))
        self.reportWidget.titleLabel.setText(self.app.translate("RecordApp", "Title:"))
        self.reportWidget.speakerLabel.setText(self.app.translate("RecordApp", "Speaker:"))
        self.reportWidget.eventLabel.setText(self.app.translate("RecordApp", "Event:"))
        self.reportWidget.roomLabel.setText(self.app.translate("RecordApp", "Room:"))
        self.reportWidget.startTimeLabel.setText(self.app.translate("RecordApp", "Start Time:"))
        self.reportWidget.endTimeLabel.setText(self.app.translate("RecordApp", "End Time:"))
        self.reportWidget.commentLabel.setText(self.app.translate("RecordApp", "Comment"))
        self.reportWidget.releaseCheckBox.setText(self.app.translate("RecordApp", "Release Received"))
        self.reportWidget.closeButton.setText(self.app.translate("RecordApp", "Close"))
        self.reportWidget.reportButton.setText(self.app.translate("RecordApp", "Report"))

        # Logic for translating the report options
        noissues = self.app.translate("RecordApp", "No Issues")
        noaudio = self.app.translate("RecordApp", "No Audio")
        novideo = self.app.translate("RecordApp", "No Video")
        noaudiovideo = self.app.translate("RecordApp", "No Audio/Video")
        self.reportWidget.options = [noissues, noaudio, novideo, noaudiovideo]
        self.reportWidget.reportCombo.clear()
        for i in self.reportWidget.options:
            self.reportWidget.reportCombo.addItem(i)
        # --- End ReportWidget

        self.logStatusWidget.retranslate()

    ###
    ### UI Logic
    ###

    def load_settings(self):
        """Load settings for Freeseer"""
        log.info('Loading settings...')

        # Load default language.
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talks as a SQL Data Model.
        self.load_event_list()

    def current_presentation(self):
        """Creates a presentation object of the current presentation.

        Current presentation is the currently selected title on the GUI.
        """
        #i = self.mainWidget.talkComboBox.currentIndex()
        #p_id = self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()
        return self.db.get_presentation(self.current_presentation_id())

    def current_presentation_id(self):
        """Returns the current selected presentation ID."""
        i = self.mainWidget.talkComboBox.currentIndex()
        return self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()

    def standby(self, state):
        """Prepares the GStreamer pipelines for recording

        Sets the pipeline to paused state so that initiating a recording
        does not have a delay due to GStreamer initialization.
        """
        def toggle_gui(state):
            """Toggles GUI components when standby is pressed"""
            if state:
                self.mainWidget.standbyButton.setHidden(state)
                self.mainWidget.disengageButton.setVisible(state)
            else:
                self.mainWidget.disengageButton.setVisible(state)
                self.mainWidget.standbyButton.setHidden(state)

            self.mainWidget.recordButton.setEnabled(state)
            self.mainWidget.eventComboBox.setDisabled(state)
            self.mainWidget.roomComboBox.setDisabled(state)
            self.mainWidget.dateComboBox.setDisabled(state)
            self.mainWidget.talkComboBox.setDisabled(state)
            self.mainWidget.audioFeedbackCheckbox.setDisabled(state)

        if state:  # Prepare the pipelines
            if self.load_backend():
                toggle_gui(True)
                self.controller.pause()
                self.mainWidget.statusLabel.setText(u"{} {} --- {} ".format(self.freeSpaceString,
                                                                            get_free_space(self.config.videodir),
                                                                            self.readyString))
            else:
                toggle_gui(False)
                self.mainWidget.standbyButton.setChecked(False)
        else:
            toggle_gui(False)
            self.controller.stop()
            self.mainWidget.standbyButton.setChecked(False)

        self.mainWidget.playButton.setEnabled(False)

    def record(self):
        """The logic for recording and stopping recording."""

        if self.mainWidget.is_recording:  # Start Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo_rec.png")
            sysIcon2 = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon2)
            self.controller.record()
            self.mainWidget.recordButton.setToolTip(self.stopString)
            self.mainWidget.disengageButton.setEnabled(False)
            self.mainWidget.pauseButton.setEnabled(True)
            self.recordAction.setText(self.stopString)

            # Hide if auto-hide is set.
            if self.config.auto_hide:
                self.hide_window()
                self.visibilityAction.setText(self.showWindowString)
                log.debug('auto-hide is enabled, main window is now hidden in systray.')

            # Start timer.
            self.timer.start(1000)

        else:  # Stop Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo.png")
            sysIcon = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon)
            self.controller.stop()
            self.mainWidget.pauseButton.setChecked(False)
            self.mainWidget.recordButton.setToolTip(self.recordString)
            self.mainWidget.disengageButton.setEnabled(True)
            self.mainWidget.pauseButton.setEnabled(False)
            self.recordAction.setText(self.recordString)
            self.mainWidget.audioSlider.setValue(0)
            self.mainWidget.statusLabel.setText(u"{} {} --- {} ".format(self.freeSpaceString,
                                                                        get_free_space(self.config.videodir),
                                                                        self.idleString))

            # Finally set the standby button back to unchecked position.
            self.standby(False)

            # Stop and reset timer.
            self.timer.stop()
            self.reset_timer()

            #Show playback button
            self.mainWidget.playButton.setVisible(True)
            self.mainWidget.playButton.setEnabled(True)

            # Select next talk if there is one within 15 minutes.
            if self.current_event and self.current_room:
                starttime = QtCore.QDateTime().currentDateTime()
                stoptime = starttime.addSecs(900)
                talkid = self.db.get_talk_between_time(self.current_event, self.current_room,
                                                       starttime.toString(), stoptime.toString())

                if talkid is not None:
                    for i in range(self.mainWidget.talkComboBox.count()):
                        if talkid == self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString():
                            self.mainWidget.talkComboBox.setCurrentIndex(i)

    def _enable_disable_gui(self, state):
        """Disables GUI components when Auto Record is pressed, and enables them when Auto Record is released"""
        self.mainWidget.standbyButton.setDisabled(state)
        self.mainWidget.eventComboBox.setDisabled(state)
        self.mainWidget.roomComboBox.setDisabled(state)
        self.mainWidget.dateComboBox.setDisabled(state)
        self.mainWidget.talkComboBox.setDisabled(state)
        self.mainWidget.audioFeedbackCheckbox.setDisabled(state)

    def stop_auto_record_gui(self):
        """Sets the gui for stopping the auto record"""
        self.autoRecordWidget.stop_timer()
        self.autoRecordWidget.close()
        self._enable_disable_gui(False)
        self.recorded = False
        self.actionAutoRecord.setChecked(False)

    def auto_record(self, state):
        """Starts automated recording"""
        if state:
            # If there is a room selected, then it's possible to auto-record
            if self.current_room:
                self.autoTalks = self.db.get_talks_by_room_and_time(self.current_room)
                # Start recording if there are talks in database that can be auto-recorded
                if self.autoTalks.next():
                    # Set the cursor back to before the first record so that single_auto_record works properly
                    self.autoTalks.previous()
                    self._enable_disable_gui(True)
                    self.single_auto_record()
                else:
                    # Dialog for no talks to auto-record
                    QtGui.QMessageBox.information(self, 'No Talks to Record',
                        'There are no upcoming talks to auto-record in this room', QtGui.QMessageBox.Ok)
                    self.actionAutoRecord.setChecked(False)

            else:
                # Dialog that pops up when no room is selected
                QtGui.QMessageBox.information(self, 'No Room Selected',
                    'Please select a room to auto-record', QtGui.QMessageBox.Ok)
                self.actionAutoRecord.setChecked(False)
        else:
            self.beforeStartTimer.stop()
            self.beforeEndTimer.stop()
            self.controller.stop()
            self.stop_auto_record_gui()

        self.mainWidget.playButton.setEnabled(False)

    def single_auto_record(self):
        """Completes one display and record cycle of the auto-record feature.

        Stops the recording of the last talk if it exists, displays the countdown until the start of
        the next talk, and when the talk begins, records the talk while displaying the countdown until
        the end of the talk.
        """
        if self.recorded:
            self.controller.stop()
            self.recorded = False
            log.debug("Auto-recording for the current talk stopped.")

        if self.autoTalks.next():
            starttime = QtCore.QTime.fromString(self.autoTalks.value(8).toString())
            endtime = QtCore.QTime.fromString(self.autoTalks.value(9).toString())
            currenttime = QtCore.QTime.currentTime()

            if currenttime <= starttime:
                self.singleID = self.autoTalks.value(0).toString()
                title = self.autoTalks.value(1).toString()
                speaker = self.autoTalks.value(2).toString()

                # Time (in seconds) until recording for the talk starts
                self.timeUntilStart = currenttime.secsTo(starttime)
                # Time (in seconds) from the starttime to endtime of this talk
                self.timeUntilEnd = starttime.secsTo(endtime)

                # Display fullscreen countdown and talk info until talk starts
                self.autoRecordWidget.set_recording(False)
                self.autoRecordWidget.set_display_message(title, speaker)
                self.autoRecordWidget.start_timer(self.timeUntilStart)
                self.autoRecordWidget.showFullScreen()

                # Wait for talk to start, then change display and start recording
                self.beforeStartTimer.setInterval((self.timeUntilStart + 1) * 1000)
                self.beforeStartTimer.setSingleShot(True)
                self.beforeStartTimer.start()
            else:
                # Start time has already passed, so move on to next talk
                self.single_auto_record()
        else:
            self.stop_auto_record_gui()

    def start_single_record(self):
        """Begins the auto-recording of a single talk while displaying the countdown on screen"""
        self.autoRecordWidget.set_recording(True)
        self.autoRecordWidget.set_display_message()
        self.autoRecordWidget.start_timer(self.timeUntilEnd)
        if self.controller.record_talk_id(self.singleID):
            log.debug("Auto-recording for the current talk started.")
            self.recorded = True
        self.beforeEndTimer.setInterval((self.timeUntilEnd + 1) * 1000)
        self.beforeEndTimer.setSingleShot(True)
        self.beforeEndTimer.start()

    def pause(self, state):
        """Pause the recording"""
        if state:  # Pause Recording.
            self.controller.pause()
            log.info("Recording paused.")
            self.mainWidget.pauseButton.setToolTip(self.resumeString)
            self.mainWidget.statusLabel.setText(self.pausedString)
            self.timer.stop()
        elif self.mainWidget.is_recording:
            self.controller.record()
            log.info("Recording unpaused.")
            self.mainWidget.pauseButton.setToolTip(self.pauseString)
            self.timer.start(1000)

    def load_backend(self):
        """Prepares the backend for recording"""
        if self.current_presentation():
            presentation = self.current_presentation()

        # If current presentation is no existant (empty talk database)
        # use a default recording name.
        else:
            presentation = Presentation(title=unicode("default"))

        initialized, self.recently_recorded_video = self.controller.load_backend(presentation)
        if initialized:
            return True
        else:
            return False  # Error something failed while loading the backend

    def update_timer(self):
        """Updates the Elapsed Time displayed.

        Uses the statusLabel for the display.
        """
        frmt_time = "%d:%02d" % (self.time_minutes, self.time_seconds)
        self.time_seconds += 1
        if self.time_seconds == 60:
            self.time_seconds = 0
            self.time_minutes += 1

        self.mainWidget.statusLabel.setText(u"{} {} --- {} {} --- {}".format(self.elapsedTimeString,
                                                                             frmt_time,
                                                                             self.freeSpaceString,
                                                                             get_free_space(self.config.videodir),
                                                                             self.recordingString))

    def reset_timer(self):
        """Resets the Elapsed Time."""
        self.time_minutes = 0
        self.time_seconds = 0

    def toggle_audio_feedback(self, enabled):
        """Enables or disables audio feedback according to checkbox state"""
        self.config.audio_feedback = enabled

    ###
    ### Talk Related
    ###

    def set_talk_tooltip(self, talk):
        self.mainWidget.talkComboBox.setToolTip(talk)

    def load_event_list(self):
        model = self.db.get_events_model()
        self.mainWidget.eventComboBox.setModel(model)

    def load_rooms_from_event(self, event):
        #self.disconnect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

        self.current_event = event

        model = self.db.get_rooms_model(self.current_event)
        self.mainWidget.roomComboBox.setModel(model)

        #self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

    def load_dates_from_event_room(self, change):
        event = str(self.mainWidget.eventComboBox.currentText())
        room = str(self.mainWidget.roomComboBox.currentText())
        model = self.db.get_dates_from_event_room_model(event, room)
        self.mainWidget.dateComboBox.setModel(model)

    def load_talks_from_date(self, date):
        self.current_room = str(self.mainWidget.roomComboBox.currentText())
        self.current_date = date

        model = self.db.get_talks_model(self.current_event, self.current_room, self.current_date)
        self.mainWidget.talkComboBox.setModel(model)

    ###
    ### Report Failure
    ###
    def show_report_widget(self):
        p = self.current_presentation()
        self.reportWidget.titleLabel2.setText(p.title)
        self.reportWidget.speakerLabel2.setText(p.speaker)
        self.reportWidget.eventLabel2.setText(p.event)
        self.reportWidget.roomLabel2.setText(p.room)
        self.reportWidget.startTimeLabel2.setText(p.startTime)
        self.reportWidget.endTimeLabel2.setText(p.endTime)

        # Get existing report if there is one.
        talk_id = self.current_presentation_id()
        f = self.db.get_report(talk_id)
        if f is not None:
            self.reportWidget.commentEdit.setText(f.comment)
            i = self.reportWidget.reportCombo.findText(f.indicator)
            self.reportWidget.reportCombo.setCurrentIndex(i)
            self.reportWidget.releaseCheckBox.setChecked(f.release)
        else:
            self.reportWidget.commentEdit.setText("")
            self.reportWidget.reportCombo.setCurrentIndex(0)
            self.reportWidget.releaseCheckBox.setChecked(False)

        self.reportWidget.show()

    def report(self):
        talk_id = self.current_presentation_id()
        i = self.reportWidget.reportCombo.currentIndex()

        failure = Failure(talk_id, self.reportWidget.commentEdit.text(), self.reportWidget.options[i], self.reportWidget.releaseCheckBox.isChecked())
        log.info("Report Failure: %s, %s, %s, release form? %s" % (talk_id,
                                                                   self.reportWidget.commentEdit.text(),
                                                                   self.reportWidget.options[i],
                                                                   self.reportWidget.releaseCheckBox.isChecked()))

        self.db.insert_failure(failure)
        self.reportWidget.close()

    ###
    ### Misc.
    ###
    def _icon_activated(self, reason):
        if reason == QtGui.QSystemTrayIcon.Trigger:
            self.systray.menu.popup(QCursor.pos())
        if reason == QtGui.QSystemTrayIcon.DoubleClick:
            self.toggle_record_button()

    def hide_window(self):
        self.geometry = self.saveGeometry()
        self.hide()

    def show_window(self):
        if (self.geometry is not None):
            self.restoreGeometry(self.geometry)
        self.show()

    def toggle_window_visibility(self):
        """Toggles the visibility of the Recording Main Window."""
        if self.isHidden():
            self.show_window()
            self.visibilityAction.setText(self.hideWindowString)
        else:
            self.hide_window()
            self.visibilityAction.setText(self.showWindowString)

    def toggle_record_button(self):
        self.mainWidget.standbyButton.toggle()
        self.mainWidget.recordButton.toggle()

    def audio_feedback(self, value):
        self.mainWidget.audioSlider.setValue(value)

    def open_video_directory(self):
        if sys.platform.startswith("linux"):
            os.system("xdg-open %s" % self.config.videodir)
        elif sys.platform.startswith("win32"):
            os.system("explorer %s" % self.config.videodir)
        else:
            log.info("Error: This command is not supported on the current OS.")

    def closeEvent(self, event):
        log.info('Exiting freeseer...')
        event.accept()

    '''
    This function plays the most recently recorded video
    '''
    def play_video(self):
        if sys.platform.startswith("linux"):
            subprocess.call(["xdg-open", "{}/{}".format(self.config.videodir, self.recently_recorded_video)])
        if sys.platform.startswith("win32"):
            os.system("start {}".format(os.path.join(self.config.videodir, self.recently_recorded_video)))

    '''
    Client functions
    '''
    def show_client_widget(self):
        self.current_presentation()
        self.clientWidget.show()

    '''
    This function is for handling commands sent from the server to the client
    '''
    def getAction(self):
        message = self.clientWidget.socket.read(self.clientWidget.socket.bytesAvailable())
        if message == 'Record':
            self.mainWidget.standbyButton.toggle()
            self.mainWidget.recordButton.toggle()
            self.clientWidget.sendMessage('Started recording')
            log.info("Started recording by server's request")
        elif message == 'Stop':
            self.mainWidget.recordButton.toggle()
            log.info("Stopping recording by server's request")
        elif message == 'Pause' or 'Resume':
            self.mainWidget.pauseButton.toggle()
            if message == 'Pause':
                log.info("Paused recording by server's request")
            elif message == 'Resume':
                log.info("Resumed recording by server's request")

    ###
    ### Utility
    ###
    def open_configtool(self):
        self.configToolApp.show()

    def open_talkeditor(self):
        self.talkEditorApp.show()
        self.load_event_list()
Example #15
0
class RecordApp(FreeseerApp):
    """Freeseer's main GUI class."""
    def __init__(self):
        FreeseerApp.__init__(self)

        self.controller = RecordingController()
        self.config = self.controller.config
        self.db = self.controller.db

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.clientWidget = ClientDialog(self.config.configdir, self.db)
        self.configToolApp = ConfigToolApp(self)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(_fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        self.actionClient = QtGui.QAction(self)
        self.actionClient.setIcon(self.icon)
        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        # Hide the controller client configuration screen for Freeseer 3.0.0
        # release. This feature's not ready for public use so lets keep it
        # hidden for now.
        #self.menuFile.insertAction(self.actionExit, self.actionClient)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL('triggered()'), self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL('triggered()'), self.toggle_record_button)
        self.connect(self.systray, QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(self.mainWidget.eventComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_rooms_from_event)
        self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_dates_from_event_room)
        self.connect(self.mainWidget.dateComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_date)
        self.connect(self.mainWidget.talkComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.set_talk_tooltip)
        self.connect(self.mainWidget.standbyPushButton, QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.recordPushButton, QtCore.SIGNAL('toggled(bool)'), self.record)
        self.connect(self.mainWidget.pauseToolButton, QtCore.SIGNAL('toggled(bool)'), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox, QtCore.SIGNAL('toggled(bool)'), self.toggle_audio_feedback)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL('triggered()'), self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL('triggered()'), self.open_talkeditor)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL('triggered()'), self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL('triggered()'), self.show_report_widget)
        self.connect(self.actionClient, QtCore.SIGNAL('triggered()'), self.show_client_widget)

        # GUI Disabling/Enabling Connections
        self.connect(self.mainWidget.recordPushButton, QtCore.SIGNAL("toggled(bool)"), self.mainWidget.pauseToolButton.setEnabled)

        #Client Connections
        self.connect(self.clientWidget.socket, QtCore.SIGNAL('readyRead()'), self.getAction)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton, QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.recordPushButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.recordPushButton.setFocus()

        self.retranslate()

    ###
    ### Translation Related
    ###
    def retranslate(self):
        self.clientWidget.retranslate(self.current_language)

        self.setWindowTitle(self.app.translate("RecordApp", "Freeseer - portable presentation recording station"))
        #
        # Reusable Strings
        #
        self.standbyString = self.app.translate("RecordApp", "Standby")
        self.recordString = self.app.translate("RecordApp", "Record")
        self.pauseString = self.app.translate("RecordApp", "Pause")
        self.resumeString = self.app.translate("RecordApp", "Resume")
        self.stopString = self.app.translate("RecordApp", "Stop")
        self.hideWindowString = self.app.translate("RecordApp", "Hide Main Window")
        self.showWindowString = self.app.translate("RecordApp", "Show Main Window")

        # Status Bar messages
        self.idleString = self.app.translate("RecordApp", "Idle.")
        self.readyString = self.app.translate("RecordApp", "Ready.")
        self.recordingString = self.app.translate("RecordApp", "Recording...")
        self.pausedString = self.app.translate("RecordApp", "Recording Paused.")
        # --- End Reusable Strings

        if self.mainWidget.recordPushButton.isChecked() and self.mainWidget.pauseToolButton.isChecked():
            self.mainWidget.statusLabel.setText(self.pausedString)
        elif self.mainWidget.recordPushButton.isChecked() and (not self.mainWidget.pauseToolButton.isChecked()):
            self.mainWidget.statusLabel.setText(self.recordingString)
        elif self.mainWidget.standbyPushButton.isChecked():
            self.mainWidget.statusLabel.setText(self.readyString)
        else:
            self.mainWidget.statusLabel.setText(self.idleString)

        #
        # Menubar
        #
        self.menuOptions.setTitle(self.app.translate("RecordApp", "&Options"))
        self.actionConfigTool.setText(self.app.translate("RecordApp", "&Configuration"))
        self.actionTalkEditor.setText(self.app.translate("RecordApp", "&Edit Talks"))
        self.actionOpenVideoFolder.setText(self.app.translate("RecordApp", "&Open Video Directory"))
        self.actionClient.setText(self.app.translate("RecordApp", "&Connect to server"))
        self.actionReport.setText(self.app.translate("RecordApp", "&Report"))
        # --- End Menubar

        #
        # Systray
        #
        self.visibilityAction.setText(self.hideWindowString)
        self.recordAction.setText(self.recordString)
        # --- End Systray

        #
        # RecordingWidget
        #
        self.mainWidget.standbyPushButton.setText(self.standbyString)
        self.mainWidget.standbyPushButton.setToolTip(self.standbyString)
        if self.mainWidget.recordPushButton.isChecked():
            self.mainWidget.recordPushButton.setText(self.stopString)
            self.mainWidget.recordPushButton.setToolTip(self.stopString)
        else:
            self.mainWidget.recordPushButton.setText(self.recordString)
            self.mainWidget.recordPushButton.setToolTip(self.recordString)
        self.mainWidget.pauseToolButton.setText(self.pauseString)
        self.mainWidget.pauseToolButton.setToolTip(self.pauseString)
        self.mainWidget.eventLabel.setText(self.app.translate("RecordApp", "Event"))
        self.mainWidget.roomLabel.setText(self.app.translate("RecordApp", "Room"))
        self.mainWidget.dateLabel.setText(self.app.translate("RecordApp", "Date"))
        self.mainWidget.talkLabel.setText(self.app.translate("RecordApp", "Talk"))
        # --- End RecordingWidget

        #
        # ReportWidget
        #
        self.reportWidget.setWindowTitle(self.app.translate("RecordApp", "Reporting Tool"))
        self.reportWidget.titleLabel.setText(self.app.translate("RecordApp", "Title:"))
        self.reportWidget.speakerLabel.setText(self.app.translate("RecordApp", "Speaker:"))
        self.reportWidget.eventLabel.setText(self.app.translate("RecordApp", "Event:"))
        self.reportWidget.roomLabel.setText(self.app.translate("RecordApp", "Room:"))
        self.reportWidget.timeLabel.setText(self.app.translate("RecordApp", "Time:"))
        self.reportWidget.commentLabel.setText(self.app.translate("RecordApp", "Comment"))
        self.reportWidget.releaseCheckBox.setText(self.app.translate("RecordApp", "Release Received"))
        self.reportWidget.closeButton.setText(self.app.translate("RecordApp", "Close"))
        self.reportWidget.reportButton.setText(self.app.translate("RecordApp", "Report"))

        # Logic for translating the report options
        noissues = self.app.translate("RecordApp", "No Issues")
        noaudio = self.app.translate("RecordApp", "No Audio")
        novideo = self.app.translate("RecordApp", "No Video")
        noaudiovideo = self.app.translate("RecordApp", "No Audio/Video")
        self.reportWidget.options = [noissues, noaudio, novideo, noaudiovideo]
        self.reportWidget.reportCombo.clear()
        for i in self.reportWidget.options:
            self.reportWidget.reportCombo.addItem(i)
        # --- End ReportWidget

    ###
    ### UI Logic
    ###

    def load_settings(self):
        """Load settings for Freeseer"""
        log.info('Loading settings...')

        # Load default language.
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talks as a SQL Data Model.
        self.load_event_list()

    def current_presentation(self):
        """Creates a presentation object of the current presentation.

        Current presentation is the currently selected title on the GUI.
        """
        #i = self.mainWidget.talkComboBox.currentIndex()
        #p_id = self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()
        return self.db.get_presentation(self.current_presentation_id())

    def current_presentation_id(self):
        """Returns the current selected presentation ID."""
        i = self.mainWidget.talkComboBox.currentIndex()
        return self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString()

    def standby(self, state):
        """Prepares the GStreamer pipelines for recording

        Sets the pipeline to paused state so that initiating a recording
        does not have a delay due to GStreamer initialization.
        """
        def toggle_gui(state):
            """Toggles GUI components when standby is pressed"""
            self.mainWidget.standbyPushButton.setHidden(state)
            self.mainWidget.recordPushButton.setVisible(state)
            self.mainWidget.recordPushButton.setEnabled(state)
            self.mainWidget.pauseToolButton.setVisible(state)
            self.mainWidget.eventComboBox.setDisabled(state)
            self.mainWidget.roomComboBox.setDisabled(state)
            self.mainWidget.dateComboBox.setDisabled(state)
            self.mainWidget.talkComboBox.setDisabled(state)
            self.mainWidget.audioFeedbackCheckbox.setDisabled(state)

        if (state):  # Prepare the pipelines
            if self.load_backend():
                toggle_gui(True)
                self.controller.pause()
                self.mainWidget.statusLabel.setText(self.readyString)
            else:
                toggle_gui(False)
                self.mainWidget.standbyPushButton.setChecked(False)
        else:
            toggle_gui(False)
            self.mainWidget.standbyPushButton.setChecked(False)

    def record(self, state):
        """The logic for recording and stopping recording."""

        if state:  # Start Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo_rec.png")
            sysIcon2 = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon2)
            self.systray.showMessage("Recording", "RECORDING")
            self.controller.record()
            self.mainWidget.recordPushButton.setText(self.stopString)
            self.recordAction.setText(self.stopString)

            # Hide if auto-hide is set.
            if self.config.auto_hide:
                self.hide_window()
                self.visibilityAction.setText(self.showWindowString)
                log.debug('auto-hide is enabled, main window is now hidden in systray.')

            self.mainWidget.statusLabel.setText(self.recordingString)

            # Start timer.
            self.timer.start(1000)

        else:  # Stop Recording.
            logo_rec = QtGui.QPixmap(":/freeseer/logo.png")
            sysIcon = QtGui.QIcon(logo_rec)
            self.systray.setIcon(sysIcon)
            self.controller.stop()
            self.mainWidget.pauseToolButton.setChecked(False)
            self.mainWidget.recordPushButton.setText(self.recordString)
            self.recordAction.setText(self.recordString)
            self.mainWidget.audioSlider.setValue(0)

            # Finally set the standby button back to unchecked position.
            self.standby(False)

            # Stop and reset timer.
            self.timer.stop()
            self.reset_timer()

            # Select next talk if there is one within 15 minutes.
            if self.current_event and self.current_room:
                starttime = QtCore.QDateTime().currentDateTime()
                stoptime = starttime.addSecs(900)
                talkid = self.db.get_talk_between_time(self.current_event, self.current_room,
                                                       starttime.toString(), stoptime.toString())
                if talkid is not None:
                    for i in range(self.mainWidget.talkComboBox.count()):
                        if talkid == self.mainWidget.talkComboBox.model().index(i, 1).data(QtCore.Qt.DisplayRole).toString():
                            self.mainWidget.talkComboBox.setCurrentIndex(i)

    def pause(self, state):
        """Pause the recording"""
        if (state):  # Pause Recording.
            self.controller.pause()
            log.info("Recording paused.")
            self.mainWidget.pauseToolButton.setToolTip(self.resumeString)
            self.mainWidget.statusLabel.setText(self.pausedString)
            self.timer.stop()
        elif self.mainWidget.recordPushButton.isChecked():
            self.controller.record()
            log.info("Recording unpaused.")
            self.mainWidget.pauseToolButton.setToolTip(self.pauseString)
            self.mainWidget.statusLabel.setText(self.recordingString)
            self.timer.start(1000)

    def load_backend(self):
        """Prepares the backend for recording"""
        if self.current_presentation():
            presentation = self.current_presentation()

        # If current presentation is no existant (empty talk database)
        # use a default recording name.
        else:
            presentation = Presentation(title=unicode("default"))

        if self.controller.load_backend(presentation):
            return True
        else:
            return False  # Error something failed while loading the backend

    def update_timer(self):
        """Updates the Elapsed Time displayed.

        Uses the statusLabel for the display.
        """
        time = "%d:%02d" % (self.time_minutes, self.time_seconds)
        self.time_seconds += 1
        if self.time_seconds == 60:
            self.time_seconds = 0
            self.time_minutes += 1

        self.mainWidget.statusLabel.setText("Free Space: %s --- Elapsed Time: %s" %
                        (get_free_space(self.config.videodir), time))

    def reset_timer(self):
        """Resets the Elapsed Time."""
        self.time_minutes = 0
        self.time_seconds = 0

    def toggle_audio_feedback(self, enabled):
        """Enables or disables audio feedback according to checkbox state"""
        self.config.audio_feedback = enabled

    ###
    ### Talk Related
    ###

    def set_talk_tooltip(self, talk):
        self.mainWidget.talkComboBox.setToolTip(talk)

    def load_event_list(self):
        model = self.db.get_events_model()
        self.mainWidget.eventComboBox.setModel(model)

    def load_rooms_from_event(self, event):
        #self.disconnect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

        self.current_event = event

        model = self.db.get_rooms_model(self.current_event)
        self.mainWidget.roomComboBox.setModel(model)

        #self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_room)

    def load_dates_from_event_room(self, change):
        event = str(self.mainWidget.eventComboBox.currentText())
        room = str(self.mainWidget.roomComboBox.currentText())
        model = self.db.get_dates_from_event_room_model(event, room)
        self.mainWidget.dateComboBox.setModel(model)

    def load_talks_from_date(self, date):
        self.current_room = str(self.mainWidget.roomComboBox.currentText())
        self.current_date = date

        model = self.db.get_talks_model(self.current_event, self.current_room, self.current_date)
        self.mainWidget.talkComboBox.setModel(model)

    ###
    ### Report Failure
    ###
    def show_report_widget(self):
        p = self.current_presentation()
        self.reportWidget.titleLabel2.setText(p.title)
        self.reportWidget.speakerLabel2.setText(p.speaker)
        self.reportWidget.eventLabel2.setText(p.event)
        self.reportWidget.roomLabel2.setText(p.room)
        self.reportWidget.timeLabel2.setText(p.time)

        # Get existing report if there is one.
        talk_id = self.current_presentation_id()
        f = self.db.get_report(talk_id)
        if f is not None:
            self.reportWidget.commentEdit.setText(f.comment)
            i = self.reportWidget.reportCombo.findText(f.indicator)
            self.reportWidget.reportCombo.setCurrentIndex(i)
            self.reportWidget.releaseCheckBox.setChecked(f.release)
        else:
            self.reportWidget.commentEdit.setText("")
            self.reportWidget.reportCombo.setCurrentIndex(0)
            self.reportWidget.releaseCheckBox.setChecked(False)

        self.reportWidget.show()

    def report(self):
        talk_id = self.current_presentation_id()
        presentation = self.current_presentation()
        i = self.reportWidget.reportCombo.currentIndex()

        failure = Failure(talk_id, self.reportWidget.commentEdit.text(), self.reportWidget.options[i], self.reportWidget.releaseCheckBox.isChecked())
        log.info("Report Failure: %s, %s, %s, release form? %s" % (talk_id,
                                                                   self.reportWidget.commentEdit.text(),
                                                                   self.reportWidget.options[i],
                                                                   self.reportWidget.releaseCheckBox.isChecked()))

        self.db.insert_failure(failure)
        self.reportWidget.close()

    ###
    ### Misc.
    ###

    def _icon_activated(self, reason):
        if reason == QtGui.QSystemTrayIcon.Trigger:
            self.systray.menu.popup(QCursor.pos())
        if reason == QtGui.QSystemTrayIcon.DoubleClick:
            self.toggle_record_button()

    def hide_window(self):
        self.geometry = self.saveGeometry()
        self.hide()

    def show_window(self):
        if (self.geometry is not None):
            self.restoreGeometry(self.geometry)
        self.show()

    def toggle_window_visibility(self):
        """Toggles the visibility of the Recording Main Window."""
        if self.isHidden():
            self.show_window()
            self.visibilityAction.setText(self.hideWindowString)
        else:
            self.hide_window()
            self.visibilityAction.setText(self.showWindowString)

    def toggle_record_button(self):
        self.mainWidget.standbyPushButton.toggle()
        self.mainWidget.recordPushButton.toggle()

    def audio_feedback(self, value):
        self.mainWidget.audioSlider.setValue(value)

    def open_video_directory(self):
        if sys.platform.startswith("linux"):
            os.system("xdg-open %s" % self.config.videodir)
        elif sys.platform.startswith("win32"):
            os.system("explorer %s" % self.config.videodir)
        else:
            log.info("Error: This command is not supported on the current OS.")

    def closeEvent(self, event):
        log.info('Exiting freeseer...')
        event.accept()

    '''
    Client functions
    '''
    def show_client_widget(self):
        self.current_presentation()
        self.clientWidget.show()

    '''
    This function is for handling commands sent from the server to the client
    '''
    def getAction(self):
        message = self.clientWidget.socket.read(self.clientWidget.socket.bytesAvailable())
        if message == 'Record':
            self.mainWidget.standbyPushButton.toggle()
            self.mainWidget.recordPushButton.toggle()
            self.clientWidget.sendMessage('Started recording')
            log.info("Started recording by server's request")
        elif message == 'Stop':
            self.mainWidget.recordPushButton.toggle()
            log.info("Stopping recording by server's request")
        elif message == 'Pause' or 'Resume':
            self.mainWidget.pauseToolButton.toggle()
            if message == 'Pause':
                log.info("Paused recording by server's request")
            elif message == 'Resume':
                log.info("Resumed recording by server's request")

    ###
    ### Utility
    ###
    def open_configtool(self):
        self.configToolApp.show()

    def open_talkeditor(self):
        self.talkEditorApp.show()
Example #16
0
class TestTalkEditorApp(unittest.TestCase):
    '''
    Test suite to verify the functionality of the TalkEditorApp class.

    Tests interact like an end user (using QtTest). Expect the app to be rendered.

    '''

    def setUp(self):
        '''
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and TalkEditorApp object.
        TalkEditorApp.show() causes the UI to be rendered.
        '''
        self.profile_manager = ProfileManager(tempfile.mkdtemp())
        profile = self.profile_manager.get('testing')
        config = profile.get_config('freeseer.conf', settings.FreeseerConfig,
                                    storage_args=['Global'], read_only=True)
        db = profile.get_database()

        self.app = QtGui.QApplication([])
        self.talk_editor = TalkEditorApp(config, db)
        self.talk_editor.show()

    def tearDown(self):
        '''
        Standard tear down method. Runs after each test_* method.

        This method closes the TalkEditorApp by clicking the "close" button
        '''
        shutil.rmtree(self.profile_manager._base_folder)

        del self.app
        self.talk_editor.app.deleteLater()

    # def test_add_talk(self):
    #     '''
    #     Tests a user creating a talk and adding it.
    #     '''

    #     QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton, Qt.Qt.LeftButton)
    #     self.assertFalse(self.talk_editor.editorWidget.isVisible())
    #     self.assertTrue(self.talk_editor.addTalkWidget.isVisible())

    #     mTitle = "This is a test"
    #     mPresenter = "Me, myself, and I"
    #     mEvent = "0 THIS St."
    #     mRoom = "Room 13"

    #     # populate talk data (date and time are prepopulated)
    #     self.talk_editor.addTalkWidget.titleLineEdit.setText(mTitle)
    #     self.talk_editor.addTalkWidget.presenterLineEdit.setText(mPresenter)
    #     self.talk_editor.addTalkWidget.eventLineEdit.setText(mEvent)
    #     self.talk_editor.addTalkWidget.roomLineEdit.setText(mRoom)

    #     # add in the talk
    #     QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.addButton, Qt.Qt.LeftButton)

    #     # find our talk (ensure it was added)
    #     found = False
    #     row_count = self.talk_editor.editorWidget.editor.model().rowCount() - 1
    #     while row_count >= 0 and not found:  # should be at the end, but you never know
    #         if self.talk_editor.editorWidget.editor.model().index(row_count, 1).data() == mTitle and \
    #                 self.talk_editor.editorWidget.editor.model().index(row_count, 2).data() == mPresenter and \
    #                 self.talk_editor.editorWidget.editor.model().index(row_count, 5).data() == mEvent and \
    #                 self.talk_editor.editorWidget.editor.model().index(row_count, 6).data() == mRoom:
    #                 found = True
    #                 # TODO: Select this row
    #         row_count -= 1

    #     self.assertTrue(found, "Couldn't find talk just inserted...")

    #     # now delete the talk we just created
    #     QtTest.QTest.mouseClick(self.talk_editor.editorWidget.removeButton, Qt.Qt.LeftButton)

    def test_file_menu_quit(self):
        '''
        Tests TalkEditorApp's File->Quit
        '''

        self.assertTrue(self.talk_editor.isVisible())

        # File->Quit
        self.talk_editor.actionExit.trigger()
        self.assertFalse(self.talk_editor.isVisible())

    def test_help_menu_about(self):
        '''
        Tests TalkEditorApp's Help->About
        '''

        self.assertTrue(self.talk_editor.isVisible())

        # Help->About
        self.talk_editor.actionAbout.trigger()
        self.assertFalse(self.talk_editor.hasFocus())
        self.assertTrue(self.talk_editor.aboutDialog.isVisible())

        # Click "Close"
        QtTest.QTest.mouseClick(self.talk_editor.aboutDialog.closeButton, Qt.Qt.LeftButton)
        self.assertFalse(self.talk_editor.aboutDialog.isVisible())
Example #17
0
    def __init__(self):
        FreeseerApp.__init__(self)

        self.controller = RecordingController()
        self.config = self.controller.config
        self.db = self.controller.db

        self.resize(550, 450)

        # Setup custom widgets
        self.mainWidget = RecordingWidget()
        self.setCentralWidget(self.mainWidget)
        self.reportWidget = ReportDialog()
        self.reportWidget.setModal(True)
        self.clientWidget = ClientDialog(self.config.configdir, self.db)
        self.configToolApp = ConfigToolApp(self)
        self.configToolApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.configToolApp.setWindowFlags(QtCore.Qt.Dialog)
        self.talkEditorApp = TalkEditorApp(self)
        self.talkEditorApp.setWindowModality(QtCore.Qt.ApplicationModal)
        self.talkEditorApp.setWindowFlags(QtCore.Qt.Dialog)

        self.statusBar().addPermanentWidget(self.mainWidget.statusLabel)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None
        self.current_event = None
        self.current_room = None
        self.controller.set_window_id(self.mainWidget.previewWidget.winId())
        self.controller.set_audio_feedback_handler(self.audio_feedback)

        # Set timer for recording how much time elapsed during a recording
        self.reset_timer()
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_timer)

        #
        # Setup Menubar
        #

        # Build the options Menu, TalkEditor and ConfigTool
        self.menuOptions = QtGui.QMenu(self.menubar)
        self.menuOptions.setObjectName(_fromUtf8("menuOptions"))
        self.menubar.insertMenu(self.menuHelp.menuAction(), self.menuOptions)
        self.actionConfigTool = QtGui.QAction(self)
        self.actionConfigTool.setShortcut("Ctrl+C")
        self.actionConfigTool.setObjectName(_fromUtf8("actionConfigTool"))
        self.actionTalkEditor = QtGui.QAction(self)
        self.actionTalkEditor.setShortcut("Ctrl+E")
        self.actionTalkEditor.setObjectName(_fromUtf8("actionTalkEditor"))
        self.menuOptions.addAction(self.actionConfigTool)
        self.menuOptions.addAction(self.actionTalkEditor)

        folderIcon = QtGui.QIcon.fromTheme("folder")
        self.actionOpenVideoFolder = QtGui.QAction(self)
        self.actionOpenVideoFolder.setShortcut("Ctrl+O")
        self.actionOpenVideoFolder.setObjectName(_fromUtf8("actionOpenVideoFolder"))
        self.actionOpenVideoFolder.setIcon(folderIcon)

        self.actionReport = QtGui.QAction(self)
        self.actionReport.setObjectName(_fromUtf8("actionReport"))

        self.actionClient = QtGui.QAction(self)
        self.actionClient.setIcon(self.icon)
        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionOpenVideoFolder)
        # Hide the controller client configuration screen for Freeseer 3.0.0
        # release. This feature's not ready for public use so lets keep it
        # hidden for now.
        #self.menuFile.insertAction(self.actionExit, self.actionClient)
        self.menuHelp.addAction(self.actionReport)
        # --- End Menubar

        #
        # Systray Setup
        #
        self.systray = QtGui.QSystemTrayIcon(self.icon)
        self.systray.show()
        self.systray.menu = QtGui.QMenu()
        self.systray.setContextMenu(self.systray.menu)

        self.visibilityAction = QtGui.QAction(self)
        self.recordAction = QtGui.QAction(self)

        self.systray.menu.addAction(self.visibilityAction)
        self.systray.menu.addAction(self.recordAction)

        self.connect(self.visibilityAction, QtCore.SIGNAL('triggered()'), self.toggle_window_visibility)
        self.connect(self.recordAction, QtCore.SIGNAL('triggered()'), self.toggle_record_button)
        self.connect(self.systray, QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self._icon_activated)
        # --- End Systray Setup

        # main tab connections
        self.connect(self.mainWidget.eventComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_rooms_from_event)
        self.connect(self.mainWidget.roomComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_dates_from_event_room)
        self.connect(self.mainWidget.dateComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.load_talks_from_date)
        self.connect(self.mainWidget.talkComboBox, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.set_talk_tooltip)
        self.connect(self.mainWidget.standbyPushButton, QtCore.SIGNAL("toggled(bool)"), self.standby)
        self.connect(self.mainWidget.recordPushButton, QtCore.SIGNAL('toggled(bool)'), self.record)
        self.connect(self.mainWidget.pauseToolButton, QtCore.SIGNAL('toggled(bool)'), self.pause)
        self.connect(self.mainWidget.audioFeedbackCheckbox, QtCore.SIGNAL('toggled(bool)'), self.toggle_audio_feedback)

        # Main Window Connections
        self.connect(self.actionConfigTool, QtCore.SIGNAL('triggered()'), self.open_configtool)
        self.connect(self.actionTalkEditor, QtCore.SIGNAL('triggered()'), self.open_talkeditor)
        self.connect(self.actionOpenVideoFolder, QtCore.SIGNAL('triggered()'), self.open_video_directory)
        self.connect(self.actionReport, QtCore.SIGNAL('triggered()'), self.show_report_widget)
        self.connect(self.actionClient, QtCore.SIGNAL('triggered()'), self.show_client_widget)

        # GUI Disabling/Enabling Connections
        self.connect(self.mainWidget.recordPushButton, QtCore.SIGNAL("toggled(bool)"), self.mainWidget.pauseToolButton.setEnabled)

        #Client Connections
        self.connect(self.clientWidget.socket, QtCore.SIGNAL('readyRead()'), self.getAction)

        #
        # ReportWidget Connections
        #
        self.connect(self.reportWidget.reportButton, QtCore.SIGNAL("clicked()"), self.report)

        self.load_settings()

        # Setup spacebar key.
        self.mainWidget.recordPushButton.setShortcut(QtCore.Qt.Key_Space)
        self.mainWidget.recordPushButton.setFocus()

        self.retranslate()
Example #18
0
class TestTalkEditorApp(unittest.TestCase):
    '''
    Test suite to verify the functionality of the TalkEditorApp class.

    Tests interact like an end user (using QtTest). Expect the app to be rendered.

    '''
    def setUp(self):
        '''
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and TalkEditorApp object.
        TalkEditorApp.show() causes the UI to be rendered.
        '''
        settings.configdir = tempfile.mkdtemp()

        self.app = QtGui.QApplication([])
        self.talk_editor = TalkEditorApp()
        self.talk_editor.show()

    def tearDown(self):
        '''
        Standard tear down method. Runs after each test_* method.

        This method closes the TalkEditorApp by clicking the "close" button
        '''
        shutil.rmtree(settings.configdir)

        QtTest.QTest.mouseClick(self.talk_editor.editorWidget.closeButton,
                                Qt.Qt.LeftButton)
        del self.app
        del self.talk_editor.app

    def test_add_talk(self):
        '''
        Tests a user creating a talk and adding it.
        '''

        QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton,
                                Qt.Qt.LeftButton)
        self.assertFalse(self.talk_editor.editorWidget.isVisible())
        self.assertTrue(self.talk_editor.addTalkWidget.isVisible())

        mTitle = "This is a test"
        mPresenter = "Me, myself, and I"
        mEvent = "0 THIS St."
        mRoom = "Room 13"

        # populate talk data (date and time are prepopulated)
        self.talk_editor.addTalkWidget.titleLineEdit.setText(mTitle)
        self.talk_editor.addTalkWidget.presenterLineEdit.setText(mPresenter)
        self.talk_editor.addTalkWidget.eventLineEdit.setText(mEvent)
        self.talk_editor.addTalkWidget.roomLineEdit.setText(mRoom)

        # add in the talk
        QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.addButton,
                                Qt.Qt.LeftButton)

        # find our talk (ensure it was added)
        found = False
        row_count = self.talk_editor.editorWidget.editor.model().rowCount() - 1
        while row_count >= 0 and not found:  # should be at the end, but you never know
            if self.talk_editor.editorWidget.editor.model().index(row_count, 1).data() == mTitle and \
                    self.talk_editor.editorWidget.editor.model().index(row_count, 2).data() == mPresenter and \
                    self.talk_editor.editorWidget.editor.model().index(row_count, 5).data() == mEvent and \
                    self.talk_editor.editorWidget.editor.model().index(row_count, 6).data() == mRoom:
                found = True
                # TODO: Select this row
            row_count -= 1

        self.assertTrue(found, "Couldn't find talk just inserted...")

        # now delete the talk we just created
        QtTest.QTest.mouseClick(self.talk_editor.editorWidget.removeButton,
                                Qt.Qt.LeftButton)

    def test_add_talk_cancel(self):
        '''
        Tests a user creating a talk, but cancelling it instead of adding it.
        '''

        QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton,
                                Qt.Qt.LeftButton)
        self.assertFalse(self.talk_editor.editorWidget.isVisible())
        self.assertTrue(self.talk_editor.addTalkWidget.isVisible())

        QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.cancelButton,
                                Qt.Qt.LeftButton)
        self.assertFalse(self.talk_editor.addTalkWidget.isVisible())
        self.assertTrue(self.talk_editor.editorWidget.isVisible())

    def test_close_talkeditor(self):
        '''
        Tests the "close" button.
        Although we close the app using this button after every test (in tearDown()),
        we are not guaranteed a valid test case in tearDown().
        '''

        QtTest.QTest.mouseClick(self.talk_editor.editorWidget.closeButton,
                                Qt.Qt.LeftButton)
        self.assertFalse(self.talk_editor.editorWidget.isVisible())

    def test_clear_all_talks(self):
        '''
        Tests the "clear" button on the main window.
        '''

        if self.talk_editor.editorWidget.editor.model().rowCount() == 0:
            QtTest.QTest.mouseClick(self.talk_editor.editorWidget.addButton,
                                    Qt.Qt.LeftButton)
            mTitle = "This is a test"
            mPresenter = "Me, myself, and I"
            mEvent = "0 THIS St."
            mRoom = "Room 13"
            # populate talk data
            self.talk_editor.addTalkWidget.titleLineEdit.setText(mTitle)
            self.talk_editor.addTalkWidget.presenterLineEdit.setText(
                mPresenter)
            self.talk_editor.addTalkWidget.eventLineEdit.setText(mEvent)
            self.talk_editor.addTalkWidget.roomLineEdit.setText(mRoom)

            # date and time are prepopulated

            # add in the talk
            QtTest.QTest.mouseClick(self.talk_editor.addTalkWidget.addButton,
                                    Qt.Qt.LeftButton)

        # we need at least 1 talk
        self.assertTrue(
            self.talk_editor.editorWidget.editor.model().rowCount() > 0)

        # TODO: ROADBLOCK
        # Clicking "clear" causes a pop-up confirmation box to appear.
        # However, there is no link to this popup from inside the talk_editor

        # hit the clear button, hit no. No changes
        #QtTest.QTest.mouseClick(self.talk_editor.editorWidget.clearButton, Qt.Qt.LeftButton)
        # TODO: get the pop-up box's focus and click the button

        # hit the clear button, hit yes. Empty DB
        #QtTest.QTest.mouseClick(self.talk_editor.editorWidget.clearButton, Qt.Qt.LeftButton)
        # TODO: get the pop-up box's focus and click the button

    def test_file_menu_quit(self):
        '''
        Tests TalkEditorApp's File->Quit
        '''

        self.assertTrue(self.talk_editor.isVisible())

        # File->Quit
        self.talk_editor.actionExit.trigger()
        self.assertFalse(self.talk_editor.isVisible())

    def test_help_menu_about(self):
        '''
        Tests TalkEditorApp's Help->About
        '''

        self.assertTrue(self.talk_editor.isVisible())

        # Help->About
        self.talk_editor.actionAbout.trigger()
        self.assertFalse(self.talk_editor.hasFocus())
        self.assertTrue(self.talk_editor.aboutDialog.isVisible())

        # Click "Close"
        QtTest.QTest.mouseClick(self.talk_editor.aboutDialog.closeButton,
                                Qt.Qt.LeftButton)
        self.assertFalse(self.talk_editor.aboutDialog.isVisible())

    def test_pep8(self):
        checker = pep8.StyleGuide(**pep8_options)
        report = checker.check_files([
            'freeseer/tests/frontend/talkeditor',
            'freeseer/frontend/talkeditor'
        ])
        pep8_report(self, report)