~ubuntu-branches/ubuntu/quantal/mythtv/quantal

« back to all changes in this revision

Viewing changes to mythplugins/mythmusic/mythmusic/playlisteditorview.cpp

  • Committer: Package Import Robot
  • Author(s): Mario Limonciello
  • Date: 2012-03-05 21:49:35 UTC
  • mfrom: (1.1.78)
  • Revision ID: package-import@ubuntu.com-20120305214935-vxn0sv24s35dl1sw
Tags: 2:0.25.0~master.20120305.6519666-0ubuntu1
* Drop mythtv-themes metapackage and childish theme.  Should be installed
  exclusively through theme chooser now.
* Update Mythbuntu theme git links to still create that theme package.
* Update configure without install patch.
* Tweak default max_connections for mysql to be 100 per requests from
  mythtv mailing lists.
* Update to a checkout post mythtv 0.25 beta release.
* New upstream checkout (6519666)
* >>Upstream changes since last upload (532cee8):
* [6519666] Use deleteLater() when deleting server sockets in
  ServerPool.
* [b08b41b] Silence unused variable warning
* [5112e25] Silence unused variable warning
* [40c69e1] AvFormatDecoder: add FORCE_DTS_TIMESTAMPS environment
  variable
* [dbb5ffb] Merge branches 'master' and 'master' of
  github.com:MythTV/mythtv
* [57687c8] Subtitles: Initialize the SRT error count to avoid bogus
  diagnostics.
* [6c3a799] Increase kMaxUIWaitTime to 10 seconds. The theory is that
  this timeout was to prevent a very delayed response to an
  availability check causing playlists to resume playing long after
  the user had moved on. The present timeout was very short though and
  didn't account for delays caused by disks needing to be spun up or
  just the latency of checking multiple storage groups for a file.
  Almost certainly fixes #8316
* [dd9a92a] Subtitles: Fix a null pointer dereference when splitting
  long lines.
* [5f98ce1] Fixes #10367. Adds new Motorolla DCX-3200 vendor and
  device id.
* [7347bf5] Fix for WSDL generation.
* [a454b79] Allow the processing of uncompressed data from Schedules
  Direct.
* [f19c9c2] Minor changes to allow compilation using VS2010
* [0607b58] Fix build after [6a200130eff4]
* [6a20013] Handle more ISO-639 codes
* [d1a6cc8] Fix universal package build with new osx-builder
* [20f2c45] Fix UPnP for Sony BluRay players
* [638192e] mythtranscode: --fifoinfo reports aspect ratio of first
  uncut frame
* [18fdd67] Look in more than one location for libdvdcss on mac.
* [871a1cd] Giving up on Qt, doing it with an external command.
* [4392c16] Delay first call to QTextCodec until after main
  QApplication has been created
* [da7626e] Do not disable mythmusic dependencies when using --
  disable-all
* [ca996e0] Updated Norwegian Bokmal MythFrontend and all plugins
  translation from Rune Evjen.
* [18ab21a] Rearrange code in AddRangeList to defeat compile warnings
* [2422b6f] Miscellaneous string fixes
* [5e898a1] Fix HLS AddVideoLiveStream with files in subdirectories.
* [f834940] MythArchive: Remove the Cancel options from the menus
* [366d96d] Correct issue passing python library name for dependency
  checking.
* [c09418f] MythBrowser: Remove the Cancel options from the menus
* [002d7c5] MythMusic: Remove the Cancel options from the menus
* [bb3d1a8] MythMusic: Add some context menus on the playlist editor
  screen
* [bf4ff78] Per 2075458f5 Remove deprecated attribute from
  dispatchNow(), we know it's deprecated but it's not going away any
  time soon
* [12bbcf0] Fix a warning about an unused variable in httpconfig.cpp
* [43dcfce] Fix a warning about an unused variable in videolist.cpp
* [4edcda6] Move the Recording Profiles editor into mythtv-setup where
  it belongs. This constantly gets overlooked because it's not in the
  right place, especially by users who chose to use a third party
  frontend.
* [d7c8dfb] Better default device (when MediaMonitor disabled) on OS
  X. Refs #10370
* [7b526c4] Rework AudioReencodeBuffer further to fix HLS audio
  buffering
* [a130e74] Bump ABI version.
* [5e976b4] Rename util.h into mythmiscutil.h
* [efe385c] Fix dcraw detection on FreeBSD (old sh, not bash)
* [f5aa5e8] Use QNetworkAddressEntry to get proper broadcast address
  for udplistener
* [b6f9e1d] Revert "Rename util.h into mythutil.h"
* [84275f1] Revert "util.h rename itself didn't get committed"
* [8ef8c0b] Merge branch 'master' of github.com:MythTV/mythtv
* [0fe6e14] Totally rework the AudioReencodeBuffer part in transcode
* [fb8004a] util.h rename itself didn't get committed
* [ef771da] Rename util.h into mythutil.h
* [ba9b5d3] Rewrite configure for mythplugins
* [a5557a3] Fix MythZoneMinder on mac; the proper way..
* [30ed8f0] DeleteMap tracker: Fix an error in 94d27c67f.
* [6ae9f66] Rewrite configure for mythplugins
* [0fc9853] Fix MythZoneMinder on mac; the proper way..
* [79f5133] Updated US English MythFrontend and all plugins
  translation from the US English Language Translation Team.
