← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/b1 into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/b1 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  Bug #774853 in OpenLP: "Color formatting tag displays incorrect color"
  https://bugs.launchpad.net/openlp/+bug/774853
  Bug #793745 in OpenLP: "Drag & drop support from filesystem to media/image plugins"
  https://bugs.launchpad.net/openlp/+bug/793745

For more details, see:
https://code.launchpad.net/~trb143/openlp/b1/+merge/66019

This is a proposal for testing not merging.
It is likely to have bugs in it and I cannot test presentations properly.

I have also left in some debug prints so no comments on those.

What Have I changed.
- Refactored file load code so duplicate checking is at path/file level not file level
- Added a sort for file add (missing in trunk)! 
- Added Drag and Drop to Images, Presentations and Media.  It could be added to Songs and Bibles to start the import wizard if required.

- Added ability to have 2 files with the same name and different paths in the system.
   - Changes needed to ServiceItem so added versioning
   - Move setting from_plugin, from_serviceitem code.
   - Handle multi version serviceitem files

I think Images and Media work fine and have tested old files, new files, mixed files.
Basic Presentation code tested.

Please help me finish this by testing and letting me know what crashes.
BTW ServiceItem files are NOT backward compatible so OpenLP will crash.
-- 
https://code.launchpad.net/~trb143/openlp/b1/+merge/66019
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/b1 into lp:openlp.
=== modified file 'openlp.pyw'
--- openlp.pyw	2011-06-12 16:02:52 +0000
+++ openlp.pyw	2011-06-27 16:28:27 +0000
@@ -93,7 +93,7 @@
         # On Windows, the args passed into the constructor are
         # ignored. Not very handy, so set the ones we want to use.
         self.args = args
