18
18
#include "dynamicplaylistcontrols.h"
20
#include "playlistdelegates.h"
21
#include "playlistheader.h"
19
22
#include "playlistview.h"
21
#include "playlistheader.h"
22
#include "playlistdelegates.h"
23
#include "core/logging.h"
25
25
#include <QCleanlooksStyle>
26
26
#include <QPainter>
50
50
void PlaylistProxyStyle::drawControl(
51
51
ControlElement element, const QStyleOption* option, QPainter* painter,
52
52
const QWidget* widget) const {
53
if (element == CE_Header) {
54
const QStyleOptionHeader* header_option = qstyleoption_cast<const QStyleOptionHeader*>(option);
55
const QRect& rect = header_option->rect;
56
const QString& text = header_option->text;
57
const QFontMetrics& font_metrics = header_option->fontMetrics;
59
// spaces added to make transition less abrupt
60
if (rect.width() < font_metrics.width(text + " ")) {
61
const Playlist::Column column = static_cast<Playlist::Column>(header_option->section);
62
QStyleOptionHeader new_option(*header_option);
63
new_option.text = Playlist::abbreviated_column_name(column);
64
QProxyStyle::drawControl(element, &new_option, painter, widget);
53
69
if (element == CE_ItemViewItem)
54
70
cleanlooks_->drawControl(element, option, painter, widget);
69
85
: QTreeView(parent),
70
86
style_(new PlaylistProxyStyle(style())),
72
header_(new PlaylistHeader(Qt::Horizontal, this)),
88
header_(new PlaylistHeader(Qt::Horizontal, this, this)),
73
89
setting_initial_header_layout_(false),
90
upgrading_from_qheaderview_(false),
74
91
read_only_settings_(true),
75
92
glow_enabled_(true),
76
93
currently_glowing_(false),
95
112
connect(header_, SIGNAL(sectionResized(int,int,int)), SLOT(SaveGeometry()));
96
113
connect(header_, SIGNAL(sectionMoved(int,int,int)), SLOT(SaveGeometry()));
114
connect(header_, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), SLOT(SaveGeometry()));
97
115
connect(header_, SIGNAL(SectionVisibilityChanged(int,bool)), SLOT(SaveGeometry()));
98
116
connect(header_, SIGNAL(sectionResized(int,int,int)), SLOT(InvalidateCachedCurrentPixmap()));
99
117
connect(header_, SIGNAL(sectionMoved(int,int,int)), SLOT(InvalidateCachedCurrentPixmap()));
100
118
connect(header_, SIGNAL(SectionVisibilityChanged(int,bool)), SLOT(InvalidateCachedCurrentPixmap()));
101
119
connect(header_, SIGNAL(StretchEnabledChanged(bool)), SLOT(SaveSettings()));
102
connect(header_, SIGNAL(ColumnAlignmentChanged()), SLOT(SaveSettings()));
103
120
connect(header_, SIGNAL(StretchEnabledChanged(bool)), SLOT(StretchChanged(bool)));
104
121
connect(header_, SIGNAL(MouseEntered()), SLOT(RatingHoverOut()));
149
166
setItemDelegateForColumn(Playlist::Column_LastPlayed, new LastPlayedItemDelegate(this));
152
void PlaylistView::SetPlaylist(Playlist *playlist) {
169
void PlaylistView::SetPlaylist(Playlist* playlist) {
154
171
disconnect(playlist_, SIGNAL(CurrentSongChanged(Song)),
155
172
this, SLOT(MaybeAutoscroll()));
157
174
this, SLOT(DynamicModeChanged(bool)));
158
175
disconnect(playlist_, SIGNAL(destroyed()), this, SLOT(PlaylistDestroyed()));
177
disconnect(dynamic_controls_, SIGNAL(Expand()),
178
playlist_, SLOT(ExpandDynamicPlaylist()));
160
179
disconnect(dynamic_controls_, SIGNAL(Repopulate()),
161
180
playlist_, SLOT(RepopulateDynamicPlaylist()));
162
181
disconnect(dynamic_controls_, SIGNAL(TurnOff()),
175
194
connect(playlist_, SIGNAL(CurrentSongChanged(Song)), SLOT(MaybeAutoscroll()));
176
195
connect(playlist_, SIGNAL(DynamicModeChanged(bool)), SLOT(DynamicModeChanged(bool)));
177
196
connect(playlist_, SIGNAL(destroyed()), SLOT(PlaylistDestroyed()));
197
connect(dynamic_controls_, SIGNAL(Expand()), playlist_, SLOT(ExpandDynamicPlaylist()));
178
198
connect(dynamic_controls_, SIGNAL(Repopulate()), playlist_, SLOT(RepopulateDynamicPlaylist()));
179
199
connect(dynamic_controls_, SIGNAL(TurnOff()), playlist_, SLOT(TurnOffDynamicPlaylist()));
199
219
QSettings settings;
200
220
settings.beginGroup(Playlist::kSettingsGroup);
202
if (!header_->restoreState(settings.value("state").toByteArray())) {
203
header_->HideSection(Playlist::Column_Disc);
204
header_->HideSection(Playlist::Column_Year);
205
header_->HideSection(Playlist::Column_Genre);
206
header_->HideSection(Playlist::Column_BPM);
207
header_->HideSection(Playlist::Column_Bitrate);
208
header_->HideSection(Playlist::Column_Samplerate);
209
header_->HideSection(Playlist::Column_Filename);
210
header_->HideSection(Playlist::Column_Filesize);
211
header_->HideSection(Playlist::Column_Filetype);
212
header_->HideSection(Playlist::Column_DateCreated);
213
header_->HideSection(Playlist::Column_DateModified);
214
header_->HideSection(Playlist::Column_AlbumArtist);
215
header_->HideSection(Playlist::Column_Composer);
216
header_->HideSection(Playlist::Column_Rating);
217
header_->HideSection(Playlist::Column_PlayCount);
218
header_->HideSection(Playlist::Column_SkipCount);
219
header_->HideSection(Playlist::Column_LastPlayed);
222
QByteArray state(settings.value("state").toByteArray());
223
if (!header_->RestoreState(state)) {
224
// Maybe we're upgrading from a version that persisted the state with
226
if (!header_->restoreState(state)) {
227
header_->HideSection(Playlist::Column_Disc);
228
header_->HideSection(Playlist::Column_Year);
229
header_->HideSection(Playlist::Column_Genre);
230
header_->HideSection(Playlist::Column_BPM);
231
header_->HideSection(Playlist::Column_Bitrate);
232
header_->HideSection(Playlist::Column_Samplerate);
233
header_->HideSection(Playlist::Column_Filename);
234
header_->HideSection(Playlist::Column_Filesize);
235
header_->HideSection(Playlist::Column_Filetype);
236
header_->HideSection(Playlist::Column_DateCreated);
237
header_->HideSection(Playlist::Column_DateModified);
238
header_->HideSection(Playlist::Column_AlbumArtist);
239
header_->HideSection(Playlist::Column_Composer);
240
header_->HideSection(Playlist::Column_Rating);
241
header_->HideSection(Playlist::Column_PlayCount);
242
header_->HideSection(Playlist::Column_SkipCount);
243
header_->HideSection(Playlist::Column_LastPlayed);
221
header_->moveSection(header_->visualIndex(Playlist::Column_Track), 0);
222
setting_initial_header_layout_ = true;
245
header_->moveSection(header_->visualIndex(Playlist::Column_Track), 0);
246
setting_initial_header_layout_ = true;
248
upgrading_from_qheaderview_ = true;
225
252
// New columns that we add are visible by default if the user has upgraded
472
504
void PlaylistView::RemoveSelected() {
505
int rows_removed = 0;
473
506
QItemSelection selection(selectionModel()->selection());
508
if (selection.isEmpty()) {
475
512
// Sort the selection so we remove the items at the *bottom* first, ensuring
476
513
// we don't have to mess around with changing row numbers
477
514
qSort(selection.begin(), selection.end(), CompareSelectionRanges);
516
// Store the last selected row, which is the first in the list
517
int last_row = selection.first().bottom();
479
519
foreach (const QItemSelectionRange& range, selection) {
520
rows_removed += range.height();
480
521
model()->removeRows(range.top(), range.height(), range.parent());
483
// Select the new current item
484
if (currentIndex().isValid())
485
selectionModel()->select(
486
QItemSelection(currentIndex().sibling(currentIndex().row(), 0),
487
currentIndex().sibling(currentIndex().row(), model()->columnCount()-1)),
488
QItemSelectionModel::Select);
524
int new_row = last_row-rows_removed+1;
525
// Index of the first column for the row to select
526
QModelIndex new_index = model()->index(new_row, 0);
528
// Select the new current item, we want always the item after the last selected
529
if (new_index.isValid()) {
530
// Update visual selection with the entire row
531
selectionModel()->select(QItemSelection(new_index, model()->index(new_row, model()->columnCount()-1)),
532
QItemSelectionModel::Select);
533
// Update keyboard selected row, if it's not the first row
535
keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier));
537
// We're removing the last item, select the new last row
538
selectionModel()->select(QItemSelection(model()->index(model()->rowCount()-1, 0),
539
model()->index(model()->rowCount()-1, model()->columnCount()-1)),
540
QItemSelectionModel::Select);
491
544
QList<int> PlaylistView::GetEditableColumns() {
820
873
s.beginGroup(Playlist::kSettingsGroup);
821
874
glow_enabled_ = s.value("glow_effect", true).toBool();
822
header_->SetStretchEnabled(s.value("stretch", true).toBool());
875
background_enabled_ = s.value("bg_enabled", true).toBool();
877
if (setting_initial_header_layout_ || upgrading_from_qheaderview_) {
878
header_->SetStretchEnabled(s.value("stretch", true).toBool());
879
upgrading_from_qheaderview_ = false;
824
882
if (currently_glowing_ && glow_enabled_ && isVisible())
826
884
if (!glow_enabled_)
887
setProperty("background_enabled", background_enabled_);
829
889
if (setting_initial_header_layout_) {
830
890
header_->SetColumnWidth(Playlist::Column_Length, 0.06);
831
891
header_->SetColumnWidth(Playlist::Column_Track, 0.05);
832
892
setting_initial_header_layout_ = false;
835
ColumnAlignmentMap column_alignments = s.value("column_alignments").value<ColumnAlignmentMap>();
836
if (!column_alignments.isEmpty()) playlist_->set_column_alignments(column_alignments);
895
column_alignment_ = s.value("column_alignments").value<ColumnAlignmentMap>();
896
if (column_alignment_.isEmpty()) {
897
column_alignment_ = DefaultColumnAlignment();
900
emit ColumnAlignmentChanged(column_alignment_);
839
903
void PlaylistView::SaveSettings() {
844
908
s.beginGroup(Playlist::kSettingsGroup);
845
909
s.setValue("glow_effect", glow_enabled_);
846
s.setValue("stretch", header_->is_stretch_enabled());
847
s.setValue("column_alignments", QVariant::fromValue(playlist_->column_alignments()));
910
s.setValue("column_alignments", QVariant::fromValue(column_alignment_));
911
s.setValue("bg_enabled", background_enabled_);
850
914
void PlaylistView::StretchChanged(bool stretch) {
851
915
setHorizontalScrollBarPolicy(stretch ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAsNeeded);
854
919
void PlaylistView::DynamicModeChanged(bool dynamic) {
882
947
return QObject::eventFilter(object, event);
950
void PlaylistView::rowsInserted(const QModelIndex& parent, int start, int end) {
951
const bool at_end = end == model()->rowCount(parent) - 1;
953
QTreeView::rowsInserted(parent, start, end);
956
// If the rows were inserted at the end of the playlist then let's scroll
957
// the view so the user can see.
958
scrollTo(model()->index(start, 0, parent), QAbstractItemView::PositionAtTop);
962
ColumnAlignmentMap PlaylistView::DefaultColumnAlignment() {
963
ColumnAlignmentMap ret;
965
ret[Playlist::Column_Length] =
966
ret[Playlist::Column_Track] =
967
ret[Playlist::Column_Disc] =
968
ret[Playlist::Column_Year] =
969
ret[Playlist::Column_BPM] =
970
ret[Playlist::Column_Bitrate] =
971
ret[Playlist::Column_Samplerate] =
972
ret[Playlist::Column_Filesize] =
973
ret[Playlist::Column_PlayCount] =
974
ret[Playlist::Column_SkipCount] = (Qt::AlignRight | Qt::AlignVCenter);
975
ret[Playlist::Column_Score] = (Qt::AlignCenter);
980
void PlaylistView::SetColumnAlignment(int section, Qt::Alignment alignment) {
984
column_alignment_[section] = alignment;
985
emit ColumnAlignmentChanged(column_alignment_);
989
Qt::Alignment PlaylistView::column_alignment(int section) const {
990
return column_alignment_.value(section, Qt::AlignLeft | Qt::AlignVCenter);