* [6952dc4] Miscellaneous typo and case fixes.
* [b85f5bb] MythArchive: various minor mythburn.py script improvements
* [7e9cd56] Missed a change from cda7871f - I forgot to make install
  when testing and missed the breakage.
* [9d83307] Remove an errant <value> tag from the mythgallery default
  theme. This was causing some confusion for translators.
* [cda7871] Fix the channel icon not loading in the OSD on remote
  frontends by switching to using the channel icon storage group. This
  bug has been around for years so it's nice to finally have a fix.
* [e0e321f] Additional case and spacing fixes.
* [47c7c48] Add a few missing spaces...
* [736524b] Various case and punctuation fixes.
* [eba28f4] MythMusic: Only abort ripping upon confirmation
* [81acf24] Tweak the space available for the channel number so that
  it remains hidden behind the poster.
* [fbba2ae] Show coverart in the Terra OSD, falling back to channel
  icon if the artwork isn't available and channel number if the
  channel icon isn't available.
* [ff4d601] DVD navigation: Reenable skipping past the last chapter of
  a title, and skipping previous to the first chapter of a title.  The
  limitation may have been left over from an older version of
  libdvdnav.
* [8ea557a] Fix 'depends'. I'm surprised I didn't notice this earlier,
  perhaps because I was using <group> a lot I missed that depends
  behaviour didn't work for immediate children of <window>.
* [eb87f9e] Fix 'depends' for inherited and copied screens.
* [38221b8] Only show poster in the default-wide OSD when we're not
  displaying the channum/icon/callsign. Also center the poster better
  in the available space.
* [69cae58] Merge commit 'e965387441ff189bb2c096f8ed5bdbf2b2a473e6'
* [e965387] Add setup script and readme
* [905e8e5] Split 'mythtv/bindings/python/MythTV/tmdb3/' into commit
  '565041dddf9d4937c31c0d57475c548e56882e89'
* [565041d] Enable search paging for TMDB v3 API.
* [367b05d] Enable search paging for TMDB v3 API.
* [6113151] Add proper language support to TMDB v3 API.
* [6410395] Add proper language support to TMDB v3 API.
* [c65d8eb] Remove TMDB API key from request.py
* [6c4c60a] Remove TMDB API key from request.py
* [b38f901] Fix some null strings in SQL inserts on NOT NULL columns.
* [55fd3bf] MythUI: Make ascent/descent/bearing adjustment a little
  easier to follow, by using moveTop/moveLeft instead of setX/setY
* [d16575c] MythUI: fix a typo in MythUIText::DrawSelf that could
  result in an incorrect canvas size.
* [64383c5] Fix a compiler warning.
* [ecea05d] Added ENO to an error log in avformatdecoder
* [03e2387] Services API: Fix cut and paste error.
* [99abdfe] Update xml schema declaration for 0.25
* [6e2f231] Fix typo
* [05e5cf7] Updated Spanish/Spain MythFrontend, MythArchive,
  MythBrowser, MythGallery, MythGame, MythMusic, MythNetvision,
  MythNews, MythWeather transation from the Spanish Language
  Translation Team
* [2f895cb] Fix mythzoneminder on mac part #3
* [e34c8d7] Fix universal architecture compilation of myth on mac.
* [a513779] Fix MythZoneMinder part #2
* [700a58d] Remove stray include, same as <Qt>
* [d84d5c9] Add basic dead key support to mythuitextedit. Implemented
  from scratch because I couldn't see a way of getting QT to handle
  it. 
* [c3544ed] Fix mac compilation
* [6bfda0c] Fix mythoneminder compilation when using mysql universal
  libraries.
* [21ad34b] Add --firewire-sdk configuration switch to configure
* [3196c2c] Fix FireWire compilation on mac when compiling in 64 bits
  mode.
* [5dccbd5] Fix mac compilation when Qt Frameworks are in use.
* [20d6852] Fix libcec configure to work with v1.5
* [f16048b] Finish the db upgrade to 1299 (perl bindings)
* [d486b8a] Make artwork edit UI elements optional on video metadata
  edit screen.
* [38dfa89] Updated British English MythFrontend, MythArchive,
  MythGame and MythMusic translation from Nick Morrott
* [7e4740e] Refs #8941. Make sure we set the channum when switching to
  a new card with either a specific chanid or inputid.
* [05bc5e1] plugins configure: Remove some debugging left by mistake
* [ff593fa] Clean up the mappings for network control jump points.
* [146ee76] Fixes #8744. Fixes crash in DVB-x channel scanning.
* [6f24f3b] Subtitles: Rename the OSDSubFont setting to
  DefaultSubtitleFont.
* [6202c0d] Revert "Subtitles: Remove the OSDSubFont setting."
* [4a2420e] MythZoneMinder: Add support for the deep filesystem
  hierarchy for events.
