Merge lp:~trb143/openlp/dnd into lp:openlp

Proposed by Tim Bentley
Status: Superseded
Proposed branch: lp:~trb143/openlp/dnd
Merge into: lp:openlp
Diff against target: 371 lines (+157/-33) (has conflicts)
9 files modified
openlp.pyw (+2/-0)
openlp/core/lib/__init__.py (+5/-0)
openlp/core/lib/listwidgetwithdnd.py (+50/-0)
openlp/core/lib/mediamanageritem.py (+52/-14)
openlp/core/ui/servicemanager.py (+29/-9)
openlp/plugins/images/lib/mediaitem.py (+3/-0)
openlp/plugins/media/lib/mediaitem.py (+12/-9)
openlp/plugins/presentations/lib/mediaitem.py (+3/-0)
openlp/plugins/songusage/songusageplugin.py (+1/-1)
Text conflict in openlp/core/lib/__init__.py
To merge this branch: bzr merge lp:~trb143/openlp/dnd
Reviewer Review Type Date Requested Status
Raoul Snyman Needs Fixing
Andreas Preikschat Pending
Review via email: mp+70201@code.launchpad.net

This proposal supersedes a proposal from 2011-08-02.

This proposal has been superseded by a proposal from 2011-08-03.

Description of the change

Move all the Drag and Drop changes from the B1 tree which is stuck at present.
It is no possible to Dnd Images, Presentations and Media into the plugins as wee as dragging a otz file into the service manager.

Can import Folders now.
Remove duplicate popups now.

Servicefile load now checks for unsaved file and asks to save.

To post a comment you must log in.
Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

A few things:

1) line 74: hasUrls should be hasUrls()
2) line 143: spelling (runn)
3) line 146-147, 165-166: wrong indents
4) Dropping a few files (e. g. images) makes the mainwindow process bar going from 0 to 100 (in one step) as many times as many files I drop (instead of increasing the bar after processing each file)
5) when I DnD a service file to the service manager without asking me to save an already opened service
6) I thought you were going to add support for folders as well (e. g. image library)
7) line 220-222, ...: I do not like this. All ListWidgets which allow dnd need to connect to the signal, thus it should be taken care of when activating the dnd. I am not sure if we should call/have an activate method. I was thinking about specifying this in the constructor or to have an attribute (like hasDnD) in the media manager.
8) When I DnD two files (e. g. "Copy of Foo" and "Foo") a dialog pops up and says that "Copy of Foo" is already in the list. I guess this will be/is fixed in your b1 branch?
9) The "duplicate error message" does not pop up once, instead it pop ups x times which can block the program (as you have to close x dialogs)

review: Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

line 74: hasUrls should be hasUrls()

review: Needs Fixing
lp:~trb143/openlp/dnd updated
1700. By Tim Bentley

Fix missing()

1701. By Tim Bentley