-        # provide a listener for widgets to reqest a screen update.
+        # provide a listener for widgets to request a screen update.
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
         QtCore.QObject.connect(Receiver.get_receiver(),
@@ -125,6 +125,8 @@
             # now kill the splashscreen
             self.splash.finish(self.mainWindow)
             log.debug(u'Splashscreen closed')
+        # make sure Qt really removes the splash screen
+        self.processEvents()
         self.mainWindow.repaint()
         self.processEvents()
         if not has_run_wizard:

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2011-06-12 16:02:52 +0000
+++ openlp/core/lib/__init__.py	2011-06-27 16:28:27 +0000
@@ -121,8 +121,7 @@
 
 def image_to_byte(image):
     """
-    Resize an image to fit on the current screen for the web and returns
-    it as a byte stream.
+    Convert an Image to a Base64 array.
 
     ``image``
         The image to converted.
@@ -233,9 +232,23 @@
     except IOError:
         pass
 
+def generate_hash_for_file(full_path, filename):
+    """
+    Convert a file path into a hash with correct file type
+
+    ``full_path``
+        Path to the file including the file name
+
+    ``filename``
+        The name of the file.
+    """
+    file_type = os.path.splitext(filename)[1]
+    hash_name = unicode(abs(hash(unicode(full_path))))
+    return u'%s%s' %(hash_name, file_type)
+
+from eventreceiver import Receiver
 from listwidgetwithdnd import ListWidgetWithDnD
 from displaytags import DisplayTags
-from eventreceiver import Receiver
 from spelltextedit import SpellTextEdit
 from settingsmanager import SettingsManager
 from plugin import PluginStatus, StringContent, Plugin

=== modified file 'openlp/core/lib/listwidgetwithdnd.py'
--- openlp/core/lib/listwidgetwithdnd.py	2011-06-12 16:02:52 +0000
+++ openlp/core/lib/listwidgetwithdnd.py	2011-06-27 16:28:27 +0000
@@ -29,6 +29,8 @@
 """
 from PyQt4 import QtCore, QtGui
 
+from openlp.core.lib import Receiver
+
 class ListWidgetWithDnD(QtGui.QListWidget):
     """
     Provide a list widget to store objects and handle drag and drop events
@@ -41,6 +43,13 @@
         self.mimeDataText = name
         assert(self.mimeDataText)
 
+    def activateDnD(self):
+        """
+        Activate DnD of widget
+        """
+        self.setAcceptDrops(True)
+        self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
+
     def mouseMoveEvent(self, event):
         """
         Drag and drop event does not care what data is selected
@@ -58,3 +67,33 @@
         drag.setMimeData(mimeData)
         mimeData.setText(self.mimeDataText)
         drag.start(QtCore.Qt.CopyAction)
+
+    def dragEnterEvent(self, event):
+        if event.mimeData().hasUrls:
+            event.accept()
+        else:
+            event.ignore()
+
+    def dragMoveEvent(self, event):
+        if event.mimeData().hasUrls:
+            event.setDropAction(QtCore.Qt.CopyAction)
+            event.accept()
+        else:
+            event.ignore()
+
+    def dropEvent(self, event):
+        """
+        Receive drop event check if it is a file and process it if it is.
+
+        ``event``
+            Handle of the event pint passed
+        """
+        if event.mimeData().hasUrls:
+            event.setDropAction(QtCore.Qt.CopyAction)
+            event.accept()
+            for url in event.mimeData().urls():
+                Receiver.send_message(u'%s_dnd' % self.mimeDataText,
+                    url.toLocalFile())
+
+        else:
+            event.ignore()

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2011-06-12 16:02:52 +0000
+++ openlp/core/lib/mediamanageritem.py	2011-06-27 16:28:27 +0000
@@ -252,7 +252,6 @@
         self.listView.setSelectionMode(
             QtGui.QAbstractItemView.ExtendedSelection)
         self.listView.setAlternatingRowColors(True)
-        self.listView.setDragEnabled(True)
         self.listView.setObjectName(u'%sListView' % self.plugin.name)
         # Add to pageLayout
         self.pageLayout.addWidget(self.listView)
@@ -331,27 +330,58 @@
         log.info(u'New files(s) %s', unicode(files))
         if files:
             Receiver.send_message(u'cursor_busy')
-            names = []
-            for count in range(0, self.listView.count()):
-                names.append(self.listView.item(count).text())
-            newFiles = []
-            for file in files:
-                filename = os.path.split(unicode(file))[1]
-                if filename in names:
-                    critical_error_message_box(
-                        UiStrings().Duplicate,
-                        unicode(translate('OpenLP.MediaManagerItem',
-                        'Duplicate filename %s.\nThis filename is already in '
-                        'the list')) % filename)
-                else:
-                    newFiles.append(file)
-            self.loadList(newFiles)
-            lastDir = os.path.split(unicode(files[0]))[0]
-            SettingsManager.set_last_dir(self.settingsSection, lastDir)
-            SettingsManager.set_list(self.settingsSection,
-                self.settingsSection, self.getFileList())
+            self.validateAndLoad(files)
         Receiver.send_message(u'cursor_normal')
 
+    def loadFile(self, filename):
+        """
+        Turn file from Drag and Drop into a array so the Validate code
+        can runn it.
+
+         ``filename``
+         The file to be loaded
+        """
+        filename = unicode(filename)
+        type = filename.split(u'.')[-1]
+        if type.lower() not in self.onNewFileMasks:
+            critical_error_message_box(
+                translate('OpenLP.MediaManagerItem',
+                'Invalid File Type'),
+                unicode(translate('OpenLP.MediaManagerItem',
+                'Invalid File %s.\nSuffix not supported'))
+                % filename)
+        else:
+            self.validateAndLoad([filename])
+
+    def validateAndLoad(self, files):
+        """
+        Process a list for files either from the File Dialog or from Drag and
+        Drop
+
+         ``files``
+         The files to be loaded
+        """
+        names = []
+        for count in range(0, self.listView.count()):
+            names.append(unicode(self.listView.item(count).
+                data(QtCore.Qt.UserRole).toString()))
+        for file in files:
+            filename = unicode(file)
+            if filename in names:
+                critical_error_message_box(
+                    UiStrings().Duplicate,
+                    unicode(translate('OpenLP.MediaManagerItem',
+                    'Duplicate filename %s.\nThis filename is already in '
+                    'the list')) % filename)
+            else:
+                names.append(file)
+        self.listView.clear()
+        self.loadList(names)
+        lastDir = os.path.split(unicode(files[0]))[0]
+        SettingsManager.set_last_dir(self.settingsSection, lastDir)
+        SettingsManager.set_list(self.settingsSection,
+            self.settingsSection, self.getFileList())
+
     def contextMenu(self, point):
         item = self.listView.itemAt(point)
         # Decide if we have to show the context menu or not.
@@ -476,7 +506,6 @@
             log.debug(u'%s Preview requested', self.plugin.name)
             serviceItem = self.buildServiceItem()
             if serviceItem:
-                serviceItem.from_plugin = True
                 self.plugin.previewController.addServiceItem(serviceItem)
                 if keepFocus:
                     self.listView.setFocus()
@@ -500,8 +529,6 @@
             item = self.createItemFromId(item_id)
         serviceItem = self.buildServiceItem(item)
         if serviceItem:
-            if not item_id:
-                serviceItem.from_plugin = True
             self.plugin.liveController.addServiceItem(serviceItem)
 
     def createItemFromId(self, item_id):
@@ -531,7 +558,6 @@
     def addToService(self, item=None, replace=None):
         serviceItem = self.buildServiceItem(item, True)
         if serviceItem:
-            serviceItem.from_plugin = False
             self.plugin.serviceManager.addServiceItem(serviceItem,
                 replace=replace)
 

=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2011-06-18 13:36:29 +0000
+++ openlp/core/lib/serviceitem.py	2011-06-27 16:28:27 +0000
@@ -35,7 +35,10 @@
 import os
 import uuid
 
-from openlp.core.lib import build_icon, clean_tags, expand_tags
+from PyQt4 import QtCore
+
+from openlp.core.lib import build_icon, clean_tags, expand_tags, \
+    generate_hash_for_file
 from openlp.core.lib.ui import UiStrings
 
 log = logging.getLogger(__name__)
@@ -67,7 +70,7 @@
     AllowsVariableStartTime = 12
     AllowsVirtualSplit = 13
     AllowsWordSplit = 14
-
+    Version20 = 99
 
 class ServiceItem(object):
     """
@@ -84,9 +87,19 @@
         ``plugin``
             The plugin that this service item belongs to.
         """
+        self.from_plugin = False
+        self.from_service = True
+        self.capabilities = []
         if plugin:
             self.renderer = plugin.renderer
             self.name = plugin.name
+            self.from_plugin = True
+            self.from_service = False
+            # mark with latest version
+            self.add_capability(ItemCapabilities.Version20)
+        else:
+            self.from_plugin = False
+            self.from_service = True
         self.title = u''
         self.shortname = u''
         self.audit = u''
@@ -100,8 +113,6 @@
         self._display_frames = []
         self._uuid = 0
         self.notes = u''
-        self.from_plugin = False
-        self.capabilities = []
         self.is_valid = True
         self.icon = None
         self.themedata = None
@@ -115,7 +126,6 @@
         self.start_time = 0
         self.end_time = 0
         self.media_length = 0
-        self.from_service = False
         self._new_item()
 
     def _new_item(self):
@@ -198,7 +208,7 @@
         self.foot_text = \
             u'<br>'.join([footer for footer in self.raw_footer if footer])
 
-    def add_from_image(self, path, title):
+    def add_from_image(self, path, title, reference=None):
         """
         Add an image slide to the service item.
 
@@ -209,8 +219,14 @@
             A title for the slide in the service item.
         """
         self.service_item_type = ServiceItemType.Image
-        self._raw_frames.append({u'title': title, u'path': path})
-        self.renderer.image_manager.add_image(title, path)
+        print path, title, reference
+        if not reference:
+            print "No Ref"
+            reference = generate_hash_for_file(path, title)
+            print reference
+        self._raw_frames.append({u'title': title, u'path': path,
+            u'reference': reference})
+        self.renderer.image_manager.add_image(reference, path)
         self._new_item()
 
     def add_from_text(self, title, raw_slide, verse_tag=None):
@@ -231,7 +247,7 @@
             {u'title': title, u'raw_slide': raw_slide, u'verseTag': verse_tag})
         self._new_item()
 