* [a6b1e3a] Program editor: don't seek too far when stepping to the
  next keyframe.
* [97da8c8] Fix a doxygen comment
* [144c8bb] MythMusic: Do a full reload of the tracks and playlists
  after doing a scan
* [f78f999] Change delete behaviour so that we always use the deleted
  recording group allowing all recordings to be undeleted. By default
  we will only keep recordings for a minimum of 5 minutes (max ~20m)
  after their deletion, enough time to recover from a mistake but
  still free up space quickly. As before the user can specify to keep
  deleted recordings for a fixed number of days or until the space is
  needed for a new recording instead. Post 0.25 this change will allow
  us to strip out the old deletion code and simplify configuration
  process, the functional change is being made now to fix a couple of
  bugs caused by external processes such as MythPreviewGen blocking
  deletes from the UI. Fixes #9536
* [cfd3fc0] MythMusic: Fix the sending of the MUSIC_SETTINGS_CHANGED
  event
* [5932419] Merge branch 'compartist'
* [5206271] Subtitles: Apply OSDCC708TextZoom to CEA-608 captions as
  well.
* [99512fb] Refs #10386.  Don't sent EXIT_TO_MAIN event to Live TV
  jump point.
* [dfd909f] Fix crash on mac when no audio device exists.
* [bd68156] MythMusic: Fix the BLANKSCR keybinding not working
* [9016890] MythMusic: Check for some additional cdio headers
* [3570a99] MythMusic: Fix a memory leak in the playlist editor
* [7e6f5fa] Fixes #10386. Segfault fix. Check for null.
* [510da69] As noted in SHA1:9551bce2, MainServer doesn't know the
  actual recording status because it defaults to rsRecorded when the
  recordinginfo is initialized from the recorded table.  MainServer
  doesn't account for this and tries to make any needed state change
  which always ends up staying rsRecorded.  MainServer then passes
  this bad status to the scheduler.  If the recording had already
  failed, the rsFailed status gets overwritten.
* [3740d7d] Spelling consistency fixes
* [47d7c77] Fixes #9233. Refs #7408. Re-enables WindowResized().
* [a5447f1] MythMusic: Add a Compilations branch to the playlist
  editor
* [1824969] Fixes #10153. Guess at DVB-S vs DVB-S2 when not explicitly
  set.
* [21784ce] Fixes #10377. Prevent getting "stuck on a mux".
* [593d24b] Refs #10377. Some logging fixes. (VB_PLAYBACK-
  >VB_CHANNEL).
* [14ec737] Change the rsTuning UI state equivalent from 'tuning' to
  'running'. The UI states for the 'status' statetype are limited to 5
  generic values (normal, running, warning, error, disabled) to allow
  some portability to scenarios other than recording. (This was
  supposed to save themers some time and effort although it also binds
  their hands and doesn't allow as much creativity with how various
  recording states are represented. For this reason it may be re-
  visited post-0.25)
* [4d68d5e] Updated Russian MythFrontend, MythArchive, MythBrowser,
  MythGallery, MythGame, MythMusic, MythNews, MythWeather and
  MythZoneminder.
* [34c8767] Subtitles: fix an incorrect CEA-708 font mapping.
* [b967448] Fix the faulty exit code 139 issue in Ubuntu systems
* [723d798] Subtitles: improve vertical alignment for CEA-608
  captions.
* [1af1aec] Fixes display of position in the Program Lister.
  MythUIButtonList is zero indexed, to get a position for display we
  must add one.
* [967208b] Fix the last, hopefully, remaining places where
  livetvorder isn't honored.
* [0a301c0] Fix the scheduler to not write incorrect oldrecorded
  entries.
* [5d5aef3] Subtitles: improve the layout.
* [878d5eb] String consistency updated
* [456bb42] Updated Estonian MythFrontend and all plugins translation
  from Marko Punnar
* [e719d54] Replace tabs with spaces in Terra's schedule filter editor
  window xml
* [a3d9891] Use proper capitalization for some common words and
  prefixes.
* [5b19c4d] Populate the infomap from both RecordingRule and
  RecordingInfo if available. This fixes recording rule specific
  information not being available in the sub screens of the schedule
  editor.
* [f77d001] Fix minor problems editing in-progress recordings.
* [006ded1] Fix recording status strings being set to 'Not scheduled'
  when the reason for that is they were in the past and should have
  been marked as Recorded/Aborted/Failed/Cancelled/etc instead
* [6bedf81] Correct handling of unrelated argument after arg-less
  keyword.
* [7adbd54] Delay String processing until after QApplication has been
  initialized.
* [f613a43] Fix LiveTV switching by videosource to honor livetvorder.
* [9b5b7b5] Exit cutlist edit mode cleanly when executing a jump
  point.
* [c2a0b85] Updated British English translation MythFrontend
  translation from Nick Morrott.
* [307dac8] Make jump points work during playback when the OSD is
  present.
* [d59f4f4] Change dynamic cast to static. This is troubling because
  we rely on dynamic casts in so many places but for at least one
  person this cast was failing and causing popup menus in MythMusic to
  no longer have any effect. Maybe a buggy version of gcc?