Fix conflict

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp.pyw'
--- openlp.pyw 2011-07-23 22:52:34 +0000
+++ openlp.pyw 2011-08-03 17:36:20 +0000
@@ -127,6 +127,8 @@
127 # now kill the splashscreen127 # now kill the splashscreen
128 self.splash.finish(self.mainWindow)128 self.splash.finish(self.mainWindow)
129 log.debug(u'Splashscreen closed')129 log.debug(u'Splashscreen closed')
130 # make sure Qt really display the splash screen
131 self.processEvents()
130 self.mainWindow.repaint()132 self.mainWindow.repaint()
131 self.processEvents()133 self.processEvents()
132 if not has_run_wizard:134 if not has_run_wizard:
133135
=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py 2011-07-30 07:34:37 +0000
+++ openlp/core/lib/__init__.py 2011-08-03 17:36:20 +0000
@@ -233,9 +233,14 @@
233 except IOError:233 except IOError:
234 pass234 pass
235235
236from eventreceiver import Receiver
236from listwidgetwithdnd import ListWidgetWithDnD237from listwidgetwithdnd import ListWidgetWithDnD
238<<<<<<< TREE
237from formattingtags import FormattingTags239from formattingtags import FormattingTags
238from eventreceiver import Receiver240from eventreceiver import Receiver
241=======
242from displaytags import DisplayTags
243>>>>>>> MERGE-SOURCE
239from spelltextedit import SpellTextEdit244from spelltextedit import SpellTextEdit
240from settingsmanager import SettingsManager245from settingsmanager import SettingsManager
241from plugin import PluginStatus, StringContent, Plugin246from plugin import PluginStatus, StringContent, Plugin
242247
=== 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-08-03 17:36:20 +0000
@@ -27,8 +27,12 @@
27"""27"""
28Extend QListWidget to handle drag and drop functionality28Extend QListWidget to handle drag and drop functionality
29"""29"""
30import os.path
31
30from PyQt4 import QtCore, QtGui32from PyQt4 import QtCore, QtGui
3133
34from openlp.core.lib import Receiver
35
32class ListWidgetWithDnD(QtGui.QListWidget):36class ListWidgetWithDnD(QtGui.QListWidget):
33 """37 """
34 Provide a list widget to store objects and handle drag and drop events38 Provide a list widget to store objects and handle drag and drop events
@@ -41,6 +45,16 @@
41 self.mimeDataText = name45 self.mimeDataText = name
42 assert(self.mimeDataText)46 assert(self.mimeDataText)
4347
48 def activateDnD(self):
49 """
50 Activate DnD of widget
51 """
52 self.setAcceptDrops(True)
53 self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
54 QtCore.QObject.connect(Receiver.get_receiver(),
55 QtCore.SIGNAL(u'%s_dnd' % self.mimeDataText),
56 self.parent().loadFile)
57
44 def mouseMoveEvent(self, event):58 def mouseMoveEvent(self, event):
45 """59 """
46 Drag and drop event does not care what data is selected60 Drag and drop event does not care what data is selected
@@ -58,3 +72,39 @@
58 drag.setMimeData(mimeData)72 drag.setMimeData(mimeData)
59 mimeData.setText(self.mimeDataText)73 mimeData.setText(self.mimeDataText)
60 drag.start(QtCore.Qt.CopyAction)74 drag.start(QtCore.Qt.CopyAction)
75
76 def dragEnterEvent(self, event):
77 if event.mimeData().hasUrls():
78 event.accept()
79 else:
80 event.ignore()
81
82 def dragMoveEvent(self, event):
83 if event.mimeData().hasUrls():
84 event.setDropAction(QtCore.Qt.CopyAction)
85 event.accept()
86 else:
87 event.ignore()
88
89 def dropEvent(self, event):
90 """
91 Receive drop event check if it is a file and process it if it is.
92
93 ``event``
94 Handle of the event pint passed
95 """
96 if event.mimeData().hasUrls():
97 event.setDropAction(QtCore.Qt.CopyAction)
98 event.accept()
99 files = []
100 for url in event.mimeData().urls():
101 localFile = unicode(url.toLocalFile())
102 if os.path.isfile(localFile):
103 files.append(localFile)
104 elif os.path.isdir(localFile):
105 listing = os.listdir(localFile)
106 for file in listing:
107 files.append(os.path.join(localFile,file))
108 Receiver.send_message(u'%s_dnd' % self.mimeDataText,files)
109 else:
110 event.ignore()
61111
=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py 2011-07-23 21:29:24 +0000
+++ openlp/core/lib/mediamanageritem.py 2011-08-03 17:36:20 +0000
@@ -252,7 +252,6 @@
252 self.listView.setSelectionMode(252 self.listView.setSelectionMode(
253 QtGui.QAbstractItemView.ExtendedSelection)253 QtGui.QAbstractItemView.ExtendedSelection)
254 self.listView.setAlternatingRowColors(True)254 self.listView.setAlternatingRowColors(True)
255 self.listView.setDragEnabled(True)
256 self.listView.setObjectName(u'%sListView' % self.plugin.name)255 self.listView.setObjectName(u'%sListView' % self.plugin.name)
257 # Add to pageLayout256 # Add to pageLayout
258 self.pageLayout.addWidget(self.listView)257 self.pageLayout.addWidget(self.listView)
@@ -339,26 +338,65 @@
339 log.info(u'New files(s) %s', unicode(files))338 log.info(u'New files(s) %s', unicode(files))
340 if files:339 if files:
341 Receiver.send_message(u'cursor_busy')340 Receiver.send_message(u'cursor_busy')
342 names = []341 self.validateAndLoad(files)
343 for count in range(0, self.listView.count()):342 Receiver.send_message(u'cursor_normal')
344 names.append(self.listView.item(count).text())343
345 newFiles = []344 def loadFile(self, files):
346 for file in files:345 """
347 filename = os.path.split(unicode(file))[1]346 Turn file from Drag and Drop into an array so the Validate code
348 if filename in names:347 can run it.
348
349 ``files``
350 The list of files to be loaded
351 """
352 newFiles = []
353 errorShown = False
354 for file in files:
355 type = file.split(u'.')[-1]
356 if type.lower() not in self.onNewFileMasks:
357 if not errorShown:
349 critical_error_message_box(358 critical_error_message_box(
350 UiStrings().Duplicate,359 translate('OpenLP.MediaManagerItem',
360 'Invalid File Type'),
351 unicode(translate('OpenLP.MediaManagerItem',361 unicode(translate('OpenLP.MediaManagerItem',
352 'Duplicate filename %s.\nThis filename is already in '362 'Invalid File %s.\nSuffix not supported'))
353 'the list')) % filename)363 % file)
354 else:364 errorShown = True
355 newFiles.append(file)365 else:
366 newFiles.append(file)
367 if file:
368 self.validateAndLoad(newFiles)
369
370 def validateAndLoad(self, files):
371 """
372 Process a list for files either from the File Dialog or from Drag and
373 Drop
374
375 ``files``
376 The files to be loaded
377 """
378 names = []
379 for count in range(0, self.listView.count()):
380 names.append(self.listView.item(count).text())
381 newFiles = []
382 duplicatesFound = False
383 for file in files:
384 filename = os.path.split(unicode(file))[1]
385 if filename in names:
386 duplicatesFound = True
387 else:
388 newFiles.append(file)
389 if newFiles:
356 self.loadList(newFiles)390 self.loadList(newFiles)
357 lastDir = os.path.split(unicode(files[0]))[0]391 lastDir = os.path.split(unicode(files[0]))[0]
358 SettingsManager.set_last_dir(self.settingsSection, lastDir)392 SettingsManager.set_last_dir(self.settingsSection, lastDir)
359 SettingsManager.set_list(self.settingsSection,393 SettingsManager.set_list(self.settingsSection,
360 self.settingsSection, self.getFileList())394 self.settingsSection, self.getFileList())
361 Receiver.send_message(u'cursor_normal')395 if duplicatesFound:
396 critical_error_message_box(
397 UiStrings().Duplicate,
398 unicode(translate('OpenLP.MediaManagerItem',
399 'Duplicate files found on import and ignored.')))
362400
363 def contextMenu(self, point):401 def contextMenu(self, point):
364 item = self.listView.itemAt(point)402 item = self.listView.itemAt(point)
365403
=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py 2011-07-24 17:52:53 +0000
+++ openlp/core/ui/servicemanager.py 2011-08-03 17:36:20 +0000
@@ -408,20 +408,33 @@
408 return False408 return False
409 self.newFile()409 self.newFile()
410410
411 def onLoadServiceClicked(self):411 def onLoadServiceClicked(self, loadFile=None):
412 """
413 Loads the service file and saves the existing one it there is one
414 unchanged
415
416 ``loadFile``
417 The service file to the loaded. Will be None is from menu so
418 selection will be required.
419 """
412 if self.isModified():420 if self.isModified():
413 result = self.saveModifiedService()421 result = self.saveModifiedService()
414 if result == QtGui.QMessageBox.Cancel:422 if result == QtGui.QMessageBox.Cancel:
415 return False423 return False
416 elif result == QtGui.QMessageBox.Save:424 elif result == QtGui.QMessageBox.Save:
417 self.saveFile()425 self.saveFile()
418 fileName = unicode(QtGui.QFileDialog.getOpenFileName(self.mainwindow,426 if not loadFile:
419 translate('OpenLP.ServiceManager', 'Open File'),427 fileName = unicode(QtGui.QFileDialog.getOpenFileName(
420 SettingsManager.get_last_dir(428 self.mainwindow,
421 self.mainwindow.serviceSettingsSection),429 translate('OpenLP.ServiceManager', 'Open File'),
422 translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')))430 SettingsManager.get_last_dir(
423 if not fileName:431 self.mainwindow.serviceSettingsSection),
424 return False432 translate('OpenLP.ServiceManager',
433 'OpenLP Service Files (*.osz)')))
434 if not fileName:
435 return False
436 else:
437 fileName = loadFile
425 SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection,438 SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection,
426 split_filename(fileName)[0])439 split_filename(fileName)[0])
427 self.loadFile(fileName)440 self.loadFile(fileName)
@@ -1239,7 +1252,14 @@
1239 Handle of the event pint passed1252 Handle of the event pint passed
1240 """1253 """
1241 link = event.mimeData()1254 link = event.mimeData()
1242 if link.hasText():1255 if event.mimeData().hasUrls():
1256 event.setDropAction(QtCore.Qt.CopyAction)
1257 event.accept()
1258 for url in event.mimeData().urls():
1259 filename = unicode(url.toLocalFile())
1260 if filename.endswith(u'.osz'):
1261 self.onLoadServiceClicked(filename)
1262 elif event.mimeData().hasText():
1243 plugin = unicode(event.mimeData().text())1263 plugin = unicode(event.mimeData().text())
1244 item = self.serviceManagerList.itemAt(event.pos())1264 item = self.serviceManagerList.itemAt(event.pos())
1245 # ServiceManager started the drag and drop1265 # ServiceManager started the drag and drop
12461266
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py 2011-07-03 08:13:48 +0000
+++ openlp/plugins/images/lib/mediaitem.py 2011-08-03 17:36:20 +0000
@@ -52,6 +52,8 @@
52 self.hasSearch = True52 self.hasSearch = True
53 QtCore.QObject.connect(Receiver.get_receiver(),53 QtCore.QObject.connect(Receiver.get_receiver(),
54 QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)54 QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
55 # Allow DnD from the desktop
56 self.listView.activateDnD()
5557
56 def retranslateUi(self):58 def retranslateUi(self):
57 self.onNewPrompt = translate('ImagePlugin.MediaItem',59 self.onNewPrompt = translate('ImagePlugin.MediaItem',
@@ -131,6 +133,7 @@
131 icon = self.iconFromFile(imageFile, thumb)133 icon = self.iconFromFile(imageFile, thumb)
132 item_name = QtGui.QListWidgetItem(filename)134 item_name = QtGui.QListWidgetItem(filename)
133 item_name.setIcon(icon)135 item_name.setIcon(icon)
136 item_name.setToolTip(imageFile)
134 item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))137 item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))
135 self.listView.addItem(item_name)138 self.listView.addItem(item_name)
136 if not initialLoad:139 if not initialLoad:
137140
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py 2011-07-03 08:13:48 +0000
+++ openlp/plugins/media/lib/mediaitem.py 2011-08-03 17:36:20 +0000
@@ -39,6 +39,8 @@
3939
40log = logging.getLogger(__name__)40log = logging.getLogger(__name__)
4141
42CLAPPERBOARD = QtGui.QPixmap(u':/media/media_video.png').toImage()
43
42class MediaMediaItem(MediaManagerItem):44class MediaMediaItem(MediaManagerItem):
43 """45 """
44 This is the custom media manager item for Media Slides.46 This is the custom media manager item for Media Slides.
@@ -48,8 +50,7 @@
48 def __init__(self, parent, plugin, icon):50 def __init__(self, parent, plugin, icon):
49 self.IconPath = u'images/image'51 self.IconPath = u'images/image'
50 self.background = False52 self.background = False
51 self.PreviewFunction = QtGui.QPixmap(53 self.PreviewFunction = CLAPPERBOARD
52 u':/media/media_video.png').toImage()
53 MediaManagerItem.__init__(self, parent, plugin, icon)54 MediaManagerItem.__init__(self, parent, plugin, icon)
54 self.singleServiceItem = False55 self.singleServiceItem = False
55 self.hasSearch = True56 self.hasSearch = True
@@ -60,6 +61,8 @@
60 QtCore.QObject.connect(Receiver.get_receiver(),61 QtCore.QObject.connect(Receiver.get_receiver(),
61 QtCore.SIGNAL(u'openlp_phonon_creation'),62 QtCore.SIGNAL(u'openlp_phonon_creation'),
62 self.createPhonon)63 self.createPhonon)
64 # Allow DnD from the desktop
65 self.listView.activateDnD()
6366
64 def retranslateUi(self):67 def retranslateUi(self):
65 self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')68 self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
@@ -201,17 +204,17 @@
201 SettingsManager.set_list(self.settingsSection,204 SettingsManager.set_list(self.settingsSection,
202 u'media', self.getFileList())205 u'media', self.getFileList())
203206
204 def loadList(self, files):207 def loadList(self, media):
205 # Sort the themes by its filename considering language specific208 # Sort the themes by its filename considering language specific
206 # characters. lower() is needed for windows!209 # characters. lower() is needed for windows!
207 files.sort(cmp=locale.strcoll,210 media.sort(cmp=locale.strcoll,
208 key=lambda filename: os.path.split(unicode(filename))[1].lower())211 key=lambda filename: os.path.split(unicode(filename))[1].lower())
209 for file in files:212 for track in media:
210 filename = os.path.split(unicode(file))[1]213 filename = os.path.split(unicode(track))[1]
211 item_name = QtGui.QListWidgetItem(filename)214 item_name = QtGui.QListWidgetItem(filename)
212 img = QtGui.QPixmap(u':/media/media_video.png').toImage()215 item_name.setIcon(build_icon(CLAPPERBOARD))
213 item_name.setIcon(build_icon(img))216 item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
214 item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))217 item_name.setToolTip(track)
215 self.listView.addItem(item_name)218 self.listView.addItem(item_name)
216219
217 def createPhonon(self):220 def createPhonon(self):
218221
=== 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-08-03 17:36:20 +0000
@@ -58,6 +58,8 @@
58 self.hasSearch = True58 self.hasSearch = True
59 QtCore.QObject.connect(Receiver.get_receiver(),59 QtCore.QObject.connect(Receiver.get_receiver(),
60 QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)60 QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
61 # Allow DnD from the desktop
62 self.listView.activateDnD()
6163
62 def retranslateUi(self):64 def retranslateUi(self):
63 """65 """
@@ -205,6 +207,7 @@
205 item_name = QtGui.QListWidgetItem(filename)207 item_name = QtGui.QListWidgetItem(filename)
206 item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))208 item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
207 item_name.setIcon(icon)209 item_name.setIcon(icon)
210 item_name.setToolTip(file)
208 self.listView.addItem(item_name)211 self.listView.addItem(item_name)
209 Receiver.send_message(u'cursor_normal')212 Receiver.send_message(u'cursor_normal')
210 if not initialLoad:213 if not initialLoad:
211214
=== modified file 'openlp/plugins/songusage/songusageplugin.py'
--- openlp/plugins/songusage/songusageplugin.py 2011-07-23 21:29:24 +0000
+++ openlp/plugins/songusage/songusageplugin.py 2011-08-03 17:36:20 +0000
@@ -91,8 +91,8 @@
91 self.toolsMenu.addAction(self.songUsageMenu.menuAction())91 self.toolsMenu.addAction(self.songUsageMenu.menuAction())
92 self.songUsageMenu.addAction(self.songUsageStatus)92 self.songUsageMenu.addAction(self.songUsageStatus)
93 self.songUsageMenu.addSeparator()93 self.songUsageMenu.addSeparator()
94 self.songUsageMenu.addAction(self.songUsageReport)
94 self.songUsageMenu.addAction(self.songUsageDelete)95 self.songUsageMenu.addAction(self.songUsageDelete)
95 self.songUsageMenu.addAction(self.songUsageReport)
96 self.songUsageActiveButton = QtGui.QToolButton(96 self.songUsageActiveButton = QtGui.QToolButton(
97 self.formparent.statusBar)97 self.formparent.statusBar)
98 self.songUsageActiveButton.setCheckable(True)98 self.songUsageActiveButton.setCheckable(True)