conditionally hide some context menu actions in library view and playlist view
Song.is_stream()
This commit is contained in:
parent
246723a5a2
commit
bfb068a6d1
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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_; }
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user