* [3de87c3] Subtitles: Fix a logic error.
* [23d5167] Make host checks in Video Library scanner case
  insensitive.
* [5d7c01d] Cutlist editor: Update the edit bar for in-progress
  recordings.
* [1ce3d21] Cutlist editor: Adjust "Cut to End" behavior for an in-
  progress recording.
* [4a8546d] Merge branch 'master' of github.com:MythTV/mythtv
* [1d6485d] MythArchive consistency fixes.
* [89c34ef] Fix seeking backwards into a cut region.
* [6c3b564] Updated British English translation MythFrontend
  translation from Nick Morrott.
* [5501fff] Fix long-standing bug that always cleared
  record.next_record instead of updating it.
* [0c5de8e] Add missing menu closed event when closing the menu via
  the mouse. Fixes the menu dialog not working in some screens after
  being dismissed using a right click.
* [93c228d] Prevent crash when invoking the menu dialog via the right
  mouse button in Watch Recordings. ShowMenu() is a virtual method in
  MythScreenType, it's intended purpose is to load/display the context
  menu but here it is displaying a menu loaded elsewhere with no
  guards against duplicate popups being created. Move the menu display
  code to DisplayPopupMenu(), restore ShowMenu() to behave the same as
  the MENU key binding and re-instate the guards against multiple menu
  dialogs being created. Also fixes #10248 - 'Cannot delete recording
  if file is missing'
* [b755eca] Attempt to prevent a QString segfault if MythMenu changes
  while a dialog is open.
* [f3efafe] Fix segfault in MythUIButtonTree when list is empty and we
  attempt to navigate it. Refs #9101
* [b3e44a2] Rule type was missed from the RecordingRule text map.
  Added so that it appears twice in the map, once under the correct
  title of ruletype but also as rectype to be consistent with the
  ProgramInfo map until after 0.25 when we can rename that instance.
* [2075458] Remove deprecated attribute from dispatchNow(), we know
  it's deprecated but it's not going anywhere soon.
* [82fc1af] Add Collection support to developmental tmdb3 grabber.
* [0f0b0a7] Better backend metaclass, and people search support.
* [c47940a] Clean up and document background machinery
* [850fbc2] Replacement PagedList to temporarily work around bug in
  search API
* [d13addf] Add caching to tmdbv3 requests.
* [fe97f23] In progress TMDB v3 grabber script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include "smartplaylist.h"
22
22
#include "musicutils.h"
23
23
 
24
 
 
25
24
MusicGenericTree::MusicGenericTree(MusicGenericTree *parent,
26
25
                                   const QString &name, const QString &action,
27
26
                                   MythUIButtonListItem::CheckState check,
101
100
{
102
101
    saveTreePosition();
103
102
 
 
103
    for (int x = 0; x < m_deleteList.count(); x++)
 
104
        delete m_deleteList.at(x);
 
105
    m_deleteList.clear();
 
106
 
104
107
    if (m_rootNode)
105
108
        delete m_rootNode;
106
109
}
199
202
        //TODO should just update the relevent playlist here
200
203
        reloadTree();
201
204
    }
 
205
    else if (event->type() == DialogCompletionEvent::kEventType)
 
