conditionally hide some context menu actions in library view and playlist view

Song.is_stream()
This commit is contained in:
Paweł Bara 2011-03-20 12:43:10 +00:00
parent 246723a5a2
commit bfb068a6d1
12 changed files with 38 additions and 21 deletions

View File

@ -244,7 +244,7 @@ int Mpris1Player::GetCaps(Engine::State state) const {
if (state == Engine::Playing && !(current_item->options() & PlaylistItem::PauseDisabled)) { if (state == Engine::Playing && !(current_item->options() & PlaylistItem::PauseDisabled)) {
caps |= CAN_PAUSE; caps |= CAN_PAUSE;
} }
if (state != Engine::Empty && current_item->Metadata().filetype() != Song::Type_Stream) { if (state != Engine::Empty && !current_item->Metadata().is_stream()) {
caps |= CAN_SEEK; caps |= CAN_SEEK;
} }
} }

View File

@ -1141,9 +1141,8 @@ TagLib::String QStringToTaglibString(const QString& s) {
} }
bool Song::IsEditable() const { bool Song::IsEditable() const {
return d->valid_ && !d->filename_.isNull() && return d->valid_ && !d->filename_.isNull() && !is_stream() &&
d->filetype_ != Type_Stream && d->filetype_ != Type_Unknown && d->filetype_ != Type_Unknown && !has_cue();
!has_cue();
} }
bool Song::Save() const { bool Song::Save() const {

View File

@ -205,6 +205,7 @@ class Song {
uint ctime() const { return d->ctime_; } uint ctime() const { return d->ctime_; }
int filesize() const { return d->filesize_; } int filesize() const { return d->filesize_; }
FileType filetype() const { return d->filetype_; } FileType filetype() const { return d->filetype_; }
bool is_stream() const { return d->filetype_ == Type_Stream; }
const QString& art_automatic() const { return d->art_automatic_; } const QString& art_automatic() const { return d->art_automatic_; }
const QString& art_manual() const { return d->art_manual_; } const QString& art_manual() const { return d->art_manual_; }

View File

@ -324,7 +324,7 @@ void LibraryView::contextMenuEvent(QContextMenuEvent *e) {
// TODO: check if custom plugin actions should be enabled / visible // TODO: check if custom plugin actions should be enabled / visible
const int songs_selected = smart_playlists + smart_playlists_header + regular_elements; const int songs_selected = smart_playlists + smart_playlists_header + regular_elements;
const bool regular_elements_only = songs_selected == regular_elements; const bool regular_elements_only = songs_selected == regular_elements && regular_elements > 0;
const bool smart_playlists_only = songs_selected == smart_playlists + smart_playlists_header; const bool smart_playlists_only = songs_selected == smart_playlists + smart_playlists_header;
const bool only_smart_playlist_selected = smart_playlists == 1 && songs_selected == 1; const bool only_smart_playlist_selected = smart_playlists == 1 && songs_selected == 1;
@ -335,6 +335,7 @@ void LibraryView::contextMenuEvent(QContextMenuEvent *e) {
add_to_playlist_enqueue_->setEnabled(songs_selected); add_to_playlist_enqueue_->setEnabled(songs_selected);
// allow mixed smart playlists / regular elements selected // allow mixed smart playlists / regular elements selected
show_in_browser_->setVisible(!smart_playlists_only);
edit_tracks_->setVisible(!smart_playlists_only && regular_editable > 1); edit_tracks_->setVisible(!smart_playlists_only && regular_editable > 1);
// if neither edit_track not edit_tracks are available, we show disabled // if neither edit_track not edit_tracks are available, we show disabled
// edit_track element // edit_track element

View File

@ -1580,7 +1580,7 @@ void Playlist::InvalidateDeletedSongs() {
PlaylistItemPtr item = items_[row]; PlaylistItemPtr item = items_[row];
Song song = item->Metadata(); Song song = item->Metadata();
if(song.filetype() != Song::Type_Stream) { if(!song.is_stream()) {
bool exists = QFile::exists(song.filename()); bool exists = QFile::exists(song.filename());
if(!exists && !item->HasForegroundColor(kInvalidSongPriority)) { if(!exists && !item->HasForegroundColor(kInvalidSongPriority)) {
@ -1604,7 +1604,7 @@ bool Playlist::ApplyValidityOnCurrentSong(const QUrl& url, bool valid) {
Song current_song = current->Metadata(); Song current_song = current->Metadata();
// if validity has changed, reload the item // if validity has changed, reload the item
if(current_song.filetype() != Song::Type_Stream && if(!current_song.is_stream() &&
current_song.filename() == url.toLocalFile() && current_song.filename() == url.toLocalFile() &&
current_song.is_valid() != QFile::exists(current_song.filename())) { current_song.is_valid() != QFile::exists(current_song.filename())) {
ReloadItems(QList<int>() << current_row()); ReloadItems(QList<int>() << current_row());

View File

@ -29,7 +29,7 @@ SongPlaylistItem::SongPlaylistItem(const QString& type)
} }
SongPlaylistItem::SongPlaylistItem(const Song& song) SongPlaylistItem::SongPlaylistItem(const Song& song)
: PlaylistItem(song.filetype() == Song::Type_Stream ? "Stream" : "File"), : PlaylistItem(song.is_stream() ? "Stream" : "File"),
song_(song) song_(song)
{ {
} }

View File

@ -129,8 +129,7 @@ xrme::State Remote::state() const {
ret.can_go_next = active->next_row() != -1 || ret.can_go_next = active->next_row() != -1 ||
active->current_item_options() & PlaylistItem::ContainsMultipleTracks; active->current_item_options() & PlaylistItem::ContainsMultipleTracks;
ret.can_go_previous = active->previous_row() != -1; ret.can_go_previous = active->previous_row() != -1;
ret.can_seek = current_item && ret.can_seek = current_item && !current_item->Metadata().is_stream();
current_item->Metadata().filetype() != Song::Type_Stream;
switch (state) { switch (state) {
case Engine::Playing: ret.playback_state = xrme::State::PlaybackState_Playing; break; case Engine::Playing: ret.playback_state = xrme::State::PlaybackState_Playing; break;

View File

@ -69,7 +69,7 @@ marked in any of these ways.
composer, track, disc, bpm, year, genre, comment, is_compilation, rating, composer, track, disc, bpm, year, genre, comment, is_compilation, rating,
playcount, skipcount, lastplayed, score, cue_path, has_cue, beginning_nanosec, playcount, skipcount, lastplayed, score, cue_path, has_cue, beginning_nanosec,
end_nanosec, length_nanosec, bitrate, samplerate, directory_id, filename, end_nanosec, length_nanosec, bitrate, samplerate, directory_id, filename,
basefilename, mtime, ctime, filesize, filetype, art_automatic, art_manual, basefilename, mtime, ctime, filesize, filetype, is_stream, art_automatic, art_manual,
has_manually_unset_cover, has_embedded_cover, image, url, IsEditable, has_manually_unset_cover, has_embedded_cover, image, url, IsEditable,
IsMetadataEqual IsMetadataEqual
@group Pretty getters: PrettyTitle, PrettyTitleWithArtist, PrettyLength, @group Pretty getters: PrettyTitle, PrettyTitleWithArtist, PrettyLength,
@ -360,6 +360,12 @@ filetype() -> FileType
The type of media file. The type of media file.
@see: L{TextForFiletype} @see: L{TextForFiletype}
%End
bool is_stream() const;
%Docstring
is_stream() -> bool
True if this song represents a stream (a remote file) and false otherwise.
%End %End
QString art_automatic() const; QString art_automatic() const;

View File

@ -1100,24 +1100,32 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex&
QModelIndexList selection = ui_->playlist->view()->selectionModel()->selection().indexes(); QModelIndexList selection = ui_->playlist->view()->selectionModel()->selection().indexes();
bool cue_selected = false; bool cue_selected = false;
int editable = 0; int editable = 0;
int streams = 0;
int in_queue = 0; int in_queue = 0;
int not_in_queue = 0; int not_in_queue = 0;
foreach (const QModelIndex& index, selection) { foreach (const QModelIndex& index, selection) {
if (index.column() != 0) if (index.column() != 0)
continue; continue;
if(playlists_->current()->item_at(index.row())->Metadata().has_cue()) { PlaylistItemPtr item = playlists_->current()->item_at(index.row());
if(item->Metadata().has_cue()) {
cue_selected = true; cue_selected = true;
} else if (playlists_->current()->item_at(index.row())->Metadata().IsEditable()) { } else if (item->Metadata().IsEditable()) {
editable++; editable++;
} }
if(item->Metadata().is_stream()) {
streams++;
}
if (index.data(Playlist::Role_QueuePosition).toInt() == -1) if (index.data(Playlist::Role_QueuePosition).toInt() == -1)
not_in_queue ++; not_in_queue ++;
else else
in_queue ++; in_queue ++;
} }
int all = not_in_queue + in_queue;
// this is available when we have one or many files and at least one of // this is available when we have one or many files and at least one of
// those is not CUE related // those is not CUE related
ui_->action_edit_track->setEnabled(editable); ui_->action_edit_track->setEnabled(editable);
@ -1129,6 +1137,9 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex&
if(cue_selected) if(cue_selected)
editable = 0; editable = 0;
// no 'show in browser' action if only streams are selected
playlist_open_in_browser_->setVisible(streams != all);
bool track_column = (index.column() == Playlist::Column_Track); bool track_column = (index.column() == Playlist::Column_Track);
ui_->action_renumber_tracks->setVisible(editable >= 2 && track_column); ui_->action_renumber_tracks->setVisible(editable >= 2 && track_column);
ui_->action_selection_set_value->setVisible(editable >= 2 && !track_column); ui_->action_selection_set_value->setVisible(editable >= 2 && !track_column);

View File

@ -66,8 +66,8 @@ TEST_F(ASXParserTest, ParsesMoreThanOneTrackFromXML) {
ASSERT_EQ(2, songs.length()); ASSERT_EQ(2, songs.length());
EXPECT_EQ("http://example.com/foo.mp3", songs[0].filename()); EXPECT_EQ("http://example.com/foo.mp3", songs[0].filename());
EXPECT_EQ("http://example.com/bar.mp3", songs[1].filename()); EXPECT_EQ("http://example.com/bar.mp3", songs[1].filename());
EXPECT_EQ(Song::Type_Stream, songs[0].filetype()); EXPECT_TRUE(songs[0].is_stream());
EXPECT_EQ(Song::Type_Stream, songs[1].filetype()); EXPECT_TRUE(songs[1].is_stream());
} }
TEST_F(ASXParserTest, ParsesBrokenXmlEntities) { TEST_F(ASXParserTest, ParsesBrokenXmlEntities) {

View File

@ -66,7 +66,7 @@ TEST_F(PLSParserTest, ParseSomaFM) {
EXPECT_EQ("SomaFM: Groove Salad (#2 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[1].title()); EXPECT_EQ("SomaFM: Groove Salad (#2 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[1].title());
EXPECT_EQ("SomaFM: Groove Salad (#3 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[2].title()); EXPECT_EQ("SomaFM: Groove Salad (#3 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[2].title());
EXPECT_EQ(-1, songs[0].length_nanosec()); EXPECT_EQ(-1, songs[0].length_nanosec());
EXPECT_EQ(Song::Type_Stream, songs[0].filetype()); EXPECT_TRUE(songs[0].is_stream());
} }
TEST_F(PLSParserTest, ParseSomaFM2) { TEST_F(PLSParserTest, ParseSomaFM2) {
@ -82,7 +82,7 @@ TEST_F(PLSParserTest, ParseSomaFM2) {
EXPECT_EQ("SomaFM: Secret Agent (#2 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[1].title()); EXPECT_EQ("SomaFM: Secret Agent (#2 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[1].title());
EXPECT_EQ("SomaFM: Secret Agent (#3 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[2].title()); EXPECT_EQ("SomaFM: Secret Agent (#3 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[2].title());
EXPECT_EQ(-1, songs[0].length_nanosec()); EXPECT_EQ(-1, songs[0].length_nanosec());
EXPECT_EQ(Song::Type_Stream, songs[0].filetype()); EXPECT_TRUE(songs[0].is_stream());
} }
TEST_F(PLSParserTest, SaveAndLoad) { TEST_F(PLSParserTest, SaveAndLoad) {

View File

@ -71,8 +71,8 @@ TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) {
ASSERT_EQ(2, songs.length()); ASSERT_EQ(2, songs.length());
EXPECT_EQ("http://example.com/foo.mp3", songs[0].filename()); EXPECT_EQ("http://example.com/foo.mp3", songs[0].filename());
EXPECT_EQ("http://example.com/bar.mp3", songs[1].filename()); EXPECT_EQ("http://example.com/bar.mp3", songs[1].filename());
EXPECT_EQ(Song::Type_Stream, songs[0].filetype()); EXPECT_TRUE(songs[0].is_stream());
EXPECT_EQ(Song::Type_Stream, songs[1].filetype()); EXPECT_TRUE(songs[1].is_stream());
} }
TEST_F(XSPFParserTest, IgnoresInvalidLength) { TEST_F(XSPFParserTest, IgnoresInvalidLength) {