-    def add_from_command(self, path, file_name, image):
+    def add_from_command(self, path, file_name, image, reference=None):
         """
         Add a slide from a command.
 
@@ -243,10 +259,21 @@
 
         ``image``
             The command of/for the slide.
+
+        ``reference``
+            The unique reference the file uses
         """
         self.service_item_type = ServiceItemType.Command
+        print reference, path
+        if not reference:
+            path = os.path.join(path, file_name)
+            reference = generate_hash_for_file(path, file_name)
+        else:
+            path = os.path.join(path, reference)
+        print "video", path
         self._raw_frames.append(
-            {u'title': file_name, u'image': image, u'path': path})
+            {u'title': file_name, u'image': image, u'path': path,
+            u'reference':reference})
         self._new_item()
 
     def get_service_repr(self):
@@ -277,11 +304,18 @@
         if self.service_item_type == ServiceItemType.Text:
             service_data = [slide for slide in self._raw_frames]
         elif self.service_item_type == ServiceItemType.Image:
-            service_data = [slide[u'title'] for slide in self._raw_frames]
+            if self.is_capable(ItemCapabilities.Version20):
+                for slide in self._raw_frames:
+                    service_data.append(
+                        {u'title': slide[u'title'], u'path': slide[u'path'],
+                        u'reference': slide[u'reference']})
+            else:
+                service_data = [slide[u'title'] for slide in self._raw_frames]
         elif self.service_item_type == ServiceItemType.Command:
             for slide in self._raw_frames:
                 service_data.append(
-                    {u'title': slide[u'title'], u'image': slide[u'image']})
+                    {u'title': slide[u'title'], u'image': slide[u'image'],
+                    u'reference': slide[u'reference']})
         return {u'header': service_header, u'data': service_data}
 
     def set_from_service(self, serviceitem, path=None):