206
    {
 
207
        DialogCompletionEvent *dce = dynamic_cast<DialogCompletionEvent*>(event);
 
208
 
 
209
        if (!dce)
 
210
            return;
 
211
 
 
212
        // make sure the user didn't ESCAPE out of the menu
 
213
        if (dce->GetResult() < 0)
 
214
            return;
 
215
 
 
216
        QString resultid   = dce->GetId();
 
217
        QString resulttext = dce->GetResultText();
 
218
 
 
219
        if (resultid == "smartplaylistmenu")
 
220
        {
 
221
            if (GetFocusWidget() != m_playlistTree)
 
222
                return;
 
223
 
 
224
            MythGenericTree *node = m_playlistTree->GetCurrentNode();
 
225
            if (!node)
 
226
                return;
 
227
 
 
228
            MusicGenericTree *mnode = dynamic_cast<MusicGenericTree*>(node);
 
229
            if (!mnode)
 
230
                return;
 
231
 
 
232
            if (resulttext == tr("New Smart Playlist"))
 
233
            {
 
234
                QString category;
 
235
                if (mnode->getAction() == "smartplaylistcategory")
 
236
                    category = mnode->getString();
 
237
 
 
238
                MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
 
239
                SmartPlaylistEditor* editor = new SmartPlaylistEditor(mainStack);
 
240
 
 
241
                if (!editor->Create())
 
242
                {
 
243
                    delete editor;
 
244
                    return;
 
245
                }
 
246
 
 
247
                editor->newSmartPlaylist(category);
 
248
 
 
249
                connect(editor, SIGNAL(smartPLChanged(const QString&, const QString&)),
 
250
                        this, SLOT(smartPLChanged(QString, QString)));
 
251
 
 
252
                mainStack->AddScreen(editor);
 
253
            }
 
254
            else if (resulttext == tr("Remove Smart Playlist"))
 
255
            {
 
256
                QString category = mnode->getParent()->getString();
 
257
                QString name = mnode->getString();
 
258
 
 
259
                ShowOkPopup(QString("Are you sure you want to delete this Smart Playlist?\n"
 
260
                                    "Category: %1 - Name: %2").arg(category).arg(name),
 
261
                            this, SLOT(deleteSmartPlaylist(bool)), true);
 
262
            }
 
263
            else if (resulttext == tr("Edit Smart Playlist"))
 
264
            {
 
265
                QString category = mnode->getParent()->getString();
 
266
                QString name = mnode->getString();
 
267
 
 
268
                MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
 
269
                SmartPlaylistEditor* editor = new SmartPlaylistEditor(mainStack);
 
270
 
 
271
                if (!editor->Create())
 
272
                {
 
273
                    delete editor;
 
274
                    return;
 
275
                }
 
276
 
 
277
                editor->editSmartPlaylist(category, name);
 
278
 
 
279
                connect(editor, SIGNAL(smartPLChanged(const QString&, const QString&)),
 
280
                        this, SLOT(smartPLChanged(QString, QString)));
 
281
 
 
282
                mainStack->AddScreen(editor);
 
283
            }
 
284
            else if (resulttext == tr("Replace Tracks"))
 
285
            {
 
286
                m_playlistOptions.insertPLOption = PL_REPLACE;
 
287
                doUpdatePlaylist();
 
288
            }
 
289
            else if (resulttext == tr("Add Tracks"))
 
290
            {
 
291
                m_playlistOptions.insertPLOption = PL_INSERTATEND;
 
292
                doUpdatePlaylist();
 
293
            }
 
294
        }
 
295
        else if (resultid == "playlistmenu")
 
296
        {
 
297
            if (GetFocusWidget() != m_playlistTree)
 
298
                return;
 
299
 
 
300
            MythGenericTree *node = m_playlistTree->GetCurrentNode();
 
301
            if (!node)
 
302
                return;
 
303
 
 
304
            MusicGenericTree *mnode = dynamic_cast<MusicGenericTree*>(node);
 
305
            if (!mnode)
 
306
                return;
 
307
 
 
308
            if (resulttext == tr("Remove Playlist"))
 
309
            {
 
310
                QString name = mnode->getString();
 
311
 
 
312
                ShowOkPopup(QString("Are you sure you want to delete this Playlist?\n"
 
313
                                    "Name: %1").arg(name),
 
314
                            this, SLOT(deletePlaylist(bool)), true);
 
315
            }
 
316
            else if (resulttext == tr("Replace Tracks"))
 
317
            {
 
318
                m_playlistOptions.playPLOption = PL_CURRENT;
 
319
                m_playlistOptions.insertPLOption = PL_REPLACE;
 
320
                doUpdatePlaylist();
 
321
            }
 
322
            else if (resulttext == tr("Add Tracks"))
 
323
            {
 
324
                m_playlistOptions.insertPLOption = PL_INSERTATEND;
 
325
                doUpdatePlaylist();
 
326
            }
 
327
        }
 
328
    }
202
329
 
203
330
    MusicCommon::customEvent(event);
204
331
}
338
465
    return handled;
339
466
}
340
467
 
 
468
void PlaylistEditorView::ShowMenu(void)
 
469
{
 
470
    if (GetFocusWidget() == m_playlistTree)
 
471
    {
 
472
        m_playlistOptions.playPLOption = PL_CURRENT;
 
473
        m_playlistOptions.insertPLOption = PL_REPLACE;
 
474
 
 
475
        MythMenu *menu = NULL;
 
476
        MusicGenericTree *mnode = dynamic_cast<MusicGenericTree*>(m_playlistTree->GetCurrentNode());
 
477
 
 
478
        if (!mnode)
 
479
        {
 
480
            MusicCommon::ShowMenu();
 
481
            return;
 
482
        }
 
483
 
 
484
        if (mnode->getAction() == "smartplaylists" ||
 
485
            mnode->getAction() == "smartplaylistcategory" ||
 
486
            mnode->getAction() == "smartplaylist")
 
487
        {
 
488
            menu = createSmartPlaylistMenu();
 
489
        }
 
490
        else if (mnode->getAction() == "playlists" ||
 
491
                 mnode->getAction() == "playlist")
 
492
        {
 
493
            menu = createPlaylistMenu();
 
494
        }
 
495
        else if (mnode->getAction() == "album" ||
 
496
                 mnode->getAction() == "artist" ||
 
497
                 mnode->getAction() == "compartist" ||
 
498
                 mnode->getAction() == "genre" ||
 
499
                 mnode->getAction() == "year" ||
 
500
                 mnode->getAction() == "rating")
 
501
        {
 
502
            menu = createPlaylistOptionsMenu();
 
503
 
 
504
            m_songList.clear();
 
505
            MetadataPtrList *tracks = qVariantValue<MetadataPtrList*> (mnode->GetData());
 
506
            for (int x = 0; x < tracks->count(); x++)
 
507
            {
 
508
                Metadata *mdata = tracks->at(x);
 
509
                if (mdata)
 
510
                    m_songList.append((int)mdata->ID());
 
511
            }
 
512
        }
 
513
 
 
514
        if (menu)
 
515
        {
 
516
            menu->AddItem(tr("More Options"), NULL, createMainMenu());
 
517
 
 
518
            MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
 
519
 
 
520
            MythDialogBox *menuPopup = new MythDialogBox(menu, popupStack, "actionmenu");
 
521
 
 
522
            if (menuPopup->Create())
 
523
                popupStack->AddScreen(menuPopup);
 
524
            else
 
525
                delete menu;
 
526
 
 
527
            return;
 
528
        }
 
529
    }
 
530
 
 
531
    MusicCommon::ShowMenu();
 
532
}
 
