1
0
mirror of https://github.com/gryf/pygtktalog.git synced 2025-12-17 11:30:19 +01:00

changes in tests, upgrade to new EXIF module, etc

This commit is contained in:
2009-04-07 19:40:15 +00:00
parent fb920f58bc
commit 5e8c33f05a
14 changed files with 1241 additions and 741 deletions

5
README
View File

@@ -24,9 +24,8 @@ REQUIREMENTS
pyGTKtalog is written in python with following dependencies:
- python 2.4 or higher
- pygtk 2.10 or higher <http://www.pygtk.org>
- pysqlite2 <http://pysqlite.org/> (unnecessary, if python 2.5 is used)
- python 2.5 or higher
- pygtk 2.12 or higher <http://www.pygtk.org>
Optional modules:

View File

@@ -1,110 +1,62 @@
# This Python file uses the following encoding: utf-8
#
# Author: Roman 'gryf' Dobosz gryf@elysium.pl
#
# Copyright (C) 2007 by Roman 'gryf' Dobosz
#
# This file is part of pyGTKtalog.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# -------------------------------------------------------------------------
"""
Project: pyGTKtalog
Description: Application main launch file.
Type: core
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2007-05-01
"""
import sys
import os
try:
import gtk
except ImportError:
print "You need to install pyGTK v2.10.x or newer."
raise
import locale
import gettext
def setup_path():
"""Sets up the python include paths to include needed directories"""
import os.path
import gtk
import pygtk
pygtk.require("2.0")
import gtkmvc
gtkmvc.require("1.2.2")
from src.lib.globs import TOPDIR
from src.lib.globs import APPL_SHORT_NAME
sys.path = [os.path.join(TOPDIR, "src")] + sys.path
return
from models.m_config import ConfigModel
from models.m_main import MainModel
from ctrls.c_main import MainController
from views.v_main import MainView
def check_requirements():
"""Checks versions and other requirements"""
import sys
import gtkmvc
gtkmvc.require("1.2.0")
try:
from models.m_config import ConfigModel
except ImportError:
print "Some fundamental files are missing.",
print "Try runnig pyGTKtalog in his root directory"
raise
conf = ConfigModel()
conf.load()
try:
import pygtk
#tell pyGTK, if possible, that we want GTKv2
pygtk.require("2.0")
except ImportError:
#Some distributions come with GTK2, but not pyGTK
pass
try:
import sqlite3 as sqlite
except ImportError:
try:
from pysqlite2 import dbapi2 as sqlite
except ImportError:
print "pyGTKtalog uses SQLite DB.\nYou'll need to get it and the",
print "python bindings as well.",
print "http://www.sqlite.org"
print "http://initd.org/tracker/pysqlite"
print "Alternatively install python 2.5 or higher"
raise
if conf.confd['exportxls']:
try:
import pyExcelerator
except ImportError:
print "WARNING: You'll need pyExcelerator, if you want to export",
print "DB to XLS format."
print "http://sourceforge.net/projects/pyexcelerator"
if conf.confd['thumbs'] and conf.confd['retrive']:
try:
import Image
except ImportError:
print "WARNING: You'll need Python Imaging Library (PIL), if you",
print "want to make\nthumbnails!"
print _("WARNING: You'll need Python Imaging Library (PIL), if "
"you want to make thumbnails!")
raise
return
if __name__ == "__main__":
def run():
"""Create model, controller and view and launch it."""
# Directory from where pygtkatalog was invoced. We need it for calculate
# path for argument (catalog file)
execution_dir = os.path.abspath(os.path.curdir)
# Directory, where this files lies. We need it to setup private source
# paths
libraries_dir = os.path.dirname(__file__)
if libraries_dir:
os.chdir(libraries_dir)
setup_path()
#check_requirements()
# Setup i18n
locale.setlocale(locale.LC_ALL, '')
gettext.install(APPL_SHORT_NAME, 'locale', unicode=True)
from models.m_main import MainModel
from ctrls.c_main import MainController
from views.v_main import MainView
check_requirements()
model = MainModel()
if len(sys.argv) > 1:
@@ -115,6 +67,9 @@ if __name__ == "__main__":
try:
gtk.main()
except KeyboardInterrupt:
#model.config.save()
#model.cleanup()
model.config.save()
model.cleanup()
gtk.main_quit
if __name__ == "__main__":
run()

