Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: tommie/freeseer
base: 327f31041f
...
head fork: tommie/freeseer
compare: c288009239
  • 3 commits
  • 9 files changed
  • 0 commit comments
  • 1 contributor
9 setup.py
View
@@ -24,20 +24,17 @@ def rcc4(inpath, outpath):
('framework/resources/resource.qrc', 'framework/resource_rc.py'),
]
-build_dir = os.path.join('build', 'lib.%s-%s' % (distutils.util.get_platform(), sys.version[0:3]))
+build_dir = os.path.abspath(os.path.join('build', 'lib.%s-%s' % (distutils.util.get_platform(), sys.version[0:3])))
-for (inpath, outpath) in QT4_UI_DEFS:
+for (inpath, outpath) in QT4_UI_DEFS + QT4_RC_DEFS:
outdir = os.path.join(build_dir, 'freeseer', os.path.dirname(outpath))
if not os.path.exists(outdir):
os.makedirs(outdir)
+for (inpath, outpath) in QT4_UI_DEFS:
uic4(os.path.join('src', 'freeseer', inpath), os.path.join(build_dir, 'freeseer', outpath))
for (inpath, outpath) in QT4_RC_DEFS:
- outdir = os.path.join(build_dir, 'freeseer', os.path.dirname(outpath))
- if not os.path.exists(outdir):
- os.makedirs(outdir)
-
rcc4(os.path.join('src', 'freeseer', inpath), os.path.join(build_dir, 'freeseer', outpath))
setup(name='freeseer',
58 src/freeseer/backend/gstreamer.py
View
@@ -95,7 +95,7 @@ def __init__(self, core):
##
def on_message(self, bus, message):
t = message.type
-
+
if t == gst.MESSAGE_EOS:
#self.player.set_state(gst.STATE_NULL)
self.stop()
@@ -111,7 +111,7 @@ def on_message(self, bus, message):
self.core.logger.log.debug('v4l2src failed, falling back to v4lsrc')
self.change_video_source('usb_fallback', self.video_device)
self.record(self.filename)
-
+
elif message.structure is not None:
s = message.structure.get_name()
@@ -119,7 +119,7 @@ def on_message(self, bus, message):
if s == 'level':
msg = message.structure.to_string()
rms_dB = float(msg.split(',')[6].split('{')[1].rstrip('}'))
-
+
# This is an inaccurate representation of decibels into percent
# conversion, this code should be revisited.
try:
@@ -127,7 +127,7 @@ def on_message(self, bus, message):
except OverflowError:
percent = 0
self.core.audioFeedbackEvent(percent)
-
+
def on_sync_message(self, bus, message):
if message.structure is None:
return
@@ -169,14 +169,14 @@ def _set_video_source(self):
# not sure about device format on windows. for now lets just use the default
if os.name == 'posix': # only set device for linux systems.
video_src.set_property('device', self.video_device)
-
-
+
+
video_rate = gst.element_factory_make('videorate', 'video_rate')
video_rate_cap = gst.element_factory_make('capsfilter',
'video_rate_cap')
video_rate_cap.set_property('caps',
- gst.caps_from_string('video/x-raw-rgb, framerate=10/1'))
+ gst.caps_from_string('video/x-raw-rgb, framerate=25/1'))
video_scale = gst.element_factory_make('videoscale', 'video_scale')
video_scale_cap = gst.element_factory_make('capsfilter',
'video_scale_cap')
@@ -198,7 +198,7 @@ def _set_video_source(self):
video_scale_cap,
video_cspace,
self.video_tee)
-
+
if ( self.icecast ):
# Add a "tee" component so that the icecast components can be built at the end
self.src_tee = gst.element_factory_make('tee', 'src_tee')
@@ -212,18 +212,18 @@ def _set_video_source(self):
self.dv1394dvdemux = gst.element_factory_make('dvdemux',
'dv1394dvdemux')
self.dv1394dvdec = gst.element_factory_make('dvdec', 'dv1394dvdec')
-
+
self.player.add(self.dv1394q1,
self.dv1394q2,
self.dv1394dvdemux,
self.dv1394dvdec)
-
+
if ( self.icecast ):
# The "src_tee" was added so link from it
self.src_tee.link(self.dv1394dvdemux)
- else:
+ else:
video_src.link(self.dv1394dvdemux)
-
+
self.dv1394dvdemux.connect('pad-added', self._dvdemux_padded)
gst.element_link_many(self.dv1394q1, self.dv1394dvdec, video_rate)
else:
@@ -249,7 +249,7 @@ def _clear_video_source(self):
video_scale = self.player.get_by_name('video_scale')
video_scale_cap = self.player.get_by_name('video_scale_cap')
video_cspace = self.player.get_by_name('video_cspace')
-
+
if ( self.icecast ):
# The "src_tee" was added so remove it
self.player.remove(self.src_tee)
@@ -301,7 +301,7 @@ def _set_video_feedback(self):
self.player.add(vpqueue, vpsink)
gst.element_link_many(self.video_tee, vpqueue, vpsink)
-
+
def _clear_video_feedback(self):
vpqueue = self.player.get_by_name('vpqueue')
vpsink = self.player.get_by_name('vpsink')
@@ -332,7 +332,7 @@ def _set_audio_encoder(self):
'''
Sets the audio encoder pipeline
'''
-
+
audioenc_queue = gst.element_factory_make('queue',
'audioenc_queue')
audioenc_convert = gst.element_factory_make('audioconvert',
@@ -363,7 +363,7 @@ def _set_audio_encoder(self):
audioenc_codec,
audioenc_tags,
self.mux)
-
+
def _clear_audio_encoder(self):
'''
Clears the audio encoder pipeline
@@ -501,7 +501,7 @@ def _clear_icecast_streaming(self):
def test_feedback_start(self, video=False, audio=False):
self.test_video = video
self.test_audio = audio
-
+
if self.test_video == True:
self._set_video_source()
self._set_video_feedback()
@@ -514,11 +514,11 @@ def test_feedback_start(self, video=False, audio=False):
def test_feedback_stop(self):
self.player.set_state(gst.STATE_NULL)
-
+
if self.test_video == True:
self._clear_video_source()
self._clear_video_feedback()
-
+
if self.test_audio == True:
self._clear_audio_source()
self._clear_audio_feedback()
@@ -564,10 +564,10 @@ def record(self, filename):
if self.recording_audio_feedback == True:
self._set_audio_feedback()
-
+
if self.icecast == True:
self._set_icecast_streaming()
-
+
self.player.set_state(gst.STATE_PLAYING)
def stop(self):
@@ -580,10 +580,10 @@ def stop(self):
if self.record_video == True:
self._clear_video_source()
self._clear_video_encoder()
-
+
if self.recording_video_feedback == True:
self._clear_video_feedback()
-
+
if self.record_audio == True:
self._clear_audio_source()
self._clear_audio_encoder()
@@ -692,7 +692,7 @@ def change_output_resolution(self, width, height):
# If streaming is being done, reset the bitrate according to the new resolution
if self.icecast:
self.change_stream_resolution(self.icecast_width, self.icecast_height, width, height)
-
+
def change_stream_resolution(self, width, height, record_width, record_height):
'''
Sets the resolution of the streamed video, and attempts to choose the ideal bitrate for the given resolutions.
@@ -704,8 +704,8 @@ def change_stream_resolution(self, width, height, record_width, record_height):
'480,640': 800, '480,800': 800, '480,1024': 350, # bit rates for 480x360 stream
'640,640': 1250, '640,800': 1000, '640,1024': 500, # bit rates for 640x480 stream
'800,640': 1250, '800,800': 1000, '800,1024': 750 # bit rates for 800x600 stream
- }
-
+ }
+
# If the pairing cannot be found, we back off to the average best bitrate at each resolution
default_bitmap = { 320: 400, # resolution of 320x240 - 400 kbps
480: 500, # resolution of 480x360 - 500 kbps
@@ -721,12 +721,12 @@ def change_stream_resolution(self, width, height, record_width, record_height):
self.icecast_height = height
# If the pairing is found in bitmap, use the given bitrate
- if stream_rec_pair in bitmap:
+ if stream_rec_pair in bitmap:
self.icecast_vidbitrate = bitmap[stream_rec_pair]
elif self.icecast_width in default_bitmap: # Else, if the stream resolution is in default_bitmap, use that bitrate
self.icecast_vidbitrate = default_bitmap[width]
else: # If pairing not in default_bitmap, use default value of 1000
- self.icecast_vidbitrate = 1000
+ self.icecast_vidbitrate = 1000
def change_audio_source(self, new_source):
'''
@@ -784,7 +784,7 @@ def disable_audio_feedback(self):
Disable the audio feedback.
'''
self.recording_audio_feedback = False
-
+
def enable_icecast_streaming(self, ip='127.0.0.1',
port=8000,
password='hackme',
54 src/freeseer/framework/config.py
View
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
# freeseer - vga/presentation capture software
@@ -36,13 +35,15 @@ def __init__(self, configdir):
'''
# Get the user's home directory
self.userhome = os.path.expanduser('~')
-
+
# Config location
self.configdir = configdir
self.configfile = os.path.abspath("%s/freeseer.conf" % self.configdir)
-
+
# Set default settings
self.videodir = os.path.abspath('%s/Videos/' % self.userhome)
+ self.uploaddir = os.path.abspath(os.path.join(configdir, 'spool-upload'))
+ self.archivedest = ''
self.presentations_file = os.path.abspath('%s/presentations.db' % self.configdir)
self.resolution = '0x0' # no scaling for video
@@ -61,7 +62,7 @@ def __init__(self, configdir):
self.enable_video_recoding = True
self.enable_audio_recoding = True
-
+
self.enable_streaming = 'False'
self.streaming_resolution = '0x0' #no scaling for streaming
self.streaming_mount = 'stream.ogv'
@@ -72,38 +73,42 @@ def __init__(self, configdir):
# Map of resolution names to the actual resolution (both stream and record)
# Names should include all options available in the GUI
- self.resmap = { '240p':'320x240',
- '360p':'480x360',
- '480p':'640x480',
- '720p':'1280x720',
+ self.resmap = { '240p':'320x240',
+ '360p':'480x360',
+ '480p':'640x480',
+ '720p':'1280x720',
'1080p':'1920x1080' }
# Read in the config file
self.readConfig()
-
- # Make the recording directory
- try:
+
+ if not os.path.exists(self.uploaddir):
+ # Chances of a race in this type of application is zero.
+ os.makedirs(self.uploaddir)
+
+ if not os.path.exists(self.videodir):
+ # Chances of a race in this type of application is zero.
os.makedirs(self.videodir)
- except OSError:
- print('Video directory exists.')
-
+
def readConfig(self):
'''
Read in settings from config file if exists.
If the config file does not exist create one and set some defaults.
'''
config = ConfigParser.ConfigParser()
-
+
try:
config.readfp(open(self.configfile))
# Config file does not exist, create a default
except IOError:
self.writeConfig()
return
-
+
# Config file exists, read in the settings
try:
self.videodir = config.get('Global', 'video_directory')
+ self.uploaddir = config.get('Global', 'upload_spool_directory')
+ self.archivedest = config.get('Global', 'archive_destination')
self.resolution = config.get('Global', 'resolution')
self.videosrc = config.get('lastrun', 'video_source')
self.videodev = config.get('lastrun', 'video_device')
@@ -127,16 +132,18 @@ def readConfig(self):
except:
print('Corrupt config found, creating a new one.')
self.writeConfig()
-
+
def writeConfig(self):
'''
Write settings to a config file.
'''
config = ConfigParser.ConfigParser()
-
+
# Set config settings
config.add_section('Global')
config.set('Global', 'video_directory', self.videodir)
+ config.set('Global', 'upload_spool_directory', self.uploaddir)
+ config.set('Global', 'archive_destination', self.archivedest)
config.set('Global', 'resolution', self.resolution)
config.set('Global','streaming_resolution',self.streaming_resolution)
config.add_section('lastrun')
@@ -157,19 +164,12 @@ def writeConfig(self):
config.set('lastrun','streaming_port',self.streaming_port)
config.set('lastrun','streaming_password',self.streaming_password)
config.set('lastrun','streaming_url',self.streaming_url)
- # Make sure the config directory exists before writing to the configfile
+ # Make sure the config directory exists before writing to the configfile
try:
os.makedirs(self.configdir)
except OSError:
pass # directory exists.
-
+
# Save default settings to new config file
with open(self.configfile, 'w') as configfile:
config.write(configfile)
-
-# Config class test code
-if __name__ == "__main__":
- config = Config(os.path.abspath(os.path.expanduser('~/.freeseer/')))
- print('\nTesting freeseer config file')
- print('Video Directory at %s' % config.videodir)
- print('Test complete!')
251 src/freeseer/framework/core.py
View
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
# freeseer - vga/presentation capture software
@@ -28,6 +27,7 @@
import time
import logging
import logging.config
+import re
import unicodedata
from freeseer import project_info
@@ -35,7 +35,6 @@
from config import Config
from logger import Logger
-from db_connector import *
from rss_parser import *
from presentation import *
@@ -48,12 +47,11 @@ class FreeseerCore:
'''
def __init__(self, ui):
self.ui = ui
-
+
# Read in config information
configdir = os.path.abspath(os.path.expanduser('~/.freeseer/'))
self.config = Config(configdir)
self.logger = Logger(configdir)
- self.db = DB_Connector(configdir)
# Start Freeseer Recording Backend
self.backend = Freeseer_gstreamer(self)
@@ -69,207 +67,33 @@ def __init__(self, ui):
self.feedback = False
self.spaces = False
-
- self.logger.log.info(u"Core initialized")
-
- def duplicate_exists(self, recordname):
- '''
- Checks to see if a record name already exists in the directory.
- '''
- filename = self.config.videodir + '/' + recordname
- try:
- result = open(filename, 'r')
- except IOError:
- return False
- return True
+ self.logger.log.info(u"Core initialized")
- def get_record_name(self, presentation):
+ def _get_record_name(self, presentation):
'''
Returns the filename to use when recording.
'''
- recordname = self.make_record_name(presentation)
-
- count = 0
- tempname = recordname
-
- # check if this record name already exists in this directory and add "-NN" ending if so.
- while(self.duplicate_exists(tempname + ".ogg")):
- tempname = recordname + "-" + self.make_id_from_string(count, "0123456789")
- count+=1
-
- recordname = tempname + ".ogg"
-
- self.logger.log.debug('Set record name to ' + recordname)
-
- return recordname
-
-
- def make_record_name(self, presentation):
- '''
- Create an 'EVENT-ROOM-SPEAKER-TITLE' record name
- If any information is missing, we blank it out intelligently
- And if we have nothing for some reason, we use "default"
- '''
- event = self.make_shortname(presentation.event)
- title = self.make_shortname(presentation.title)
- room = self.make_shortname(presentation.room)
- speaker = self.make_shortname(presentation.speaker)
-
- recordname=""
-
- if(event!=""):
- if(recordname!=""):
- recordname=recordname+"-"+event
- else:
- recordname=event
-
- if(room!=""):
- if(recordname!=""):
- recordname=recordname+"-"+room
- else:
- recordname=room
-
- if(speaker!=""):
- if(recordname!=""):
- recordname=recordname+"-"+speaker
- else:
- recordname=speaker
-
- if(title!=""):
- if(recordname!=""):
- recordname=recordname+"-"+title
- else:
- recordname=title
-
- # Convert unicode filenames to their equivalent ascii so that
- # we don't run into issues with gstreamer or filesystems
- recordname=unicodedata.normalize('NFKD', recordname).encode('ascii','ignore')
-
- if(recordname!=""):
- return recordname
-
- return "default"
-
- def make_id_from_string(self, position, string='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
- '''
- Returns an "NN" id given an integer and a string of valid characters for the id
- ('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' are the valid characters for UNIQUE in a record name)
- '''
- index1 = position % string.__len__()
- index0 = int( position / string.__len__() )
+ ts = presentation.start_time.strftime('%Y%m%dT%H%M%S')
- if(index0 >= string.__len__() ):
- self.logger.log.debug('WARNING: Unable to generate unique filename.')
- # Return a unique 2 character string which will not overwrite previous files.
- # There is a possibility of infinite looping on testing duplicates once
- # all possible UNIQUE's and NN's are exhausted if all the files are kept
- # in the same directory.
- # (36 * 36 * 100 filenames before this occurs, assuming EVENT is unique inside the directory.)
- return "##"
+ return '%s-%s-%s.ogg' % (
+ ts,
+ self._mangle_filename_part(presentation.author),
+ self._mangle_filename_part(presentation.title))
- return string[index0]+string[index1]
+ DISALLOWED_CHARACTERS = re.compile(r'[^\w_.]')
- def make_shortname(self, providedString):
- '''
- Returns the first 6 characters of a string.
- Strip out non alpha-numeric characters, spaces, and most punctuation
- '''
-
- bad_chars = set("!@#$%^&*()+=|:;{}[]',? <>~`/\\")
- providedString="".join(ch for ch in providedString if ch not in bad_chars)
- return providedString[0:6].upper()
-
- ##
- ## Database Functions
- ##
- def get_talk_titles(self):
- return self.db.get_talk_titles()
-
-
- def get_talk_rooms(self):
- return self.db.get_talk_rooms()
-
-
- def get_talk_events(self):
- return self.db.get_talk_events()
-
- def filter_talks_by_event_room(self, event, room):
- return self.db.filter_talks_by_event_room(event, room)
-
-
- def filter_rooms_by_event(self,evento):
- return self.db.filter_rooms_by_event(evento)
-
-
- def get_presentation_id_by_selected_title(self, talk):
+ def _mangle_filename_part(self, s):
'''
- Obtains a presentation ID given a title string from the GUI
+ Return a string suitable for use in a file name.
'''
-
- speaker = talk.split(' - ', 1)[0].strip()
- title = talk.split(' - ', 1)[1].strip()
-
- talk_id = self.db.get_presentation_id_from_talk(speaker, title)
-
- return talk_id
-
- def get_presentation(self, presentation_id):
- return self.db.get_presentation(presentation_id)
-
-
- def add_talks_from_rss(self, rss):
- entry = str(rss)
- feedparser = FeedParser(entry)
-
- if len(feedparser.build_data_dictionary()) == 0:
- self.logger.log.info("RSS: No data found.")
-
- else:
- for presentation in feedparser.build_data_dictionary():
- talk = Presentation(presentation["Title"],
- presentation["Speaker"],
- presentation["Abstract"], # Description
- presentation["Level"],
- presentation["Event"],
- presentation["Time"],
- presentation["Room"])
-
- if not self.db.db_contains(talk):
- self.add_talk(talk)
-
-
- def get_presentation_id(self, presentation):
- talk_id = self.db.get_presentation_id(presentation)
- self.logger.log.debug('Found presentation id for %s - %s. ID: %s',
- presentation.speaker,
- presentation.title,
- talk_id)
- return talk_id
-
-
- def add_talk(self, presentation):
- self.db.add_talk(presentation)
- self.logger.log.debug('Talk added: %s - %s', presentation.speaker, presentation.title)
-
-
- def update_talk(self, talk_id, speaker, title, room, event, dateTime):
- self.db.update_talk(talk_id, speaker, title, room, event, dateTime)
- self.logger.log.debug('Talk updated: %s - %s', speaker, title)
-
-
- def delete_talk(self, talk_id):
- self.db.delete_talk(talk_id)
- self.logger.log.debug('Talk deleted: %s', talk_id)
-
-
- def clear_database(self):
- self.db.clear_database()
- self.logger.log.debug('Database cleared!')
+ s = s.lower().replace(u'-', u'_').replace(u' ', u'_')
+ s = self.DISALLOWED_CHARACTERS.sub(u'', s)
+ return unicodedata.normalize('NFKD', s)[:32].encode('utf-8')
##
## Backend Functions
@@ -282,7 +106,7 @@ def get_video_sources(self):
self.logger.log.debug('Available video sources: ' + str(vidsrcs))
return vidsrcs
-
+
def get_video_devices(self, device_type):
'''
Returns available video devices.
@@ -291,7 +115,7 @@ def get_video_devices(self, device_type):
self.logger.log.debug('Available video devices for ' + device_type + ': ' + str(viddevs))
return viddevs
-
+
def get_audio_sources(self):
'''
Returns supported audio sources.
@@ -310,10 +134,10 @@ def set_video_mode(self, mode):
self.logger.log.info('Video recording: ENABLED')
else:
self.logger.log.info('Video recording: DISABLED')
-
+
self.backend.set_video_mode(mode)
-
+
def change_videosrc(self, vid_source, vid_device):
'''
Informs backend of new video source to use when recording.
@@ -389,40 +213,45 @@ def test_sources(self, state, video=False, audio=False):
self.backend.test_feedback_stop()
- def prepare_metadata(self, presentation):
+ def _prepare_metadata(self, presentation):
'''
Returns a dictionary of tags and tag values to be used
to populate the current recording's file metadata.
'''
return { "title" : presentation.title,
- "artist" : presentation.speaker,
- "performer" : presentation.speaker,
- "album" : presentation.event,
- "location" : presentation.room,
- "date" : str(datetime.date.today()),
- "comment" : presentation.description}
+ "artist" : presentation.author,
+ "performer" : presentation.author,
+ "date" : presentation.start_time.strftime('%Y-%m-%d'),
+ "extended-comment" : 'timestamp=' + presentation.start_time.strftime('%Y-%m-%d %H:%M:%S%z'),
+ }
def record(self, presentation):
'''
Informs backend to begin recording presentation.
'''
- #create a filename to record to
- record_name = self.get_record_name(presentation)
-
- #prepare metadata
- data = self.prepare_metadata(presentation)
- self.backend.populate_metadata(data)
+ self.backend.populate_metadata(self._prepare_metadata(presentation))
- record_location = os.path.abspath(self.config.videodir + '/' + record_name)
+ self._current_presentation = presentation
+ record_name = self._get_record_name(presentation)
+ record_location = os.path.abspath(os.path.join(self.config.videodir, record_name))
self.backend.record(record_location)
self.logger.log.info('Recording started')
- def stop(self):
+
+ def stop(self, presentation):
'''
Informs backend to stop recording.
'''
self.backend.stop()
+
+ # Queue file for upload
+ record_name = self._get_record_name(self._current_presentation)
+
+ os.link(
+ os.path.join(self.config.videodir, record_name),
+ os.path.join(self.config.uploaddir, record_name))
+
self.logger.log.info('Recording stopped')
@@ -434,7 +263,7 @@ def test_feedback(self, video, audio):
self.feedback = True
self.backend.test_feedback_start(video, audio)
-
+
def preview(self, enable=False, window_id=None):
'''
Enable/Disable the video preview window.
156 src/freeseer/framework/db_connector.py
View
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
# freeseer - vga/presentation capture software
@@ -27,69 +26,52 @@
import os
-class DB_Connector():
+class DB_Connector(object):
'''
Freeseer database connection.
- '''
+ '''
def __init__(self, configdir):
-
- self._CREATE_QUERY = '''CREATE TABLE presentations
- (Speaker varchar(100),
- Title varchar(255) UNIQUE,
- Description text,
- Level varchar(25),
- Event varchar(100),
- Time timestamp,
- Room varchar(25),
- Id INTEGER PRIMARY KEY,
- FileNameId INTEGER)'''
-
- self._DEFAULT_TALK = '''INSERT INTO presentations VALUES
- ("Thanh Ha",
- "Intro to Freeseer",
- "",
- "",
- "",
- "",
- "T105",
- NULL,
- 0)'''
+
+ self._CREATE_QUERY = '''CREATE TABLE presentations (
+ Id INTEGER PRIMARY KEY,
+ Author TEXT NOT NULL,
+ Title TEXT NOT NULL UNIQUE,
+ StartTime TIMESTAMP NOT NULL)'''
self.configdir = configdir
self.presentations_file = os.path.abspath("%s/presentations.db" % self.configdir)
self.cursor = None
-
+
if not os.path.isfile(self.presentations_file):
- self.db_connection = connect(self.presentations_file)
- self.create_table()
+ self.db_connection = connect(self.presentations_file)
+ self.create_table()
self.cursor = self.db_connection.cursor()
return
-
+
self.db_connection = connect(self.presentations_file)
self.cursor = self.db_connection.cursor()
-
+
def run_query(self,querie,args=None):
self.cursor = self.db_connection.cursor()
try:
self.cursor.execute(querie,args)
except:
- return
+ return
self.db_connection.commit()
return self.cursor
-
+
def create_table(self):
self.cursor = self.db_connection.cursor()
self.cursor.execute(self._CREATE_QUERY)
- self.cursor.execute(self._DEFAULT_TALK)
self.db_connection.commit()
self.cursor.close()
-
+
def get_talk_titles(self):
'''
Returns the talk titles as listed in presentations.db
'''
talk_titles = []
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''SELECT Speaker, Title, Room, Event, Time, Id FROM presentations ORDER BY Time ASC''')
@@ -101,37 +83,37 @@ def get_talk_titles(self):
time = row[4]
talk_id = row[5]
talk_titles.append([speaker, title, room, event, time, talk_id])
-
+
self.cursor.close()
-
+
return talk_titles
-
+
def get_talk_events(self):
talk_events = []
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''SELECT DISTINCT Event FROM presentations''')
-
+
for row in self.cursor:
talk_events.append(row[0])
-
+
self.cursor.close()
-
+
return talk_events
-
+
def get_talk_rooms(self):
talk_rooms = []
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''SELECT DISTINCT Room FROM presentations''')
-
+
for row in self.cursor:
talk_rooms.append(row[0])
-
+
self.cursor.close()
-
+
return talk_rooms
-
+
def db_contains(self, presentation):
'''
Check if database already contains such presentation. Two presentations
@@ -145,7 +127,7 @@ def db_contains(self, presentation):
if (presentation.title in talk_titles and presentation.event in talk_events and presentation.speaker in talk_speakers):
self.cursor.close()
return True
-
+
self.cursor.close()
return False
@@ -159,7 +141,7 @@ def get_talks_ids(self):
talks_ids.append(row[0])
self.cursor.close()
-
+
return talks_ids
def filter_talks_by_event_room(self, event, room):
@@ -169,11 +151,11 @@ def filter_talks_by_event_room(self, event, room):
if (event == "All"):
if (room == "All"):
self.cursor.execute('''SELECT Speaker, Title FROM presentations ORDER BY Time ASC''')
-
+
else:
self.cursor.execute('''SELECT DISTINCT Speaker, Title FROM presentations \
WHERE Room=? ORDER BY Time ASC''', [unicode(room)])
-
+
else:
if (room == "All"):
self.cursor.execute('''SELECT DISTINCT Speaker, Title FROM presentations \
@@ -186,39 +168,39 @@ def filter_talks_by_event_room(self, event, room):
for row in self.cursor:
speaker = row[0]
title = row[1]
-
+
if (speaker == ""):
text = "%s" % (title)
-
- else:
+
+ else:
text = "%s - %s" % (speaker, title)
-
-
+
+
talks_matched.append(text)
self.cursor.close()
return talks_matched
-
-
+
+
def filter_rooms_by_event(self,event):
rooms_matched = []
-
+
self.cursor = self.db_connection.cursor()
if(event == "All"):
self.cursor.execute('''SELECT DISTINCT Room FROM presentations ORDER BY Time ASC''')
-
+
else:
self.cursor.execute('''SELECT DISTINCT Room FROM presentations WHERE Event=? ORDER BY TIME ASC''', [unicode(event)])
-
+
rooms_matched.append("All")
-
+
for row in self.cursor:
rooms_matched.append(row[0])
-
+
self.cursor.close()
-
+
return rooms_matched
-
+
def get_presentation_id_from_talk(self, speaker, title):
self.cursor = self.db_connection.cursor()
self.cursor.execute('''SELECT Id
@@ -228,13 +210,13 @@ def get_presentation_id_from_talk(self, speaker, title):
''' % (speaker, title))
for row in self.cursor:
talk_id = row[0]
-
+
return talk_id
def get_presentation(self, talk_id):
-
+
self.cursor = self.db_connection.cursor()
- self.cursor.execute('''SELECT Speaker,
+ self.cursor.execute('''SELECT Speaker,
Title,
Description,
Level,
@@ -255,12 +237,12 @@ def get_presentation(self, talk_id):
room = row[6]
talk_id = row[7]
filename_id = row[8]
-
- self.cursor.close()
- return Presentation(title, speaker, description, level, event, time, room, talk_id, filename_id)
-
+
+ self.cursor.close()
+ return Presentation(title, speaker, description, level, event, time, room, talk_id, filename_id)
+
def make_filename_id(self, event_name):
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''SELECT COUNT(*) FROM presentations WHERE Event=?''',
[unicode(event_name)])
@@ -269,9 +251,9 @@ def make_filename_id(self, event_name):
id = row[0]
self.cursor.close()
return id
-
+
def get_filename_id(self, talk_id):
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''SELECT FileNameId FROM presentations WHERE Id=?''',
[unicode(talk_id)])
@@ -279,11 +261,11 @@ def get_filename_id(self, talk_id):
id = row[0]
self.cursor.close()
return id
-
+
def add_talk(self, presentation):
'''
Write current presentation data on database
- '''
+ '''
#create filename id (id's for each talk at an event)
filename_id = unicode(self.make_filename_id(presentation.event))
@@ -298,23 +280,23 @@ def add_talk(self, presentation):
filename_id])
def delete_talk(self, talk_id):
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''DELETE FROM presentations WHERE Id=?''',
[unicode(talk_id)])
self.db_connection.commit()
-
+
self.cursor.close()
-
+
def clear_database(self):
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''DELETE FROM presentations''')
self.db_connection.commit()
self.cursor.close()
-
+
def update_talk(self, talk_id, new_speaker, new_title, new_room, new_event, new_time):
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''UPDATE presentations SET Speaker=?, Title=?, Room=?, Event=?, Time=? WHERE Id=?''',
[unicode(new_speaker),
@@ -325,15 +307,15 @@ def update_talk(self, talk_id, new_speaker, new_title, new_room, new_event, new_
unicode(talk_id)])
self.db_connection.commit()
self.cursor.close()
-
+
def get_presentation_id(self, presentation):
-
+
self.cursor = self.db_connection.cursor()
self.cursor.execute('''SELECT Id FROM presentations WHERE Speaker=? AND Title=? AND Event=?''',
[unicode(presentation.speaker),
unicode(presentation.title),
unicode(presentation.event)])
-
+
for row in self.cursor:
id = row[0]
self.cursor.close()
22 src/freeseer/framework/presentation.py
View
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
# freeseer - vga/presentation capture software
@@ -23,25 +22,12 @@
# http://wiki.github.com/fosslc/freeseer/
-
-class Presentation():
+class Presentation(object):
'''
This class is responsible for encapsulate data about presentations
and its database related operations
'''
-
- def __init__(self, title, speaker=None, description="", level="", event="", time="", room=None, talk_id=None, filename_id=None):
-
- '''
- Initialize a presentation instance
- '''
- self.speaker = speaker
+ def __init__(self, title, author, start_time):
self.title = title
- self.description = description
- self.level = level
- self.event = event
- self.time = time
- self.room = room
- self.talk_id = talk_id
- self.filename_id = filename_id
-
+ self.author = author
+ self.start_time = start_time
127 src/freeseer/frontend/default/forms/freeseer_ui_qt.ui
View
@@ -29,30 +29,9 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <widget class="QPushButton" name="recordButton">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>40</height>
- </size>
- </property>
- <property name="text">
- <string>Record</string>
- </property>
- <property name="icon">
- <iconset resource="../../../framework/resources/resource.qrc">
- <normaloff>:/recordButton/record_red_button.png</normaloff>
- <normalon>:/recordButton/stop_red_button.png</normalon>:/recordButton/record_red_button.png</iconset>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="eventAndRoomLayout">
+ <layout class="QHBoxLayout" name="authorLayout">
<item>
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="authorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -72,43 +51,15 @@
</size>
</property>
<property name="text">
- <string>Event</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="eventList">
- <item>
- <property name="text">
- <string>All</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_6">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>24</height>
- </size>
- </property>
- <property name="text">
- <string>Room</string>
+ <string>Author</string>
</property>
</widget>
</item>
<item>
- <widget class="QComboBox" name="roomList">
+ <widget class="QLineEdit" name="author">
<item>
- <property name="text">
- <string>All</string>
+ <property name="tooltip">
+ <string>Your name</string>
</property>
</item>
</widget>
@@ -116,9 +67,9 @@
</layout>
</item>
<item>
- <layout class="QHBoxLayout" name="talkListLayout">
+ <layout class="QHBoxLayout" name="titleLayout">
<item>
- <widget class="QLabel" name="talkLabel">
+ <widget class="QLabel" name="titleLabel">
<property name="maximumSize">
<size>
<width>40</width>
@@ -131,15 +82,36 @@
</widget>
</item>
<item>
- <widget class="QComboBox" name="talkList">
+ <widget class="QLineEdit" name="title">
<property name="toolTip">
- <string>Title of the presentation being recorded. For example &quot;Thanh Ha - Introduction to Freeseer&quot;</string>
+ <string>Title of the presentation being recorded.</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
+ <widget class="QPushButton" name="recordButton">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>40</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Record</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../../framework/resources/resource.qrc">
+ <normaloff>:/recordButton/record_red_button.png</normaloff>
+ <normalon>:/recordButton/stop_red_button.png</normalon>:/recordButton/record_red_button.png</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="2">
<widget class="QWidget" name="previewWidget" native="true"/>
@@ -238,17 +210,10 @@
<string>Language</string>
</property>
</widget>
- <addaction name="menuLanguage"/>
- </widget>
- <widget class="QMenu" name="menuEdit">
- <property name="title">
- <string>Edit</string>
- </property>
<addaction name="actionPreferences"/>
- <addaction name="actionEdit_talks"/>
+ <addaction name="menuLanguage"/>
</widget>
<addaction name="menuFile"/>
- <addaction name="menuEdit"/>
<addaction name="menuOptions"/>
<addaction name="menuHelp"/>
</widget>
@@ -273,11 +238,6 @@
<string/>
</property>
</action>
- <action name="actionEdit_talks">
- <property name="text">
- <string>Edit Talks</string>
- </property>
- </action>
<action name="actionPreferences">
<property name="text">
<string>Preferences</string>
@@ -285,8 +245,9 @@
</action>
</widget>
<tabstops>
+ <tabstop>author</tabstop>
+ <tabstop>title</tabstop>
<tabstop>recordButton</tabstop>
- <tabstop>talkList</tabstop>
<tabstop>audioFeedbackCheckbox</tabstop>
<tabstop>audioFeedbackSlider</tabstop>
</tabstops>
@@ -329,7 +290,7 @@
<connection>
<sender>recordButton</sender>
<signal>toggled(bool)</signal>
- <receiver>eventList</receiver>
+ <receiver>author</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
@@ -345,23 +306,7 @@
<connection>
<sender>recordButton</sender>
<signal>toggled(bool)</signal>
- <receiver>roomList</receiver>
- <slot>setDisabled(bool)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>440</x>
- <y>72</y>
- </hint>
- <hint type="destinationlabel">
- <x>436</x>
- <y>99</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>recordButton</sender>
- <signal>toggled(bool)</signal>
- <receiver>talkList</receiver>
+ <receiver>title</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
162 src/freeseer/frontend/default/main.py
View
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
# freeseer - vga/presentation capture software
@@ -65,7 +64,7 @@ def translate(self):
DESCRIPTION = self.tr('AboutDialog','Freeseer is a video capture utility capable of capturing presentations. It captures video sources such as usb, firewire, or local desktop along with audio and mixes them together to produce a video.')
COPYRIGHT=self.tr('Copyright (C) 2011 The Free and Open Source Software Learning Centre')
LICENSE_TEXT=self.tr("Freeseer is licensed under the GPL version 3. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.")
-
+
ABOUT_INFO = u'<h1>'+NAME+u'</h1>' + \
u'<br><b>'+ self.tr("Version")+":" + __version__ + u'</b>' + \
u'<p>' + DESCRIPTION + u'</p>' + \
@@ -74,28 +73,28 @@ def translate(self):
u'<p>' + LICENSE_TEXT + u'</p>' \
u'<p>' + self.tr("Record button graphics by")+ ': <a href="' + RECORD_BUTTON_LINK+ u'">' + RECORD_BUTTON_ARTIST + u'</a></p>' \
u'<p>'+ self.tr("Headphones graphics by") + ': <a href="' + HEADPHONES_LINK+ u'">' + HEADPHONES_ARTIST + u'</a></p>'
-
+
self.ui.retranslateUi(self);
self.ui.aboutInfo.setText(ABOUT_INFO);
class SystemLanguages:
'''
- Language system class that is responsible for retrieving valid languages in the system
+ Language system class that is responsible for retrieving valid languages in the system
'''
def __init__(self):
self.languages = []
self.languages = self.getAllLanguages();
-
+
def getAllLanguages(self):
- '''
- Returns all the valid languages that have existing qm files. In other words languages
+ '''
+ Returns all the valid languages that have existing qm files. In other words languages
that can be loaded into the translator
- '''
+ '''
try:
files = listdir(LANGUAGE_DIR);
files = map(lambda x: x.split('.') , files);
qm_files = filter(lambda x:x[len(x)-1] == 'qm',files);
- language_prefix = map(lambda x: x[0].split("tr_")[1],qm_files);
+ language_prefix = map(lambda x: x[0].split("tr_")[1],qm_files);
except:
return [];
return language_prefix;
@@ -114,21 +113,17 @@ def __init__(self):
self.default_language = 'en';
self.talks_to_save = []
self.talks_to_delete = []
-
+
# Initialize geometry, to be used for restoring window positioning.
self.geometry = None
self.core = FreeseerCore(self)
-
+
#Setup the translator and populate the language menu under options
self.uiTranslator = QtCore.QTranslator();
self.langActionGroup = QtGui.QActionGroup(self);
QtCore.QTextCodec.setCodecForTr(QtCore.QTextCodec.codecForName('utf-8'));
self.setupLanguageMenu();
-
- self.load_talks()
- self.load_events()
- self.load_rooms()
# setup systray
logo = QtGui.QPixmap(":/freeseer/freeseer_logo.png")
@@ -146,8 +141,6 @@ def __init__(self):
self.connect(self.systray, QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self._icon_activated)
# main tab connections
- self.connect(self.ui.eventList, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.get_rooms_and_talks_at_event)
- self.connect(self.ui.roomList, QtCore.SIGNAL('currentIndexChanged(const QString&)'), self.get_talks_at_room)
self.connect(self.ui.recordButton, QtCore.SIGNAL('toggled(bool)'), self.capture)
self.connect(self.ui.testButton, QtCore.SIGNAL('toggled(bool)'), self.test_sources)
self.connect(self.ui.audioFeedbackCheckbox, QtCore.SIGNAL('stateChanged(int)'), self.toggle_audio_feedback)
@@ -155,9 +148,9 @@ def __init__(self):
# Main Window Connections
self.connect(self.ui.actionExit, QtCore.SIGNAL('triggered()'), self.close)
self.connect(self.ui.actionAbout, QtCore.SIGNAL('triggered()'), self.aboutDialog.show)
- self.connect(self.ui.actionEdit_talks, QtCore.SIGNAL('triggered()'), self.run_talk_editor)
+ #self.connect(self.ui.actionEdit_talks, QtCore.SIGNAL('triggered()'), self.run_talk_editor)
self.connect(self.ui.actionPreferences, QtCore.SIGNAL('triggered()'),self.run_config_tool)
-
+
self.load_settings()
self.core.preview(True, self.ui.previewWidget.winId())
@@ -167,32 +160,32 @@ def __init__(self):
# setup spacebar key
self.ui.recordButton.setShortcut(QtCore.Qt.Key_Space)
- self.ui.recordButton.setFocus()
+ self.ui.author.setFocus()
- self.talkEditor = TalkEditorMainApp(self.core)
+ #self.talkEditor = TalkEditorMainApp(self.core)
self.configTool = ConfigTool(self.core)
self.configTool.hide()
def setupLanguageMenu(self):
- #Add Languages to the Menu Ensure only one is clicked
+ #Add Languages to the Menu Ensure only one is clicked
self.langActionGroup.setExclusive(True)
- system_ending = QtCore.QLocale.system().name(); #Retrieve Current Locale from the operating system
+ system_ending = QtCore.QLocale.system().name(); #Retrieve Current Locale from the operating system
active_button = None; #the current active menu item (menu item for default language)
current_lang_length = 0; #Used to determine the length of prefix that match for the current default language
default_ending = self.default_language;
'''
Current Lang Length
0 - No Common Prefix
- 1 - Common Language
+ 1 - Common Language
2 - Common Language and Country
'''
- language_table = SystemLanguages(); #Load all languages from the language folder
-
+ language_table = SystemLanguages(); #Load all languages from the language folder
+
for language_name in language_table.languages:
translator = QtCore.QTranslator(); #Create a translator to translate names
- data = translator.load(LANGUAGE_DIR+'tr_'+language_name);
+ data = translator.load(LANGUAGE_DIR+'tr_'+language_name);
#Create the button
- if(data == False):
+ if(data == False):
continue;
language_display_text = translator.translate("MainApp","language_name");
if(language_display_text!=''):
@@ -221,11 +214,11 @@ def setupLanguageMenu(self):
if(active_button!=None):
active_button.setChecked(True);
#print('There are no languages available in the system except english. Please check the language directory to ensure qm files exist');
-
+
#Set up the event handling for each of the menu items
self.connect(self.langActionGroup,QtCore.SIGNAL('triggered(QAction *)'), self.translateAction)
-
- def load_settings(self):
+
+ def load_settings(self):
self.core.logger.log.info('loading setting...')
#load the config file
@@ -236,7 +229,7 @@ def load_settings(self):
self.core.set_video_mode(False)
else:
self.core.set_video_mode(True)
-
+
# load video source setting
vidsrcs = self.core.get_video_sources()
src = self.core.config.videosrc
@@ -256,7 +249,7 @@ def load_settings(self):
self.videosrc = 'fireware'
else:
self.core.logger.log.debug('Can NOT find video source: '+ src)
-
+
if src == 'usb' or src == 'fireware':
dev = self.core.config.videodev
viddevs = self.core.get_video_devices(self.videosrc)
@@ -278,11 +271,11 @@ def load_settings(self):
self.core.change_soundsrc(src)
else:
self.core.logger.log.debug('Can NOT find audio source: '+ src)
-
+
# load resolution
self.resolution = self.core.config.resolution
self.change_output_resolution()
-
+
# load streaming resolution
self.streaming_resolution = self.core.config.streaming_resolution
self.change_streaming_resolution()
@@ -292,11 +285,11 @@ def load_settings(self):
mount = str(self.core.config.streaming_mount)
password = str(self.core.config.streaming_password)
resolution = str(self.core.config.streaming_resolution).strip(" ")
-
+
if ( url == "" or port == "" or password == "" or mount == ""):
QtGui.QMessageBox.warning(self, self.tr("Incomplete Streaming Settings"), self.tr("Please ensure that all the input fields for streaming are complete or disable the streaming option") , QtGui.QMessageBox.Ok);
else:
-
+
if resolution in self.core.config.resmap:
res = self.core.config.resmap[resolution]
#self.core.backend.disable_icecast_streaming()
@@ -305,7 +298,7 @@ def load_settings(self):
self.core.backend.enable_icecast_streaming(url, int(port), password, mount, res)
else:
self.core.backend.disable_icecast_streaming()
-
+
def change_output_resolution(self):
res = str(self.resolution)
if res in self.core.config.resmap:
@@ -318,7 +311,7 @@ def change_output_resolution(self):
width = s[0]
height = s[1]
self.core.change_output_resolution(width, height)
-
+
def change_streaming_resolution(self):
res = str(self.streaming_resolution)
if res in self.core.config.resmap:
@@ -346,24 +339,21 @@ def current_presentation(self):
'''
Creates a presentation object from the currently selected title on the GUI
'''
-
- title=unicode(self.ui.talkList.currentText())
-
- p_id = self.core.get_presentation_id_by_selected_title(title)
- return self.core.get_presentation(p_id)
+ return Presentation(
+ title=unicode(self.ui.title.text()),
+ author=unicode(self.ui.author.text()),
+ start_time=datetime.datetime.now())
def capture(self, state):
'''
Function for recording and stopping recording.
'''
-
-
if (state): # Start Recording.
logo_rec = QtGui.QPixmap(":/freeseer/freeseer_logo_rec.png")
sysIcon2 = QtGui.QIcon(logo_rec)
self.systray.setIcon(sysIcon2)
- self.core.record(self.current_presentation())
+ self.core.record(self.current_presentation())
self.ui.recordButton.setText(self.tr('Stop'))
# check if auto-hide is set and if so hide
if(self.core.config.auto_hide == True):
@@ -377,18 +367,18 @@ def capture(self, state):
self.statusBar().showMessage('recording...')
self.core.config.videosrc = self.videosrc
self.core.config.writeConfig()
-
+
else: # Stop Recording.
logo_rec = QtGui.QPixmap(":/freeseer/freeseer_logo.png")
sysIcon = QtGui.QIcon(logo_rec)
self.systray.setIcon(sysIcon)
- self.core.stop()
+ self.core.stop(self.current_presentation())
self.ui.recordButton.setText(self.tr('Record'))
self.ui.audioFeedbackSlider.setValue(0)
self.statusBar().showMessage('ready')
# for stop recording, we'll keep whatever window state
# we have - hidden or showing
-
+
def test_sources(self, state):
# Test video and audio sources
@@ -402,15 +392,15 @@ def test_sources(self, state):
### Talk Related
###
- def get_rooms_and_talks_at_event(self, event):
- room_list = self.core.filter_rooms_by_event(self.ui.eventList.currentText())
+ def get_rooms_and_talks_at_event(self, event):
+ room_list = self.core.filter_rooms_by_event(self.ui.eventList.currentText())
self.update_room_list(room_list)
-
+
room = str(self.ui.roomList.currentText())
talk_list = self.core.filter_talks_by_event_room(event, room)
-
+
self.update_talk_list(talk_list)
-
+
def get_talks_at_room(self, room):
event = str(self.ui.eventList.currentText())
talk_list = self.core.filter_talks_by_event_room(event, room)
@@ -418,27 +408,27 @@ def get_talks_at_room(self, room):
def update_talk_list(self, talk_list):
self.ui.talkList.clear()
-
+
for talk in talk_list:
self.ui.talkList.addItem(talk)
-
+
def update_room_list(self, room_list):
self.ui.roomList.clear()
-
+
for room in room_list:
self.ui.roomList.addItem(room)
-
+
def load_talks(self):
'''
This method updates the GUI with the available presentation titles.
'''
-
+
# Update the main tab
event = str(self.ui.eventList.currentText())
room = str(self.ui.roomList.currentText())
talk_list = self.core.filter_talks_by_event_room(event, room)
self.update_talk_list(talk_list)
-
+
def load_events(self):
'''
This method updates the GUI with the available presentation events.
@@ -446,11 +436,11 @@ def load_events(self):
event_list = self.core.get_talk_events()
self.ui.eventList.clear()
self.ui.eventList.addItem("All")
-
+
for event in event_list:
if len(event)>0:
- self.ui.eventList.addItem(event)
-
+ self.ui.eventList.addItem(event)
+
def load_rooms(self):
'''
This method updates the GUI with the available presentation rooms.
@@ -458,7 +448,7 @@ def load_rooms(self):
room_list = self.core.get_talk_rooms()
self.ui.roomList.clear()
self.ui.roomList.addItem("All")
-
+
for room in room_list:
if len(room)>0:
self.ui.roomList.addItem(room)
@@ -474,13 +464,13 @@ def update_talk_views(self):
###
### Misc
###
-
+
def area_select(self):
self.area_selector = QtAreaSelector(self)
self.area_selector.show()
self.core.logger.log.info('Desktop area selector started.')
self.hide_window()
-
+
def desktopAreaEvent(self, start_x, start_y, end_x, end_y):
self.start_x = self.core.config.start_x = start_x
self.start_y = self.core.config.start_y = start_y
@@ -492,9 +482,9 @@ def desktopAreaEvent(self, start_x, start_y, end_x, end_y):
def _icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.Trigger:
- self.hide_window()
-
-
+ self.hide_window()
+
+
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.ui.recordButton.toggle()
@@ -506,9 +496,9 @@ def hide_window(self):
def show_window(self):
if (self.geometry is not None):
self.restoreGeometry(self.geometry)
- self.show()
-
-
+ self.show()
+
+
def toggle_window_visibility(self):
if self.isHidden():
self.show_window()
@@ -530,7 +520,7 @@ def coreEvent(self, event_type, value):
def closeEvent(self, event):
self.core.logger.log.info('Exiting freeseer...')
event.accept()
-
+
def translateAction(self ,action):
'''
@@ -539,44 +529,38 @@ def translateAction(self ,action):
'''
language_prefix = action.data().toString();
self.translateFile(language_prefix);
-
+
def translateFile(self,file_ending):
'''
Actually performs the translation. This is called by the handler for the language menu
- Note: If the language file can not be loaded then the default language is English
+ Note: If the language file can not be loaded then the default language is English
'''
load_string = LANGUAGE_DIR+'tr_'+ file_ending; #create language file path
-
+
loaded = self.uiTranslator.load(load_string);
if(loaded == True):
-
+
self.ui.retranslateUi(self); #Translate both the ui and the about page
self.aboutDialog.translate();
-
+
else:
print("Invalid Locale Resorting to Default Language: English");
self.configTool.translateFile(file_ending);
-
+
def run_config_tool(self):
self.connect(self.configTool, QtCore.SIGNAL("changed"),self.load_settings)
self.configTool.show()
-
+
# Restore window positioning if one was saved.
if (self.configTool.geometry is not None):
self.configTool.restoreGeometry(self.configTool.geometry)
-
+
def run_talk_editor(self):
self.connect(self.talkEditor, QtCore.SIGNAL('changed'), self.update_talk_views)
self.talkEditor.show()
-
+
# Restore window positioning if one was saved.
if (self.talkEditor.geometry is not None):
self.talkEditor.restoreGeometry(self.talkEditor.geometry)
-
-if __name__ == "__main__":
- app = QtGui.QApplication(sys.argv)
- main = MainApp()
- main.show();
- sys.exit(app.exec_())
90 src/freeseer/frontend/talkeditor/main.py
View
@@ -67,13 +67,13 @@ def translate(self):
u'<p>' + COPYRIGHT + u'</p>' + \
u'<p><a href="' + URL + u'">' + URL + u'</a></p>' \
u'<p>' + LICENSE_TEXT + u'</p>'
-
+
self.ui.retranslateUi(self);
self.ui.aboutInfo.setText(ABOUT_INFO);
class SystemLanguages:
'''
- Language system class that is responsible for retrieving valid languages in the system
+ Language system class that is responsible for retrieving valid languages in the system
'''
def __init__(self):
@@ -93,7 +93,7 @@ def getAllLanguages(self):
except:
return [];
return language_prefix;
-
+
class TalkEditorMainApp(QtGui.QMainWindow):
'''
Freeseer talk database editor main gui class
@@ -102,10 +102,10 @@ def __init__(self, core=None):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_TalkEditorMainWindow()
self.ui.setupUi(self)
- self.aboutDialog = AboutDialog()
+ self.aboutDialog = AboutDialog()
self.ui.editTable.setColumnHidden(5, True)
self.default_language = 'en';
-
+
# Initialize geometry, to be used for restoring window positioning.
self.geometry = None
@@ -114,7 +114,7 @@ def __init__(self, core=None):
self.core = core
else:
self.core = FreeseerCore(self)
-
+
#Setup the translator and populate the language menu under options
self.uiTranslator = QtCore.QTranslator();
self.langActionGroup = QtGui.QActionGroup(self);
@@ -122,58 +122,58 @@ def __init__(self, core=None):
self.setupLanguageMenu();
self.load_talks()
-
+
# edit talks connections
self.connect(self.ui.confirmAddTalkButton, QtCore.SIGNAL('clicked()'), self.add_talk)
self.connect(self.ui.rssButton, QtCore.SIGNAL('clicked()'), self.add_talks_from_rss)
self.connect(self.ui.removeTalkButton, QtCore.SIGNAL('clicked()'), self.remove_talk)
self.connect(self.ui.resetButton, QtCore.SIGNAL('clicked()'), self.reset)
self.ui.addTalkGroupBox.setHidden(True)
-
+
# Main Window Connections
self.connect(self.ui.actionExit, QtCore.SIGNAL('triggered()'), self.close)
self.connect(self.ui.actionAbout, QtCore.SIGNAL('triggered()'), self.aboutDialog.show)
-
+
# editTable Connections
self.connect(self.ui.editTable, QtCore.SIGNAL('cellChanged(int, int)'), self.edit_talk)
# TODO fix this
def setupLanguageMenu(self):
- #Add Languages to the Menu Ensure only one is clicked
+ #Add Languages to the Menu Ensure only one is clicked
self.langActionGroup.setExclusive(True)
- system_ending = QtCore.QLocale.system().name(); #Retrieve Current Locale from the operating system
+ system_ending = QtCore.QLocale.system().name(); #Retrieve Current Locale from the operating system
active_button = None; #the current active menu item (menu item for default language)
current_lang_length = 0; #Used to determine the length of prefix that match for the current default language
default_ending = self.default_language;
'''
Current Lang Length
0 - No Common Prefix
- 1 - Common Language
+ 1 - Common Language
2 - Common Language and Country
'''
- language_table = SystemLanguages(); #Load all languages from the language folder
-
-
+ language_table = SystemLanguages(); #Load all languages from the language folder
+
+
for language_name in language_table.languages:
translator = QtCore.QTranslator(); #Create a translator to translate names
- data = translator.load(LANGUAGE_DIR+'tr_'+language_name);
+ data = translator.load(LANGUAGE_DIR+'tr_'+language_name);
#Create the button
- if(data == False):
+ if(data == False):
continue;
language_display_text = translator.translate("MainApp","language_name");
-
+
if(language_display_text!=''):
language_menu_button = QtGui.QAction(self);
language_menu_button.setCheckable(True);
-
+
#Dialect handling for locales from operating system. Use possible match
if(language_name == system_ending): #direct match
active_button = language_menu_button;
current_lang_length = 2;
self.default_language = system_ending;
else:
-
+
if(language_name.split("_")[0] == system_ending.split("_")[0]): #If language matches but not country
if(current_lang_length < 1): #if there has been no direct match yet.
active_button = language_menu_button;
@@ -183,21 +183,21 @@ def setupLanguageMenu(self):
if(current_lang_length == 0):
active_button = language_menu_button;
self.default_language = language_name;
-
+
#language_name is a holder for the language name in the translation file tr_*.ts
language_menu_button.setText(language_display_text);
language_menu_button.setData(language_name);
self.ui.menuLanguage.addAction(language_menu_button);
self.langActionGroup.addAction(language_menu_button);
-
+
if(active_button!=None):
active_button.setChecked(True);
#print('There are no languages available in the system except english. Please check the language directory to ensure qm files exist');
-
+
#Set up the event handling for each of the menu items
self.connect(self.langActionGroup,QtCore.SIGNAL('triggered(QAction *)'), self.translateAction)
-
+
def add_talk(self):
presentation = Presentation(str(self.ui.titleEdit.text()),
str(self.ui.presenterEdit.text()),
@@ -206,10 +206,10 @@ def add_talk(self):
str(self.ui.eventEdit.text()),
str(self.ui.dateTimeEdit.text()),
str(self.ui.roomEdit.text()))
-
+
# Do not add talks if they are empty strings
if (len(presentation.title) == 0): return
-
+
self.core.add_talk(presentation)
# cleanup
@@ -225,13 +225,13 @@ def add_talk(self):
self.update_talk_views()
- def remove_talk(self):
+ def remove_talk(self):
try:
row_clicked = self.ui.editTable.currentRow()
- except:
+ except:
return
-
- id = self.ui.editTable.item(row_clicked, 5).text()
+
+ id = self.ui.editTable.item(row_clicked, 5).text()
self.core.delete_talk(str(id))
self.ui.editTable.removeRow(row_clicked)
self.update_talk_views()
@@ -257,19 +257,19 @@ def reset(self):
def load_talks(self):
talklist = self.core.get_talk_titles()
-
+
self.ui.editTable.clearContents()
- self.ui.editTable.setRowCount(0)
-
- for talk in talklist:
+ self.ui.editTable.setRowCount(0)
+
+ for talk in talklist:
index = self.ui.editTable.rowCount()
self.ui.editTable.insertRow(index)
-
- for i in range(len(talk)):
- self.ui.editTable.setItem(index, i, QtGui.QTableWidgetItem(unicode(talk[i])))
-
+
+ for i in range(len(talk)):
+ self.ui.editTable.setItem(index, i, QtGui.QTableWidgetItem(unicode(talk[i])))
+
self.ui.editTable.resizeRowsToContents()
-
+
def add_talks_from_rss(self):
rss_url = str(self.ui.rssEdit.text())
self.core.add_talks_from_rss(rss_url)
@@ -287,25 +287,25 @@ def update_talk_views(self):
# send the changed signal to Freeseer
self.emit(QtCore.SIGNAL('changed'))
-
+
def closeEvent(self, event):
self.core.logger.log.info('Exiting talk database editor...')
self.geometry = self.saveGeometry()