533
 
 
534
MythMenu* PlaylistEditorView::createPlaylistMenu(void)
 
535
{
 
536
    MythMenu *menu = NULL;
 
537
 
 
538
    if (GetFocusWidget() == m_playlistTree)
 
539
    {
 
540
        MusicGenericTree *mnode = dynamic_cast<MusicGenericTree*>(m_playlistTree->GetCurrentNode());
 
541
 
 
542
        if (!mnode)
 
543
            return NULL;
 
544
 
 
545
        if (mnode->getAction() == "playlist")
 
546
        {
 
547
            menu = new MythMenu(tr("Playlist Actions"), this, "playlistmenu");
 
548
            menu->AddItem(tr("Replace Tracks"));
 
549
            menu->AddItem(tr("Add Tracks"));
 
550
            menu->AddItem(tr("Remove Playlist"));
 
551
 
 
552
            // get list of tracks to add
 
553
            m_songList.clear();
 
554
            int playlistID = mnode->getInt();
 
555
            Playlist *playlist = gMusicData->all_playlists->getPlaylist(playlistID);
 
556
 
 
557
            if (playlist)
 
558
            {
 
559
                SongList songlist = playlist->getSongs();
 
560
 
 
561
                for (int x = 0; x < songlist.count(); x++)
 
562
                {
 
563
                    m_songList.append(songlist.at(x)->ID());
 
564
                }
 
565
            }
 
566
        }
 
567
    }
 
568
 
 
569
    return menu;
 
570
}
 
571
 
 
572
MythMenu* PlaylistEditorView::createSmartPlaylistMenu(void)
 
573
{
 
574
    MythMenu *menu = NULL;
 
575
 
 
576
    if (GetFocusWidget() == m_playlistTree)
 
577
    {
 
578
        MusicGenericTree *mnode = dynamic_cast<MusicGenericTree*>(m_playlistTree->GetCurrentNode());
 
579
 
 
580
        if (!mnode)
 
581
            return NULL;
 
582
 
 
583
        if (mnode->getAction() == "smartplaylists" || mnode->getAction() == "smartplaylistcategory")
 
584
        {
 
585
            QString label = tr("Smart Playlist Actions");
 
586
 
 
587
            menu = new MythMenu(label, this, "smartplaylistmenu");
 
588
 
 
589
            menu->AddItem(tr("New Smart Playlist"));
 
590
        }
 
591
        else if (mnode->getAction() == "smartplaylist")
 
592
        {
 
593
            menu = new MythMenu(tr("Smart Playlist Actions"), this, "smartplaylistmenu");
 
594
 
 
595
            menu->AddItem(tr("Replace Tracks"));
 
596
            menu->AddItem(tr("Add Tracks"));
 
597
 
 
598
            menu->AddItem(tr("Edit Smart Playlist"));
 
599
            menu->AddItem(tr("New Smart Playlist"));
 
600
            menu->AddItem(tr("Remove Smart Playlist"));
 
601
 
 
602
            // add the selected smart playlist's tracks to the song list
 
603
            m_songList.clear();
 
604
            QList<MythGenericTree*> *children = mnode->getAllChildren();
 
605
            for (int x = 0; x < children->count(); x++)
 
606
            {
 
607
                MythGenericTree *childnode = children->at(x);
 
608
                m_songList.append(childnode->getInt());
 
609
            }
 
610
        }
 
611
    }
 
612
 
 
613
    return menu;
 
614
}
 
615
 