View File

@@ -252,7 +252,7 @@ class MainController(Controller):
except TypeError:
if __debug__:
print "c_main.py: on_edit2_activate(): 0",
print "zaznaczonych wierszy"
print "selected rows"
return
val = self.model.get_file_info(id)
@@ -281,11 +281,9 @@ class MainController(Controller):
def on_remove_thumb1_activate(self, menu_item):
if self.model.config.confd['delwarn']:
title = 'Delete thumbnails'
question = 'Delete thumbnails?'
description = "Thumbnails for selected items will be permanently"
description += " removed from catalog."
obj = Dialogs.Qst(title, question, description)
obj = Dialogs.Qst(_("Delete thumbnails"), _("Delete thumbnails?"),
_("Thumbnails for selected items will be "
"permanently removed from catalog."))
if not obj.run():
return
try:
@@ -307,11 +305,9 @@ class MainController(Controller):
def on_remove_image1_activate(self, menu_item):
if self.model.config.confd['delwarn']:
title = 'Delete images'
question = 'Delete all images?'
description = 'All images for selected items will be permanently'
description += ' removed from catalog.'
obj = Dialogs.Qst(title, question, description)
obj = Dialogs.Qst(_("Delete images"), _("Delete all images?"),
_("All images for selected items will be "
"permanently removed from catalog."))
if not obj.run():
return
try:
@@ -343,8 +339,8 @@ class MainController(Controller):
else:
ImageView(img)
else:
Dialogs.Inf("Image view", "No Image",
"Image file does not exist.")
Dialogs.Inf(_("Image view"), _("No Image"),
_("Image file does not exist."))
def on_rename1_activate(self, widget):
model, iter = self.view['discs'].get_selection().get_selected()
@@ -492,11 +488,10 @@ class MainController(Controller):
# check if any unsaved project is on go.
if self.model.unsaved_project and \
self.model.config.confd['confirmquit']:
title = 'Quit application - pyGTKtalog'
question = 'Do you really want to quit?'
description = "Current database is not saved, any changes will "
description += "be lost."
if not Dialogs.Qst(title, question, description).run():
if not Dialogs.Qst(_("Quit application") + " - pyGTKtalog",
_("Do you really want to quit?"),
_("Current database is not saved, any changes "
"will be lost.")).run():
return
self.__store_settings()
self.model.cleanup()
@@ -506,10 +501,10 @@ class MainController(Controller):
def on_new_activate(self, widget):
"""Create new database file"""
if self.model.unsaved_project:
title = 'Unsaved data - pyGTKtalog'
question = "Do you want to abandon changes?"
desc = "Current database is not saved, any changes will be lost."
if not Dialogs.Qst(title, question, desc).run():
if not Dialogs.Qst(_("Unsaved data") + " - pyGTKtalog",
_("Do you want to abandon changes?"),
_("Current database is not saved, any changes "
"will be lost.")).run():
return
self.model.new()
@@ -525,8 +520,8 @@ class MainController(Controller):
def on_add_cd_activate(self, widget, label=None, current_id=None):
"""Add directory structure from cd/dvd disc"""
mount = device_helper.volmount(self.model.config.confd['cd'])
if mount == 'ok':
mount, msg = device_helper.volmount(self.model.config.confd['cd'])
if mount:
guessed_label = device_helper.volname(self.model.config.confd['cd'])
if not label:
label = Dialogs.InputDiskLabel(guessed_label).run()
@@ -543,10 +538,10 @@ class MainController(Controller):
device_helper.volumount(self.model.config.confd['cd'])
return True
else:
Dialogs.Wrn("Error mounting device - pyGTKtalog",
"Cannot mount device pointed to %s" %
Dialogs.Wrn(_("Error mounting device") + " - pyGTKtalog",
_("Cannot mount device pointed to %s") %
self.model.config.confd['cd'],
"Last mount message:\n%s" % mount)
_("Last mount message:\n%s") % msg)
return False
def on_add_directory_activate(self, widget, path=None, label=None,
@@ -599,6 +594,7 @@ class MainController(Controller):
def on_save_activate(self, widget):
"""Save catalog to file"""
# FIXME: Traceback when recent is null
if self.model.filename:
self.model.save()
self.__set_title(filepath=self.model.filename)
@@ -618,8 +614,8 @@ class MainController(Controller):
self.model.config.add_recent(path)
self.__set_title(filepath=path)
else:
Dialogs.Err("Error writing file - pyGTKtalog",
"Cannot write file %s." % path, "%s" % err)
Dialogs.Err(_("Error writing file") + " - pyGTKtalog",
_("Cannot write file %s.") % path, "%s" % err)
def on_stat1_activate(self, menu_item, selected_id=None):
data = self.model.get_stats(selected_id)
@@ -640,9 +636,9 @@ class MainController(Controller):
"""Open catalog file"""
confirm = self.model.config.confd['confirmabandon']
if self.model.unsaved_project and confirm:
obj = Dialogs.Qst('Unsaved data - pyGTKtalog',
'There is not saved database',
'Pressing "Ok" will abandon catalog.')
obj = Dialogs.Qst(_("Unsaved data") + " - pyGTKtalog",
_("There is not saved database"),
_("Pressing <b>Ok</b> will abandon catalog."))
if not obj.run():
return
@@ -666,8 +662,8 @@ class MainController(Controller):
if path:
if not self.model.open(path):
Dialogs.Err("Error opening file - pyGTKtalog",
"Cannot open file %s." % path)
Dialogs.Err(_("Error opening file") + " - pyGTKtalog",
_("Cannot open file %s.") % path)
else:
self.__generate_recent_menu()
self.__activate_ui(path)
@@ -733,13 +729,14 @@ class MainController(Controller):
"""delete selected images (with thumbnails)"""
list_of_paths = self.view['images'].get_selected_items()
if not list_of_paths:
Dialogs.Inf("Delete images", "No images selected",
"You have to select at least one image to delete.")
Dialogs.Inf(_("Delete images"), _("No images selected"),
_("You have to select at least one image to delete."))
return
if self.model.config.confd['delwarn']:
obj = Dialogs.Qst('Delete images', 'Delete selected images?',
'Selected images will be permanently removed from catalog.')
obj = Dialogs.Qst(_("Delete images"), _("Delete selected images?"),
_("Selected images will be permanently removed"
" from catalog."))
if not obj.run():
return
@@ -768,7 +765,7 @@ class MainController(Controller):
def on_img_save_activate(self, menu_item):
"""export images (not thumbnails) into desired direcotry"""
dialog = Dialogs.SelectDirectory("Choose directory to save images")
dialog = Dialogs.SelectDirectory(_("Choose directory to save images"))
filepath = dialog.run()
if not filepath:
@@ -793,14 +790,13 @@ class MainController(Controller):
count += 1
if count > 0:
Dialogs.Inf("Save images",
"%d images was succsefully saved." % count,
"Images are placed in directory:\n%s." % filepath)
Dialogs.Inf(_("Save images"),
_("%d images was succsefully saved.") % count,
_("Images are placed in directory:\n%s.") % filepath)
else:
description = "Images probably don't have real images - only"
description += " thumbnails."
Dialogs.Inf("Save images",
"No images was saved.",
description = _("Images probably don't have real images - only"
" thumbnails.")
Dialogs.Inf(_("Save images"), _("No images was saved."),
description)
return
@@ -809,12 +805,12 @@ class MainController(Controller):
list_of_paths = self.view['images'].get_selected_items()
if not list_of_paths:
Dialogs.Inf("Set thumbnail", "No image selected",
"You have to select one image to set as thumbnail.")
Dialogs.Inf(_("Set thumbnail"), _("No image selected"),
_("You have to select one image to set as thumbnail."))
return
if len(list_of_paths) >1:
Dialogs.Inf("Set thumbnail", "To many images selected",
"You have to select one image to set as thumbnail.")
Dialogs.Inf(_("Set thumbnail"), _("To many images selected"),
_("You have to select one image to set as thumbnail."))
return
model = self.view['images'].get_model()
@@ -872,7 +868,7 @@ class MainController(Controller):
def on_export_activate(self, menu_item):
"""export db file and coressponding images to tar.bz2 archive"""
dialog = Dialogs.ChooseFilename(None, "Choose export file")
dialog = Dialogs.ChooseFilename(None, _("Choose export file"))
filepath = dialog.run()
if not filepath:
@@ -1018,8 +1014,8 @@ class MainController(Controller):
def on_delete_tag_activate(self, menu_item):
ids = self.__get_tv_selection_ids(self.view['files'])
if not ids:
Dialogs.Inf("Remove tags", "No files selected",
"You have to select some files first.")
Dialogs.Inf(_("Remove tags"), _("No files selected"),
_("You have to select some files first."))
return
tags = self.model.get_tags_by_file_id(ids)
@@ -1027,8 +1023,9 @@ class MainController(Controller):
d = Dialogs.TagsRemoveDialog(tags)
retcode, retval = d.run()
if retcode=="ok" and not retval:
Dialogs.Inf("Remove tags", "No tags selected",
"You have to select any tag to remove from files.")
Dialogs.Inf(_("Remove tags"), _("No tags selected"),
_("You have to select any tag to remove from"
" files."))
return
elif retcode == "ok" and retval:
self.model.delete_tags(ids, retval)
@@ -1053,7 +1050,7 @@ class MainController(Controller):
def on_add_image1_activate(self, menu_item):
dialog = Dialogs.LoadImageFile(True)
msg = "Don't copy images. Generate only thumbnails."
msg = _("Don't copy images. Generate only thumbnails.")
toggle = gtk.CheckButton(msg)
toggle.show()
dialog.dialog.set_extra_widget(toggle)
@@ -1117,15 +1114,15 @@ class MainController(Controller):
return
if not selected_iter:
Dialogs.Inf("Delete disc", "No disc selected",
"You have to select disc first before you " +\
"can delete it")
Dialogs.Inf(_("Delete disc"), _("No disc selected"),
_("You have to select disc first before you "
"can delete it"))
return
if self.model.config.confd['delwarn']:
name = model.get_value(selected_iter, 1)
obj = Dialogs.Qst('Delete %s' % name, 'Delete %s?' % name,
'Object will be permanently removed.')
obj = Dialogs.Qst(_("Delete %s") % name, _("Delete %s?") % name,
_("Object will be permanently removed."))
if not obj.run():
return
@@ -1168,14 +1165,14 @@ class MainController(Controller):
return
if not list_of_paths:
Dialogs.Inf("Delete files", "No files selected",
"You have to select at least one file to delete.")
Dialogs.Inf(_("Delete files"), _("No files selected"),
_("You have to select at least one file to delete."))
return
if self.model.config.confd['delwarn']:
description = "Selected files and directories will be "
description += "permanently\n removed from catalog."
obj = Dialogs.Qst("Delete files", "Delete files?", description)
obj = Dialogs.Qst(_("Delete files"), _("Delete files?"),
_("Selected files and directories will be "
"permanently\n removed from catalog."))
if not obj.run():
return
@@ -1216,10 +1213,9 @@ class MainController(Controller):
def on_th_delete_activate(self, menu_item):
if self.model.config.confd['delwarn']:
title = 'Delete thumbnail'
question = 'Delete thumbnail?'
dsc = "Current thumbnail will be permanently removed from catalog."
obj = Dialogs.Qst(title, question, dsc)
obj = Dialogs.Qst(_("Delete thumbnail"), _("Delete thumbnail?"),
_("Current thumbnail will be permanently removed"
" from catalog."))
if not obj.run():
return
path, column = self.view['files'].get_cursor()
@@ -1366,17 +1362,19 @@ class MainController(Controller):
msg = device_helper.eject_cd(ejectapp,
self.model.config.confd['cd'])
if msg != 'ok':
Dialogs.Wrn("error ejecting device - pyGTKtalog",
"Cannot eject device pointed to %s" %
title = _("Error ejecting device")
Dialogs.Wrn(title + " - pyGTKtalog",
_("Cannot eject device pointed to %s") %
self.model.config.confd['cd'],
"Last eject message:\n%s" % msg)
_("Last eject message:\n%s") % msg)
else:
msg = device_helper.volumount(self.model.config.confd['cd'])
if msg != 'ok':
Dialogs.Wrn("error unmounting device - pyGTKtalog",
"Cannot unmount device pointed to %s" %
title = _("Error unmounting device")
Dialogs.Wrn(title + " - pyGTKtalog",
_("Cannot unmount device pointed to %s") %
self.model.config.confd['cd'],
"Last umount message:\n%s" % msg)
_("Last umount message:\n%s") % msg)
return
def property_progress_value_change(self, model, old, new):

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +1,23 @@
# This Python file uses the following encoding: utf-8
#
# Author: Roman 'gryf' Dobosz gryf@elysium.pl
#
# Copyright (C) 2007 by Roman 'gryf' Dobosz
#
# This file is part of pyGTKtalog.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# -------------------------------------------------------------------------
"""
Project: pyGTKtalog
Description: Simple functions for device management.
Type: lib
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2008-12-15
"""
import os
import locale
import gettext
from src.lib.globs import APPL_SHORT_NAME
locale.setlocale(locale.LC_ALL, '')
gettext.install(APPL_SHORT_NAME, 'locale', unicode=True)
def volname(mntp):
"""read volume name from cd/dvd"""
dev = mountpoint_to_dev(mntp)
label = None
if dev != None:
try:
disk = open(dev, "rb")
@@ -36,16 +27,19 @@ def volname(mntp):
except IOError:
return None
return label
return None
def volmount(mntp):
"""mount device, return 'ok' or error message"""
"""
Mount device.
@param mountpoint
@returns tuple with bool status of mount, and string with error message
"""
_in, _out, _err = os.popen3("mount %s" % mntp)
inf = _err.readlines()
if len(inf) > 0:
return inf[0].strip()
return False, inf[0].strip()
else:
return 'ok'
return True, ''
def volumount(mntp):
"""mount device, return 'ok' or error message"""
@@ -88,5 +82,5 @@ def eject_cd(eject_app, cdrom):
return inf[0].strip()
return 'ok'
return "Eject program not specified"
return _("Eject program not specified")

View File

@@ -35,7 +35,7 @@ TOPDIR = top_dir
RESOURCES_DIR = os.path.join(TOPDIR, "resources")
GLADE_DIR = os.path.join(RESOURCES_DIR, "glade")
STYLES_DIR = os.path.join(RESOURCES_DIR, "styles")
APPL_SHORT_NAME = "pygtktalog2"
APPL_SHORT_NAME = "pygtktalog"
APPL_VERSION = (1, 0, 2)
# ----------------------------------------------------------------------

View File

@@ -27,7 +27,7 @@ import os
from datetime import date
class GthumbCommentParser(object):
"""Read and return comments created eith gThumb program"""
def __init__(self, image_path, image_filename):
self.path = image_path
self.filename = image_filename
@@ -36,16 +36,16 @@ class GthumbCommentParser(object):
"""Return dictionary with apropriate fields, or None if no comment
available"""
try:
gf = gzip.open(os.path.join(self.path,
'.comments', self.filename + '.xml'))
gzf = gzip.open(os.path.join(self.path, '.comments',
self.filename + '.xml'))
except:
return None
try:
xml = gf.read()
gf.close()
xml = gzf.read()
gzf.close()
except:
gf.close()
gzf.close()
return None
if not xml:

View File

@@ -44,7 +44,6 @@ class Img(object):
"""Save image and asociated thumbnail into specific directory structure
returns filename for image"""
image_filename = path.join(self.base, self.sha512)
thumbnail = path.join(self.base, self.sha512 + "_t")

View File

@@ -1,7 +1,12 @@
# This Python file uses the following encoding: utf-8
"""
Project: pyGTKtalog
Description: Gather video file information. Uses external tools.
Type: lib
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2008-12-15
"""
from os import popen
from sys import argv, exit
import sys
class Midentify(object):
"""Class for retrive midentify script output and put it in dict.
@@ -16,48 +21,41 @@ class Midentify(object):
def get_data(self):
"""return dict with clip information"""
output = popen("midentify \"%s\"" % self.filename).readlines()
output = popen('midentify "%s"' % self.filename).readlines()
attrs = {'ID_VIDEO_WIDTH': ['width', int],
'ID_VIDEO_HEIGHT': ['height', int],
'ID_LENGTH': ['length', lambda x: int(x.split(".")[0])],
# length is in seconds
'ID_DEMUXER': ['container', str],
'ID_VIDEO_FORMAT': ['video_format', str],
'ID_VIDEO_CODEC': ['video_codec', str],
'ID_AUDIO_CODEC': ['audio_codec', str],
'ID_AUDIO_FORMAT': ['audio_format', str],
'ID_AUDIO_NCH': ['audio_no_channels', int],}
for line in output:
line = line.strip()
if "ID_VIDEO_WIDTH" in line:
self.tags['width'] = line.replace("ID_VIDEO_WIDTH=", "")
elif "ID_VIDEO_HEIGHT" in line:
self.tags['height'] = line.replace("ID_VIDEO_HEIGHT=", "")
elif "ID_LENGTH" in line:
length = line.replace("ID_LENGTH=", "")
if "." in length:
length = length.split(".")[0]
seconds = int(length)
if seconds > 0:
hours = seconds / 3600
seconds -= hours * 3600
for attr in attrs:
if attr in line:
self.tags[attrs[attr][0]] = \
attrs[attr][1](line.replace("%s=" % attr, ""))
if 'length' in self.tags:
if self.tags['length'] > 0:
hours = self.tags['length'] / 3600
seconds = self.tags['length'] - hours * 3600
minutes = seconds / 60
seconds -= minutes * 60
self.tags['length'] = length
length_str = "%02d:%02d:%02d" % (hours, minutes, seconds)
self.tags['duration'] = length_str
elif "ID_DEMUXER" in line:
self.tags['container'] = line.replace("ID_DEMUXER=", "")
elif "ID_VIDEO_FORMAT" in line:
self.tags['video_format'] = line.replace("ID_VIDEO_FORMAT=", "")
elif "ID_VIDEO_CODEC" in line:
self.tags['video_codec'] = line.replace("ID_VIDEO_CODEC=", "")
elif "ID_AUDIO_CODEC" in line:
self.tags['audio_codec'] = line.replace("ID_AUDIO_CODEC=", "")
elif "ID_AUDIO_FORMAT" in line:
self.tags['audio_format'] = line.replace("ID_AUDIO_FORMAT=", "")
elif "ID_AUDIO_NCH" in line:
self.tags['audio_no_channels'] = line.replace("ID_AUDIO_NCH=",
"")
return self.tags
if __name__ == "__main__":
"""run as standalone script"""
if len(argv) < 2:
print "usage: %s filename" % argv[0]
exit()
if len(sys.argv) < 2:
print "usage: %s filename" % sys.argv[0]
sys.exit()
for arg in argv[1:]:
for arg in sys.argv[1:]:
mid = Midentify(arg)
print mid.get_data()

View File

@@ -27,23 +27,17 @@ import sys
import shutil
import bz2
import math
import sqlite3 as sqlite
from tempfile import mkstemp
from datetime import datetime
import threading as _threading
import gtk
import gobject
from gtkmvc.model_mt import ModelMT
try:
import sqlite3 as sqlite
except ImportError:
from pysqlite2 import dbapi2 as sqlite
from datetime import datetime
import threading as _threading
from m_config import ConfigModel
try:
from lib.thumbnail import Thumbnail
from lib.img import Img
@@ -53,6 +47,7 @@ from lib.parse_exif import ParseExif
from lib.gthumb import GthumbCommentParser
from lib.no_thumb import no_thumb as no_thumb_img
from lib.video import Video
class MainModel(ModelMT):
"""Create, load, save, manipulate db file which is container for data"""
@@ -91,6 +86,7 @@ class MainModel(ModelMT):
# images extensions - only for PIL and EXIF
IMG = ['jpg', 'jpeg', 'gif', 'png', 'tif', 'tiff', 'tga', 'pcx', 'bmp',
'xbm', 'xpm', 'jp2', 'jpx', 'pnm']
MOV = ['avi', 'mpg', 'mpeg', 'mkv', 'wmv', 'ogm', 'mov']
def __init__(self):
"""initialize"""
@@ -1754,6 +1750,23 @@ class MainModel(ModelMT):
ext = i.split('.')[-1].lower()
# Video
if ext in self.MOV:
#import rpdb2; rpdb2.start_embedded_debugger('pass')
v = Video(current_file)
cfn = v.capture()
img = Img(cfn, self.image_path)
th = img.save()
if th:
sql = """INSERT INTO
thumbnails(file_id, filename)
VALUES(?, ?)"""
db_cursor.execute(sql, (fileid, th+"_t"))
sql = """INSERT INTO images(file_id, filename)
VALUES(?, ?)"""
db_cursor.execute(sql, (fileid, th))
os.unlink(cfn)
# Images - thumbnails and exif data
if self.config.confd['thumbs'] and ext in self.IMG:
thumb = Thumbnail(current_file, self.image_path)

View File

@@ -1,53 +1,27 @@
#!/usr/bin/env python
# This Python file uses the following encoding: utf-8
#
# Author: Roman 'gryf' Dobosz gryf@elysium.pl
#
# Copyright (C) 2007 by Roman 'gryf' Dobosz
#
# This file is part of pyGTKtalog.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# -------------------------------------------------------------------------
"""
Project: pyGTKtalog
Description: Test harvester and runner.
Type: exec
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2008-12-15
"""
import sys
import unittest
from os import path, chdir
import glob
def my_import(module, name):
"""import replacement"""
mod = __import__(module, {}, {}, [name])
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
def setup_path():
"""Sets up the python include paths to include needed directories"""
this_path = path.abspath(path.dirname(__file__))
sys.path = [path.join(this_path, "../../src")] + sys.path
sys.path = [path.join(this_path, "../../src/test")] + sys.path
sys.path = [path.join(this_path, "../../src/test/unit")] + sys.path
return
def build_suite():
"""build suite test from files in unit directory"""
"""Build suite test from files in unit directory. Filenames with test
suites should always end with "_test.py"."""
modules = []
classes = []
for fname in glob.glob1('unit', '*_test.py'):
class_name = fname[:-8]
if "_" in class_name:
@@ -59,7 +33,6 @@ def build_suite():
class_name = "Test" + class_name.capitalize()
modules.append(fname[:-3])
classes.append(class_name)
modules = map(__import__, modules)
load = unittest.defaultTestLoader.loadTestsFromModule

View File

@@ -1,9 +1,15 @@
# This Python file uses the following encoding: utf-8
"""
Project: pyGTKtalog
Description: This is simple dummy test for... testing purposes :)
Type: test
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2008-12-15
"""
import unittest
class TestDummy(unittest.TestCase):
"""Fake test class"""
def test_dummyMethod(self):
def test_dummy_method(self):
"""Test simple assertion"""
self.assertTrue(True)

View File

@@ -1,9 +1,15 @@
# This Python file uses the following encoding: utf-8
"""
Project: pyGTKtalog
Description: This is another dummy test.
Type: test
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2008-12-15
"""
import unittest
class TestFooBar(unittest.TestCase):
"""Fake test class"""
def test_dummyMethod(self):
def test_dummy_method(self):
"""Test simple assertion"""
self.assertTrue(True)

View File

@@ -1,4 +1,10 @@
# This Python file uses the following encoding: utf-8
"""
Project: pyGTKtalog
Description: Tests for Midentify class.
Type: test
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2008-12-15
"""
import unittest
from lib.midentify import Midentify
@@ -8,82 +14,82 @@ class TestMidentify(unittest.TestCase):
Midentify script belongs to mplayer package.
"""
def test_testAvi(self):
def test_avi(self):
"""test mock avi file, should return dict with expected values"""
avi = Midentify("mocks/m.avi")
result_dict = avi.get_data()
self.assertTrue(len(result_dict) != 0, "result should have lenght > 0")
self.assertEqual(result_dict['audio_format'], '85')
self.assertEqual(result_dict['width'], '128')
self.assertEqual(result_dict['audio_no_channels'], '2')
self.assertEqual(result_dict['height'], '96')
self.assertEqual(result_dict['width'], 128)
self.assertEqual(result_dict['audio_no_channels'], 2)
self.assertEqual(result_dict['height'], 96)
self.assertEqual(result_dict['video_format'], 'XVID')
self.assertEqual(result_dict['length'], '4')
self.assertEqual(result_dict['length'], 4)
self.assertEqual(result_dict['audio_codec'], 'mp3')
self.assertEqual(result_dict['video_codec'], 'ffodivx')
self.assertEqual(result_dict['duration'], '00:00:04')
self.assertEqual(result_dict['container'], 'avi')
def test_testAvi2(self):
def test_avi2(self):
"""test another mock avi file, should return dict with expected
values"""
avi = Midentify("mocks/m1.avi")
result_dict = avi.get_data()
self.assertTrue(len(result_dict) != 0, "result should have lenght > 0")
self.assertEqual(result_dict['audio_format'], '85')
self.assertEqual(result_dict['width'], '128')
self.assertEqual(result_dict['audio_no_channels'], '2')
self.assertEqual(result_dict['height'], '96')
self.assertEqual(result_dict['width'], 128)
self.assertEqual(result_dict['audio_no_channels'], 2)
self.assertEqual(result_dict['height'], 96)
self.assertEqual(result_dict['video_format'], 'H264')
self.assertEqual(result_dict['length'], '4')
self.assertEqual(result_dict['length'], 4)
self.assertEqual(result_dict['audio_codec'], 'mp3')
self.assertEqual(result_dict['video_codec'], 'ffh264')
self.assertEqual(result_dict['duration'], '00:00:04')
self.assertEqual(result_dict['container'], 'avi')
def test_testMkv(self):
def test_mkv(self):
"""test mock mkv file, should return dict with expected values"""
avi = Midentify("mocks/m.mkv")
result_dict = avi.get_data()
self.assertTrue(len(result_dict) != 0, "result should have lenght > 0")
self.assertEqual(result_dict['audio_format'], '8192')
self.assertEqual(result_dict['width'], '128')
self.assertEqual(result_dict['audio_no_channels'], '2')
self.assertEqual(result_dict['height'], '96')
self.assertEqual(result_dict['width'], 128)
self.assertEqual(result_dict['audio_no_channels'], 2)
self.assertEqual(result_dict['height'], 96)
self.assertEqual(result_dict['video_format'], 'mp4v')
self.assertEqual(result_dict['length'], '4')
self.assertEqual(result_dict['length'], 4)
self.assertEqual(result_dict['audio_codec'], 'a52')
self.assertEqual(result_dict['video_codec'], 'ffodivx')
self.assertEqual(result_dict['duration'], '00:00:04')
self.assertEqual(result_dict['container'], 'mkv')
def test_testMpg(self):
def test_mpg(self):
"""test mock mpg file, should return dict with expected values"""
avi = Midentify("mocks/m.mpg")
result_dict = avi.get_data()
self.assertTrue(len(result_dict) != 0, "result should have lenght > 0")
self.assertFalse(result_dict.has_key('audio_format'))
self.assertEqual(result_dict['width'], '128')
self.assertEqual(result_dict['width'], 128)
self.assertFalse(result_dict.has_key('audio_no_channels'))
self.assertEqual(result_dict['height'], '96')
self.assertEqual(result_dict['height'], 96)
self.assertEqual(result_dict['video_format'], '0x10000001')
self.assertFalse(result_dict.has_key('lenght'))
self.assertFalse(result_dict.has_key('audio_codec'))
self.assertEqual(result_dict['video_codec'], 'mpegpes')
self.assertEqual(result_dict['video_codec'], 'ffmpeg1')
self.assertFalse(result_dict.has_key('duration'))
self.assertEqual(result_dict['container'], 'mpeges')
def test_testOgm(self):
def test_ogm(self):
"""test mock ogm file, should return dict with expected values"""
avi = Midentify("mocks/m.ogm")
result_dict = avi.get_data()
self.assertTrue(len(result_dict) != 0, "result should have lenght > 0")
self.assertEqual(result_dict['audio_format'], '8192')
self.assertEqual(result_dict['width'], '160')
self.assertEqual(result_dict['audio_no_channels'], '2')
self.assertEqual(result_dict['height'], '120')
self.assertEqual(result_dict['width'], 160)
self.assertEqual(result_dict['audio_no_channels'], 2)
self.assertEqual(result_dict['height'], 120)
self.assertEqual(result_dict['video_format'], 'H264')
self.assertEqual(result_dict['length'], '4')
self.assertEqual(result_dict['length'], 4)
self.assertEqual(result_dict['audio_codec'], 'a52')
self.assertEqual(result_dict['video_codec'], 'ffh264')
self.assertEqual(result_dict['duration'], '00:00:04')