@@ -324,13 +358,19 @@
                 self._raw_frames.append(slide)
         elif self.service_item_type == ServiceItemType.Image:
             for text_image in serviceitem[u'serviceitem'][u'data']:
-                filename = os.path.join(path, text_image)
-                self.add_from_image(filename, text_image)
+                if self.is_capable(ItemCapabilities.Version20):
+                    self.add_from_image(text_image[u'path'],
+                        text_image[u'title'], text_image[u'reference'])
+                else:
+                    filename = os.path.join(path, text_image)
+                    self.add_from_image(filename, text_image)
         elif self.service_item_type == ServiceItemType.Command:
             for text_image in serviceitem[u'serviceitem'][u'data']:
+                print text_image
                 filename = os.path.join(path, text_image[u'title'])
                 self.add_from_command(
-                    path, text_image[u'title'], text_image[u'image'])
+                    path, text_image[u'title'], text_image[u'image'],
+                    text_image[u'reference'])
         self._new_item()
 
     def get_display_title(self):
@@ -345,7 +385,10 @@
             elif len(self._raw_frames) > 1:
                 return self.title
             else:
-                return self._raw_frames[0][u'title']
+                if len(self._raw_frames):
+                    return self._raw_frames[0][u'title']
+                else:
+                    return u''
 
     def merge(self, other):
         """
@@ -418,6 +461,10 @@
         if self.service_item_type == ServiceItemType.Text:
             return self._display_frames[row][u'html'].split(u'\n')[0]
         elif self.service_item_type == ServiceItemType.Image:
+            if u'reference' in self._raw_frames[row]:
+                return self._raw_frames[row][u'reference']
+            else:
+                return self._raw_frames[row][u'title']
             return self._raw_frames[row][u'title']
         else:
             return self._raw_frames[row][u'image']
@@ -460,4 +507,3 @@
             return end
         else:
             return u'%s : %s' % (start, end)
-

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2011-06-12 16:02:52 +0000
+++ openlp/core/ui/servicemanager.py	2011-06-27 16:28:27 +0000
@@ -34,7 +34,7 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \
-    ItemCapabilities, SettingsManager, translate
+    ItemCapabilities, SettingsManager, translate, generate_hash_for_file
 from openlp.core.lib.theme import ThemeLevel
 from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
     context_menu_action, context_menu_separator, find_and_set_in_combo_box
@@ -475,11 +475,18 @@
             if not item[u'service_item'].uses_file():
                 continue
             for frame in item[u'service_item'].get_frames():
-                if item[u'service_item'].is_image():
-                    path_from = frame[u'path']
+#                if item[u'service_item'].is_image():
+                path_from = frame[u'path']
+                if item[u'service_item'].from_plugin:
+                    path_to = os.path.join(self.servicePath,
+                        frame[u'reference'])
                 else:
-                    path_from = os.path.join(frame[u'path'], frame[u'title'])
+                    path_to = path_from
+#                else:
+#                    path_from = os.path.join(frame[u'path'], frame[u'title'])
+#                    path_to = path_from
                 # Only write a file once
+                print path_from,  path_to
                 if path_from in write_list:
                     continue
                 file_size = os.path.getsize(path_from)
@@ -499,7 +506,7 @@
                 #        QtGui.QMessageBox.Ok)
                 #    if ans == QtGui.QMessageBox.Cancel:
                 #        continue
-                write_list.append(path_from)
+                write_list.append([path_from,  path_to])
                 total_size += file_size
         log.debug(u'ServiceManager.saveFile - ZIP contents size is %i bytes' %
             total_size)
@@ -518,8 +525,8 @@
             # We save ALL filenames into ZIP using UTF-8.
             zip.writestr(service_file_name.encode(u'utf-8'), service_content)
             # Finally add all the listed media files.
-            for path_from in write_list:
-                zip.write(path_from, path_from.encode(u'utf-8'))
+            for path_from, path_to in write_list:
+                zip.write(path_from, path_to.encode(u'utf-8'))
         except IOError:
             log.exception(u'Failed to save service to disk')
             success = False
@@ -576,6 +583,7 @@
                 osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile))
                 filePath = os.path.join(self.servicePath,
                     os.path.split(osfile)[1])
+                print "fp", filePath
                 fileTo = open(filePath, u'wb')
                 fileTo.write(zip.read(file))
                 fileTo.flush()
@@ -592,7 +600,6 @@
                 for item in items:
                     self.mainwindow.incrementProgressBar()
                     serviceItem = ServiceItem()
-                    serviceItem.from_service = True
                     serviceItem.renderer = self.mainwindow.renderer
                     serviceItem.set_from_service(item, self.servicePath)
                     self.validateItem(serviceItem)

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2011-06-24 06:53:56 +0000
+++ openlp/core/ui/slidecontroller.py	2011-06-27 16:28:27 +0000
@@ -640,10 +640,11 @@
                     image = QtGui.QImage(frame[u'image'])
                 else:
                     # If current slide set background to image
+                    reference = self.serviceItem.get_rendered_frame(framenumber)
+                    image = self.imageManager.get_image(reference)
                     if framenumber == slideno:
                         self.serviceItem.bg_image_bytes = \
-                            self.imageManager.get_image_bytes(frame[u'title'])
-                    image = self.imageManager.get_image(frame[u'title'])
+                            self.imageManager.get_image_bytes(reference)
                 label.setPixmap(QtGui.QPixmap.fromImage(image))
                 self.previewListWidget.setCellWidget(framenumber, 0, label)
                 slideHeight = width * self.parent().renderer.screen_ratio
@@ -1130,7 +1131,7 @@
         Respond to the arrival of a media service item
         """
         log.debug(u'SlideController onMediaStart')