341
616
void PlaylistEditorView::createRootNode(void )
342
617
{
343
618
    if (!m_rootNode)
370
645
    node = new MusicGenericTree(m_rootNode, tr("Years"), "years");
371
646
    node->setDrawArrow(true);
372
647
    node->SetData(qVariantFromValue(gMusicData->all_music->getAllMetadata()));
 
648
 
 
649
    node = new MusicGenericTree(m_rootNode, tr("Compilations"), "compilations");
 
650
    node->setDrawArrow(true);
 
651
 
 
652
    MetadataPtrList *alltracks = gMusicData->all_music->getAllMetadata();
 
653
    MetadataPtrList *compTracks = new MetadataPtrList;
 
654
    m_deleteList.append(compTracks);
 
655
 
 
656
    for (int x = 0; x < alltracks->count(); x++)
 
657
    {
 
658
        Metadata *mdata = alltracks->at(x);
 
659
        if (mdata)
 
660
        {
 
661
            if (mdata->Compilation())
 
662
                compTracks->append(mdata);
 
663
        }
 
664
    }
 
665
    node->SetData(qVariantFromValue(compTracks));
 
666
 
373
667
#if 0
374
668
    node = new MusicGenericTree(m_rootNode, tr("Directory"), "directory");
375
669
    node->setDrawArrow(true);
391
685
 
392
686
    if (mnode->getAction() == "smartplaylists" ||
393
687
        mnode->getAction() == "smartplaylistcategory" ||
394
 
        mnode->getAction() == "playlists")
395
 
    {
396
 
        return;
397
 
    }
398
 
    else if (mnode->getAction() == "smartplaylist")
399
 
    {
400
 
        // add selected smart playlist's tracks to the current playlist
401
 
        m_songList.clear();
402
 
        QList<MythGenericTree*> *children = node->getAllChildren();
403
 
        for (int x = 0; x < children->count(); x++)
404
 
        {
405
 
            MythGenericTree *childnode = children->at(x);
406
 
            m_songList.append(childnode->getInt());
407
 
        }
408
 
 
409
 
        showPlaylistOptionsMenu();
410
 
    }
411
 
    else if (mnode->getAction() == "playlist")
412
 
    {
413
 
        // add selected playlist's tracks to the current playlist
414
 
 
415
 
        // get list of tracks to add
416
 
        int playlistID = mnode->getInt();
417
 
        Playlist *playlist = gMusicData->all_playlists->getPlaylist(playlistID);
418
 
 
419
 
        if (!playlist)
420
 
            return;
421
 
 
422
 
        SongList songlist = playlist->getSongs();
423
 
 
424
 
        for (int x = 0; x < songlist.count(); x++)
425
 
        {
426
 
            m_songList.append(songlist.at(x)->ID());
427
 
        }
428
 
 
429
 
        // show the playlist options dialog
430
 
        showPlaylistOptionsMenu();
431
 
    }
432
 
    else if (mnode->getAction() == "album" || mnode->getAction() == "artist" ||
433
 
             mnode->getAction() == "genre" || mnode->getAction() == "year" ||
434
 
             mnode->getAction() == "rating")
435
 
    {
436
 
        MetadataPtrList *tracks = qVariantValue<MetadataPtrList*> (node->GetData());
437
 
        for (int x = 0; x < tracks->count(); x++)
438
 
        {
439
 
            Metadata *mdata = tracks->at(x);
440
 
            if (mdata)
441
 
                m_songList.append((int)mdata->ID());
442
 
        }
443
 
 
444
 
        // show the playlist options dialog
445
 
        showPlaylistOptionsMenu();
 
688
        mnode->getAction() == "playlists" ||
 
689
        mnode->getAction() == "smartplaylist" ||
 
690
        mnode->getAction() == "playlist" ||
 
691
        mnode->getAction() == "album" ||
 
692
        mnode->getAction() == "artist" ||
 
693
        mnode->getAction() == "compartist" ||
 
694
        mnode->getAction() == "genre" ||
 
695
        mnode->getAction() == "year" ||
 
696
        mnode->getAction() == "rating")
 
697
    {
 
698
        ShowMenu();
446
699
    }
447
700
    else if (mnode->getAction() == "trackid")
448
701
    {
496
749
        {
497
750
            artFile = "mm_artists.png";
498
751
        }
 
752
        else if (mnode->getAction() == "compartists")
 
753
        {
 
754
            //TODO add a compilation artist icon
 
755
            artFile = "mm_artists.png";
 
756
        }
499
757
        else if (mnode->getAction() == "ratings")
500
758
        {
501
759
            artFile = "mm_ratings.png";
634
892
                else
635
893
                {
636
894
                    MetadataPtrList *filteredTracks = new MetadataPtrList;
 
895
                    m_deleteList.append(filteredTracks);
637
896
                    filteredTracks->append(mdata);
638
897
                    map.insert(mdata->Artist(), filteredTracks);
639
898
                }
648
907
            ++i;
649
908
        }
650
909
    }
 
910
    else if (node->getAction() == "compartists")
 
911
    {
 
912
        QMap<QString, MetadataPtrList*> map;
 
913
 
 
914
        for (int x = 0; x < tracks->count(); x++)
 
915
        {
 
916
            Metadata *mdata = tracks->at(x);
 
917
            if (mdata)
 
918
            {
 
919
                if (mdata->CompilationArtist() != mdata->Artist())
 
920
                {
 
921
                    if (map.contains(mdata->CompilationArtist()))
 
922
                    {
 
923
                        MetadataPtrList *filteredTracks = map.value(mdata->CompilationArtist());
 
924
                        filteredTracks->append(mdata);
 
925
                    }
 
926
                    else
 
927
                    {
 
928
                        MetadataPtrList *filteredTracks = new MetadataPtrList;
 
929
                        m_deleteList.append(filteredTracks);
 
930
                        filteredTracks->append(mdata);
 
931
                        map.insert(mdata->CompilationArtist(), filteredTracks);
 
932
                    }
 
933
                }
 
934
            }
 
935
        }
 
936
 
 
937
        QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
 
938
        while (i != map.constEnd())
 
939
        {
 
940
            MusicGenericTree *newnode = new MusicGenericTree(node, i.key(), "compartist");
 
941
            newnode->SetData(qVariantFromValue(i.value()));
 
942
            ++i;
 
943
        }
 
944
    }
651
945
    else if (node->getAction() == "albums")
652
946
    {
653
947
        QMap<QString, MetadataPtrList*> map;
665
959
                else
666
960
                {
667
961
                    MetadataPtrList *filteredTracks = new MetadataPtrList;
 
962
                    m_deleteList.append(filteredTracks);
668
963
                    filteredTracks->append(mdata);
669
964
                    map.insert(mdata->Album(), filteredTracks);
670
965
                }
697
992
                else
698
993
                {
699
994
                    MetadataPtrList *filteredTracks = new MetadataPtrList;
 
995
                    m_deleteList.append(filteredTracks);
700
996
                    filteredTracks->append(mdata);
701
997
                    map.insert(mdata->Genre(), filteredTracks);
702
998
                }
729
1025
                else
730
1026
                {
731
1027
                    MetadataPtrList *filteredTracks = new MetadataPtrList;
 
1028
                    m_deleteList.append(filteredTracks);
732
1029
                    filteredTracks->append(mdata);
733
1030
                    map.insert(ratingStr, filteredTracks);
734
1031
                }
762
1059
                else
763
1060
                {
764
1061
                    MetadataPtrList *filteredTracks = new MetadataPtrList;
 
1062
                    m_deleteList.append(filteredTracks);
765
1063
                    filteredTracks->append(mdata);
766
1064
                    map.insert(yearStr, filteredTracks);
767
1065
                }
777
1075
        }
778
1076
 
779
1077
    }
