2018-02-27 18:06:05 +01:00
|
|
|
/*
|
|
|
|
* Strawberry Music Player
|
|
|
|
* This file was part of Clementine.
|
|
|
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
2021-03-20 21:14:47 +01:00
|
|
|
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
2018-02-27 18:06:05 +01:00
|
|
|
*
|
|
|
|
* Strawberry is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Strawberry is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
2018-08-09 18:10:03 +02:00
|
|
|
*
|
2018-02-27 18:06:05 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PLAYLISTVIEW_H
|
|
|
|
#define PLAYLISTVIEW_H
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <memory>
|
2018-05-01 00:41:33 +02:00
|
|
|
|
|
|
|
#include <QtGlobal>
|
|
|
|
#include <QObject>
|
2020-02-08 15:03:11 +01:00
|
|
|
#include <QAbstractItemDelegate>
|
|
|
|
#include <QAbstractItemModel>
|
|
|
|
#include <QStyleOptionViewItem>
|
|
|
|
#include <QAbstractItemView>
|
|
|
|
#include <QTreeView>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QList>
|
2020-02-08 15:03:11 +01:00
|
|
|
#include <QByteArray>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QString>
|
|
|
|
#include <QImage>
|
|
|
|
#include <QPixmap>
|
2021-04-01 02:17:30 +02:00
|
|
|
#include <QColor>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QRect>
|
|
|
|
#include <QRegion>
|
|
|
|
#include <QStyleOption>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QProxyStyle>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QPoint>
|
|
|
|
#include <QBasicTimer>
|
|
|
|
#include <QCommonStyle>
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-07-30 21:32:56 +02:00
|
|
|
#include "core/song.h"
|
2020-04-20 18:03:18 +02:00
|
|
|
#include "covermanager/albumcoverloaderresult.h"
|
2019-03-25 22:00:40 +01:00
|
|
|
#include "settings/appearancesettingspage.h"
|
2018-02-27 18:06:05 +01:00
|
|
|
#include "playlist.h"
|
|
|
|
|
2020-02-08 15:03:11 +01:00
|
|
|
class QWidget;
|
|
|
|
class QTimer;
|
|
|
|
class QTimeLine;
|
|
|
|
class QPainter;
|
2018-05-01 00:41:33 +02:00
|
|
|
class QEvent;
|
|
|
|
class QShowEvent;
|
|
|
|
class QContextMenuEvent;
|
|
|
|
class QDragEnterEvent;
|
|
|
|
class QDragLeaveEvent;
|
|
|
|
class QDragMoveEvent;
|
|
|
|
class QDropEvent;
|
|
|
|
class QFocusEvent;
|
|
|
|
class QHideEvent;
|
|
|
|
class QKeyEvent;
|
|
|
|
class QMouseEvent;
|
|
|
|
class QPaintEvent;
|
|
|
|
class QTimerEvent;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
class Application;
|
|
|
|
class CollectionBackend;
|
|
|
|
class PlaylistHeader;
|
2020-09-17 17:50:17 +02:00
|
|
|
class DynamicPlaylistControls;
|
|
|
|
class RatingItemDelegate;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// This proxy style works around a bug/feature introduced in Qt 4.7's QGtkStyle
|
2018-05-01 00:41:33 +02:00
|
|
|
// that uses Gtk to paint row backgrounds, ignoring any custom brush or palette the caller set in the QStyleOption.
|
|
|
|
// That breaks our currently playing track animation, which relies on the background painted by Qt to be transparent.
|
2018-02-27 18:06:05 +01:00
|
|
|
// This proxy style uses QCommonStyle to paint the affected elements.
|
2019-03-09 17:43:20 +01:00
|
|
|
// This class is used by internet search view as well.
|
2018-02-27 18:06:05 +01:00
|
|
|
class PlaylistProxyStyle : public QProxyStyle {
|
2021-06-20 19:04:08 +02:00
|
|
|
Q_OBJECT
|
|
|
|
|
2020-01-28 19:41:46 +01:00
|
|
|
public:
|
2021-06-20 19:04:08 +02:00
|
|
|
explicit PlaylistProxyStyle(QObject *parent = nullptr);
|
2019-07-24 19:16:51 +02:00
|
|
|
|
2020-06-15 21:55:05 +02:00
|
|
|
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override;
|
|
|
|
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::unique_ptr<QCommonStyle> common_style_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class PlaylistView : public QTreeView {
|
|
|
|
Q_OBJECT
|
|
|
|
|
2020-06-15 21:55:05 +02:00
|
|
|
public:
|
2020-04-07 16:49:15 +02:00
|
|
|
explicit PlaylistView(QWidget *parent = nullptr);
|
2020-06-15 21:55:05 +02:00
|
|
|
~PlaylistView() override;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
static ColumnAlignmentMap DefaultColumnAlignment();
|
|
|
|
|
2020-08-29 19:55:00 +02:00
|
|
|
void Init(Application *app);
|
2020-07-10 16:18:31 +02:00
|
|
|
void SetItemDelegates();
|
2018-02-27 18:06:05 +01:00
|
|
|
void SetPlaylist(Playlist *playlist);
|
2020-07-08 20:43:46 +02:00
|
|
|
void RemoveSelected();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2021-06-20 23:53:28 +02:00
|
|
|
void SetReadOnlySettings(const bool read_only) { read_only_settings_ = read_only; }
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
Playlist *playlist() const { return playlist_; }
|
2019-03-25 22:00:40 +01:00
|
|
|
AppearanceSettingsPage::BackgroundImageType background_image_type() const { return background_image_type_; }
|
2018-02-27 18:06:05 +01:00
|
|
|
Qt::Alignment column_alignment(int section) const;
|
|
|
|
|
2020-08-29 19:55:00 +02:00
|
|
|
void ResetHeaderState();
|
2018-11-19 00:18:48 +01:00
|
|
|
|
2020-06-15 21:55:05 +02:00
|
|
|
// QTreeView
|
|
|
|
void setModel(QAbstractItemModel *model) override;
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
public slots:
|
|
|
|
void ReloadSettings();
|
2019-04-27 22:32:39 +02:00
|
|
|
void SaveSettings();
|
2020-08-23 19:17:50 +02:00
|
|
|
void SetColumnAlignment(const int section, const Qt::Alignment alignment);
|
2019-07-30 21:32:56 +02:00
|
|
|
void JumpToCurrentlyPlayingTrack();
|
2021-06-20 19:04:08 +02:00
|
|
|
void edit(const QModelIndex &idx) { QAbstractItemView::edit(idx); }
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
signals:
|
2020-08-23 19:37:24 +02:00
|
|
|
void PlayItem(QModelIndex idx, Playlist::AutoScroll autoscroll);
|
2021-06-10 23:13:03 +02:00
|
|
|
void PlayPause(const quint64 offset_nanosec = 0, Playlist::AutoScroll autoscroll = Playlist::AutoScroll_Never);
|
2020-08-23 19:17:50 +02:00
|
|
|
void RightClicked(QPoint global_pos, QModelIndex idx);
|
2018-02-27 18:06:05 +01:00
|
|
|
void SeekForward();
|
|
|
|
void SeekBackward();
|
|
|
|
void FocusOnFilterSignal(QKeyEvent *event);
|
|
|
|
void BackgroundPropertyChanged();
|
2020-08-23 19:17:50 +02:00
|
|
|
void ColumnAlignmentChanged(ColumnAlignmentMap alignment);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// QWidget
|
2020-06-15 21:55:05 +02:00
|
|
|
void keyPressEvent(QKeyEvent *event) override;
|
|
|
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
|
|
|
void hideEvent(QHideEvent *event) override;
|
|
|
|
void showEvent(QShowEvent *event) override;
|
|
|
|
void timerEvent(QTimerEvent *event) override;
|
|
|
|
void mouseMoveEvent(QMouseEvent *event) override;
|
|
|
|
void mousePressEvent(QMouseEvent *event) override;
|
|
|
|
void leaveEvent(QEvent*) override;
|
|
|
|
void paintEvent(QPaintEvent *event) override;
|
|
|
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
|
|
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
|
|
|
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
|
|
|
void dropEvent(QDropEvent *event) override;
|
|
|
|
bool eventFilter(QObject *object, QEvent *event) override;
|
|
|
|
void focusInEvent(QFocusEvent *event) override;
|
2020-09-17 17:50:17 +02:00
|
|
|
void resizeEvent(QResizeEvent *event) override;
|
2020-06-15 21:55:05 +02:00
|
|
|
|
|
|
|
// QTreeView
|
|
|
|
void drawTree(QPainter *painter, const QRegion ®ion) const;
|
2020-08-23 19:17:50 +02:00
|
|
|
void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const override;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// QAbstractScrollArea
|
2020-06-15 21:55:05 +02:00
|
|
|
void scrollContentsBy(int dx, int dy) override;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// QAbstractItemView
|
2020-06-15 21:55:05 +02:00
|
|
|
void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
2020-08-23 19:17:50 +02:00
|
|
|
bool edit(const QModelIndex &idx, QAbstractItemView::EditTrigger trigger, QEvent *event) override;
|
2020-06-15 21:55:05 +02:00
|
|
|
void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint) override;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
private slots:
|
2021-01-26 16:48:04 +01:00
|
|
|
void Update() { update(); }
|
2020-08-29 19:55:00 +02:00
|
|
|
void SetHeaderState();
|
2018-02-27 18:06:05 +01:00
|
|
|
void InhibitAutoscrollTimeout();
|
2020-08-23 19:37:24 +02:00
|
|
|
void MaybeAutoscroll(const Playlist::AutoScroll autoscroll);
|
2018-02-27 18:06:05 +01:00
|
|
|
void InvalidateCachedCurrentPixmap();
|
|
|
|
void PlaylistDestroyed();
|
2020-08-23 19:17:50 +02:00
|
|
|
void StretchChanged(const bool stretch);
|
|
|
|
void FadePreviousBackgroundImage(const qreal value);
|
2019-07-30 21:32:56 +02:00
|
|
|
void StopGlowing();
|
|
|
|
void StartGlowing();
|
|
|
|
void JumpToLastPlayedTrack();
|
|
|
|
void CopyCurrentSongToClipboard() const;
|
|
|
|
void Playing();
|
|
|
|
void Stopped();
|
|
|
|
void SongChanged(const Song &song);
|
2021-06-20 19:04:08 +02:00
|
|
|
void AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &result = AlbumCoverLoaderResult());
|
2020-09-17 17:50:17 +02:00
|
|
|
void DynamicModeChanged(const bool dynamic);
|
|
|
|
void SetRatingLockStatus(const bool state);
|
2021-06-20 19:04:08 +02:00
|
|
|
void RatingHoverIn(const QModelIndex &idx, const QPoint pos);
|
2020-09-17 17:50:17 +02:00
|
|
|
void RatingHoverOut();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
private:
|
2020-08-29 19:55:00 +02:00
|
|
|
void LoadHeaderState();
|
|
|
|
void RestoreHeaderState();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
void ReloadBarPixmaps();
|
|
|
|
QList<QPixmap> LoadBarPixmap(const QString &filename);
|
2020-08-23 19:17:50 +02:00
|
|
|
void UpdateCachedCurrentRowPixmap(QStyleOptionViewItem option, const QModelIndex &idx);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-03-25 22:00:40 +01:00
|
|
|
void set_background_image_type(AppearanceSettingsPage::BackgroundImageType bg) {
|
2018-02-27 18:06:05 +01:00
|
|
|
background_image_type_ = bg;
|
2021-06-20 19:04:08 +02:00
|
|
|
emit BackgroundPropertyChanged(); // clazy:exclude=incorrect-emit
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
2018-05-01 00:41:33 +02:00
|
|
|
// Save image as the background_image_ after applying some modifications (opacity, ...).
|
2018-02-27 18:06:05 +01:00
|
|
|
// Should be used instead of modifying background_image_ directly
|
|
|
|
void set_background_image(const QImage &image);
|
|
|
|
|
2019-07-30 21:32:56 +02:00
|
|
|
void GlowIntensityChanged();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
private:
|
|
|
|
static const int kGlowIntensitySteps;
|
|
|
|
static const int kAutoscrollGraceTimeout;
|
|
|
|
static const int kDropIndicatorWidth;
|
|
|
|
static const int kDropIndicatorGradientWidth;
|
|
|
|
|
|
|
|
QList<int> GetEditableColumns();
|
|
|
|
QModelIndex NextEditableIndex(const QModelIndex ¤t);
|
|
|
|
QModelIndex PrevEditableIndex(const QModelIndex ¤t);
|
|
|
|
|
2020-09-17 17:50:17 +02:00
|
|
|
void RepositionDynamicControls();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
Application *app_;
|
|
|
|
PlaylistProxyStyle *style_;
|
|
|
|
Playlist *playlist_;
|
|
|
|
PlaylistHeader *header_;
|
2019-03-25 22:00:40 +01:00
|
|
|
|
2020-11-10 21:55:00 +01:00
|
|
|
qreal device_pixel_ratio_;
|
2019-03-25 22:00:40 +01:00
|
|
|
AppearanceSettingsPage::BackgroundImageType background_image_type_;
|
|
|
|
QString background_image_filename_;
|
|
|
|
AppearanceSettingsPage::BackgroundImagePosition background_image_position_;
|
|
|
|
int background_image_maxsize_;
|
|
|
|
bool background_image_stretch_;
|
2019-06-30 19:37:05 +02:00
|
|
|
bool background_image_do_not_cut_;
|
2019-03-25 22:00:40 +01:00
|
|
|
bool background_image_keep_aspect_ratio_;
|
|
|
|
int blur_radius_;
|
|
|
|
int opacity_level_;
|
|
|
|
|
|
|
|
bool background_initialized_;
|
2020-08-29 19:55:00 +02:00
|
|
|
bool set_initial_header_layout_;
|
|
|
|
bool header_state_loaded_;
|
|
|
|
bool header_state_restored_;
|
2021-06-20 23:53:28 +02:00
|
|
|
bool read_only_settings_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
QImage background_image_;
|
|
|
|
QImage current_song_cover_art_;
|
|
|
|
QPixmap cached_scaled_background_image_;
|
|
|
|
|
|
|
|
// For fading when image change
|
|
|
|
QPixmap previous_background_image_;
|
|
|
|
qreal previous_background_image_opacity_;
|
|
|
|
QTimeLine *fade_animation_;
|
|
|
|
|
|
|
|
// To know if we should redraw the background or not
|
2019-03-25 22:00:40 +01:00
|
|
|
bool force_background_redraw_;
|
2018-02-27 18:06:05 +01:00
|
|
|
int last_height_;
|
|
|
|
int last_width_;
|
2019-03-25 22:00:40 +01:00
|
|
|
int current_background_image_x_;
|
|
|
|
int current_background_image_y_;
|
|
|
|
int previous_background_image_x_;
|
|
|
|
int previous_background_image_y_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
bool glow_enabled_;
|
2019-10-27 02:11:51 +01:00
|
|
|
bool select_track_;
|
2020-10-01 19:58:16 +02:00
|
|
|
bool auto_sort_;
|
2019-10-27 02:11:51 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
bool currently_glowing_;
|
|
|
|
QBasicTimer glow_timer_;
|
|
|
|
int glow_intensity_step_;
|
|
|
|
QModelIndex last_current_item_;
|
|
|
|
QRect last_glow_rect_;
|
|
|
|
|
|
|
|
QTimer *inhibit_autoscroll_timer_;
|
|
|
|
bool inhibit_autoscroll_;
|
|
|
|
bool currently_autoscrolling_;
|
|
|
|
|
|
|
|
int row_height_; // Used to invalidate the currenttrack_bar pixmaps
|
|
|
|
QList<QPixmap> currenttrack_bar_left_;
|
|
|
|
QList<QPixmap> currenttrack_bar_mid_;
|
|
|
|
QList<QPixmap> currenttrack_bar_right_;
|
|
|
|
QPixmap currenttrack_play_;
|
|
|
|
QPixmap currenttrack_pause_;
|
|
|
|
|
|
|
|
QRegion current_paint_region_;
|
|
|
|
QPixmap cached_current_row_;
|
|
|
|
QRect cached_current_row_rect_;
|
|
|
|
int cached_current_row_row_;
|
|
|
|
|
|
|
|
QPixmap cached_tree_;
|
|
|
|
int drop_indicator_row_;
|
|
|
|
bool drag_over_;
|
|
|
|
|
2020-09-17 17:50:17 +02:00
|
|
|
int header_state_version_;
|
2020-08-29 19:55:00 +02:00
|
|
|
QByteArray header_state_;
|
2018-02-27 18:06:05 +01:00
|
|
|
ColumnAlignmentMap column_alignment_;
|
2020-09-17 17:50:17 +02:00
|
|
|
bool rating_locked_;
|
2019-04-28 14:14:19 +02:00
|
|
|
|
2019-07-30 21:32:56 +02:00
|
|
|
Song song_playing_;
|
|
|
|
|
2020-09-17 17:50:17 +02:00
|
|
|
DynamicPlaylistControls *dynamic_controls_;
|
|
|
|
RatingItemDelegate *rating_delegate_;
|
|
|
|
|
2021-04-01 02:17:30 +02:00
|
|
|
QColor playlist_playing_song_color_;
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // PLAYLISTVIEW_H
|