-        file = os.path.join(item.get_frame_path(), item.get_frame_title())
+        file = item.get_frame_path()
         if self.isLive:
             self.display.video(file, self.volume)
             self.volumeSlider.setValue(self.volume)

=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py	2011-06-12 17:56:11 +0000
+++ openlp/plugins/images/lib/mediaitem.py	2011-06-27 16:28:27 +0000
@@ -33,7 +33,7 @@
 
 from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
     SettingsManager, translate, check_item_selected, check_directory_exists, \
-    Receiver
+    Receiver, generate_hash_for_file
 from openlp.core.lib.ui import UiStrings, critical_error_message_box
 from openlp.core.utils import AppLocation, delete_file, get_images_filter
 
@@ -52,6 +52,10 @@
         self.hasSearch = True
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
+        # Allow DnD from the desktop
+        self.listView.activateDnD()
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'Images_dnd'), self.loadFile)
 
     def retranslateUi(self):
         self.onNewPrompt = translate('ImagePlugin.MediaItem',
@@ -121,7 +125,8 @@
             if not initialLoad:
                 self.plugin.formparent.incrementProgressBar()
             filename = os.path.split(unicode(imageFile))[1]
-            thumb = os.path.join(self.servicePath, filename)
+            thumb_file = generate_hash_for_file(imageFile, filename)
+            thumb = os.path.join(self.servicePath, thumb_file)
             if os.path.exists(thumb):
                 if self.validate(imageFile, thumb):
                     icon = build_icon(thumb)
@@ -132,6 +137,7 @@
             item_name = QtGui.QListWidgetItem(filename)
             item_name.setIcon(icon)
             item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))