780
 
    else if (node->getAction() == "artist" || node->getAction() == "album" ||
781
 
             node->getAction() == "genre" || node->getAction() == "rating" ||
782
 
             node->getAction() == "year")
 
1078
    else if (node->getAction() == "artist" || node->getAction() == "compartist" ||
 
1079
             node->getAction() == "album" || node->getAction() == "genre" ||
 
1080
             node->getAction() == "rating" || node->getAction() == "year" ||
 
1081
             node->getAction() == "compilations")
783
1082
    {
784
1083
        // which fields have we already filtered by
785
1084
        QStringList fields;
801
1100
            newnode->SetData(node->GetData());
802
1101
        }
803
1102
 
804
 
 
805
1103
        if (!fields.contains("artists"))
806
1104
        {
807
1105
            newnode = new MusicGenericTree(node, tr("Artists"), "artists");
809
1107
            newnode->SetData(node->GetData());
810
1108
        }
811
1109
 
 
1110
        if (!fields.contains("compartists"))
 
1111
        {
 
1112
            // only show the Compilation Artists node if we are one the Compilations branch
 
1113
            bool showCompArtists = false;
 
1114
            MusicGenericTree *mnode = node;
 
1115
            do
 
1116
            {
 
1117
                if (mnode->getAction() == "compilations")
 
1118
                {
 
1119
                    showCompArtists = true;
 
1120
                    break;
 
1121
                }
 
1122
 
 
1123
                mnode = (MusicGenericTree *) mnode->getParent();
 
1124
 
 
1125
            } while (mnode);
 
1126
 
 
1127
            // only show the Comp. Artist if it differs from the Artist
 
1128
            bool found = false;
 
1129
            MetadataPtrList *tracks = qVariantValue<MetadataPtrList*> (node->GetData());
 
1130
            for (int x = 0; x < tracks->count(); x++)
 
1131
            {
 
1132
                Metadata *mdata = tracks->at(x);
 
1133
                if (mdata)
 
1134
                {
 
1135
                    if (mdata->Artist() != mdata->CompilationArtist())
 
1136
                    {
 
1137
                        found = true;
 
1138
                        break;
 
1139
                    }
 
1140
                }
 
1141
            }
 
1142
 
 
1143
            if (showCompArtists && found)
 
1144
            {
 
1145
                newnode = new MusicGenericTree(node, tr("Compilation Artists"), "compartists");
 
1146
                newnode->setDrawArrow(true);
 
1147
                newnode->SetData(node->GetData());
 
1148
            }
 
1149
        }
 
1150
 
812
1151
        if (!fields.contains("genres"))
813
1152
        {
814
1153
            newnode = new MusicGenericTree(node, tr("Genres"), "genres");
1070
1409
    QStringList route = m_playlistTree->GetCurrentNode()->getRouteByString();
1071
1410
 
1072
1411
    m_playlistTree->Reset();
 
1412
 
 
1413
    for (int x = 0; x < m_deleteList.count(); x++)
 
1414
        delete m_deleteList.at(x);
 
1415
    m_deleteList.clear();
 
1416
 
1073
1417
    m_rootNode->deleteAllChildren();
1074
1418
    createRootNode();
1075
1419
    m_playlistTree->AssignTree(m_rootNode);