+            item_name.setToolTip(imageFile)
             self.listView.addItem(item_name)
         if not initialLoad:
             self.plugin.formparent.finishedProgressBar()
@@ -208,7 +214,9 @@
             filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
             if os.path.exists(filename):
                 (path, name) = os.path.split(filename)
-                self.plugin.liveController.display.directImage(name, filename)
+                reference = generate_hash_for_file(filename, name)
+                self.plugin.liveController.display.directImage(reference,
+                    filename)
                 self.resetAction.setVisible(True)
             else:
                 critical_error_message_box(UiStrings().LiveBGError,

=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py	2011-06-12 17:56:11 +0000
+++ openlp/plugins/media/lib/mediaitem.py	2011-06-27 16:28:27 +0000
@@ -39,6 +39,8 @@
 
 log = logging.getLogger(__name__)
 
+CLAPPERBOARD = QtGui.QPixmap(u':/media/media_video.png').toImage()
+
 class MediaMediaItem(MediaManagerItem):
     """
     This is the custom media manager item for Media Slides.
@@ -48,8 +50,7 @@
     def __init__(self, parent, plugin, icon):
         self.IconPath = u'images/image'
         self.background = False
-        self.PreviewFunction = QtGui.QPixmap(
-            u':/media/media_video.png').toImage()
+        self.PreviewFunction = CLAPPERBOARD
         MediaManagerItem.__init__(self, parent, plugin, icon)
         self.singleServiceItem = False
         self.hasSearch = True
@@ -60,6 +61,10 @@
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'openlp_phonon_creation'),
             self.createPhonon)
+        # Allow DnD from the desktop
+        self.listView.activateDnD()
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'Media_dnd'), self.loadFile)
 
     def retranslateUi(self):
         self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
@@ -197,17 +202,17 @@
             SettingsManager.set_list(self.settingsSection,
                 u'media', self.getFileList())
 
-    def loadList(self, files):
+    def loadList(self, media):
         # Sort the themes by its filename considering language specific
         # characters. lower() is needed for windows!
-        files.sort(cmp=locale.strcoll,
+        media.sort(cmp=locale.strcoll,
             key=lambda filename: os.path.split(unicode(filename))[1].lower())
-        for file in files:
-            filename = os.path.split(unicode(file))[1]
+        for track in media:
+            filename = os.path.split(unicode(track))[1]
             item_name = QtGui.QListWidgetItem(filename)
-            img = QtGui.QPixmap(u':/media/media_video.png').toImage()
-            item_name.setIcon(build_icon(img))
-            item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
+            item_name.setIcon(build_icon(CLAPPERBOARD))
+            item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
+            item_name.setToolTip(track)
             self.listView.addItem(item_name)
 
     def createPhonon(self):
@@ -216,11 +221,11 @@
             self.mediaObject = Phonon.MediaObject(self)
 
     def search(self, string):
-        files = SettingsManager.load_list(self.settingsSection, u'media')
+        images = SettingsManager.load_list(self.settingsSection, u'media')
         results = []
         string = string.lower()
-        for file in files:
-            filename = os.path.split(unicode(file))[1]
+        for image in images:
+            filename = os.path.split(unicode(image))[1]
             if filename.lower().find(string) > -1:
                 results.append([file, filename])
         return results

=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py	2011-06-12 17:56:11 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py	2011-06-27 16:28:27 +0000
@@ -32,7 +32,8 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
-    translate, check_item_selected, Receiver, ItemCapabilities
+    translate, check_item_selected, Receiver, ItemCapabilities, \
+    generate_hash_for_file
 from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
     media_item_combo_box
 from openlp.plugins.presentations.lib import MessageListener
@@ -58,6 +59,10 @@
         self.hasSearch = True
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
+        # Allow DnD from the desktop
+        self.listView.activateDnD()
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'Presentations_dnd'), self.loadFile)
 
     def retranslateUi(self):
         """
@@ -205,6 +210,7 @@
             item_name = QtGui.QListWidgetItem(filename)
             item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
             item_name.setIcon(icon)
+            item_name.setToolTip(file)
             self.listView.addItem(item_name)
         Receiver.send_message(u'cursor_normal')
         if not initialLoad:

=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
--- openlp/plugins/presentations/lib/messagelistener.py	2011-06-15 22:34:40 +0000
+++ openlp/plugins/presentations/lib/messagelistener.py	2011-06-27 16:28:27 +0000
@@ -277,8 +277,7 @@
         item = message[0]
         log.debug(u'Startup called with message %s' % message)
         hide_mode = message[2]
-        file = os.path.join(item.get_frame_path(),
-            item.get_frame_title())
+        file = item.get_frame_title()
         self.handler = item.title
         if self.handler == self.mediaitem.Automatic:
             self.handler = self.mediaitem.findControllerByType(file)

=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
--- openlp/plugins/presentations/lib/presentationcontroller.py	2011-06-12 16:02:52 +0000
+++ openlp/plugins/presentations/lib/presentationcontroller.py	2011-06-27 16:28:27 +0000
@@ -31,7 +31,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, resize_image
+from openlp.core.lib import Receiver, resize_image, generate_hash_for_file
 from openlp.core.utils import AppLocation
 
 log = logging.getLogger(__name__)
@@ -133,8 +133,9 @@
         """
         The location where thumbnail images will be stored
         """
-        return os.path.join(
-            self.controller.thumbnail_folder, self.get_file_name())
+        hash_name = generate_hash_for_file(self.controller.thumbnail_folder,
+            self.get_file_name())
+        return os.path.join(self.controller.thumbnail_folder, hash_name)
 
     def get_temp_folder(self):
         """


Follow ups