2010-05-20 16:12:15 +02:00
|
|
|
/* This file is part of Clementine.
|
2010-11-20 14:27:10 +01:00
|
|
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
2010-05-20 16:12:15 +02:00
|
|
|
|
|
|
|
Clementine 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.
|
|
|
|
|
|
|
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "playlistcontainer.h"
|
|
|
|
|
2018-03-17 07:16:49 +01:00
|
|
|
#include <QAction>
|
2011-04-29 13:24:58 +02:00
|
|
|
#include <QFileDialog>
|
2010-05-20 23:21:55 +02:00
|
|
|
#include <QInputDialog>
|
2012-06-27 17:08:51 +02:00
|
|
|
#include <QKeyEvent>
|
2010-05-22 19:03:18 +02:00
|
|
|
#include <QLabel>
|
2010-05-22 22:28:11 +02:00
|
|
|
#include <QMessageBox>
|
2011-04-29 13:24:58 +02:00
|
|
|
#include <QSettings>
|
|
|
|
#include <QSortFilterProxyModel>
|
|
|
|
#include <QTimeLine>
|
2012-09-09 00:35:50 +02:00
|
|
|
#include <QTimer>
|
2011-04-29 13:24:58 +02:00
|
|
|
#include <QUndoStack>
|
2010-05-21 01:18:55 +02:00
|
|
|
|
2020-09-18 16:15:19 +02:00
|
|
|
#include "core/appearance.h"
|
|
|
|
#include "core/application.h"
|
|
|
|
#include "core/logging.h"
|
|
|
|
#include "core/player.h"
|
|
|
|
#include "core/timeconstants.h"
|
|
|
|
#include "playlistmanager.h"
|
|
|
|
#include "playlistparsers/playlistparser.h"
|
|
|
|
#include "ui/iconloader.h"
|
|
|
|
#include "ui_playlistcontainer.h"
|
|
|
|
|
2010-05-21 01:18:55 +02:00
|
|
|
const char* PlaylistContainer::kSettingsGroup = "Playlist";
|
2012-09-09 00:35:50 +02:00
|
|
|
const int PlaylistContainer::kFilterDelayMs = 100;
|
|
|
|
const int PlaylistContainer::kFilterDelayPlaylistSizeThreshold = 5000;
|
2010-05-20 23:21:55 +02:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
PlaylistContainer::PlaylistContainer(QWidget* parent)
|
|
|
|
: QWidget(parent),
|
2019-09-07 04:29:19 +02:00
|
|
|
app_(nullptr),
|
2014-02-07 16:34:20 +01:00
|
|
|
ui_(new Ui_PlaylistContainer),
|
|
|
|
manager_(nullptr),
|
|
|
|
undo_(nullptr),
|
|
|
|
redo_(nullptr),
|
|
|
|
playlist_(nullptr),
|
|
|
|
starting_up_(true),
|
|
|
|
tab_bar_visible_(false),
|
|
|
|
tab_bar_animation_(new QTimeLine(500, this)),
|
|
|
|
no_matches_label_(nullptr),
|
2019-09-07 04:29:19 +02:00
|
|
|
filter_timer_(new QTimer(this)),
|
|
|
|
dirty_(false) {
|
2010-05-20 16:12:15 +02:00
|
|
|
ui_->setupUi(this);
|
|
|
|
|
2011-04-29 13:24:58 +02:00
|
|
|
no_matches_label_ = new QLabel(ui_->playlist);
|
2010-05-22 19:03:18 +02:00
|
|
|
no_matches_label_->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
|
|
|
|
no_matches_label_->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
|
|
no_matches_label_->setWordWrap(true);
|
|
|
|
no_matches_label_->raise();
|
|
|
|
no_matches_label_->hide();
|
|
|
|
|
|
|
|
// Set the colour of the no matches label to the disabled text colour
|
|
|
|
QPalette no_matches_palette = no_matches_label_->palette();
|
2014-02-07 16:34:20 +01:00
|
|
|
const QColor no_matches_color =
|
|
|
|
no_matches_palette.color(QPalette::Disabled, QPalette::Text);
|
|
|
|
no_matches_palette.setColor(QPalette::Normal, QPalette::WindowText,
|
|
|
|
no_matches_color);
|
|
|
|
no_matches_palette.setColor(QPalette::Inactive, QPalette::WindowText,
|
|
|
|
no_matches_color);
|
2010-05-22 19:03:18 +02:00
|
|
|
no_matches_label_->setPalette(no_matches_palette);
|
2017-05-30 19:19:08 +02:00
|
|
|
|
2016-01-16 13:28:18 +01:00
|
|
|
// Remove QFrame border
|
|
|
|
ui_->toolbar->setStyleSheet("QFrame { border: 0px; }");
|
2017-05-30 19:19:08 +02:00
|
|
|
|
2018-01-03 16:24:56 +01:00
|
|
|
QSettings settings;
|
|
|
|
settings.beginGroup(Appearance::kSettingsGroup);
|
|
|
|
bool hide_toolbar = settings.value("b_hide_filter_toolbar", false).toBool();
|
|
|
|
ui_->toolbar->setVisible(!hide_toolbar);
|
|
|
|
|
2010-05-22 19:03:18 +02:00
|
|
|
// Make it bold
|
|
|
|
QFont no_matches_font = no_matches_label_->font();
|
|
|
|
no_matches_font.setBold(true);
|
|
|
|
no_matches_label_->setFont(no_matches_font);
|
|
|
|
|
2010-05-21 01:18:55 +02:00
|
|
|
settings_.beginGroup(kSettingsGroup);
|
|
|
|
|
2010-05-20 16:12:15 +02:00
|
|
|
// Tab bar
|
|
|
|
ui_->tab_bar->setExpanding(false);
|
|
|
|
ui_->tab_bar->setMovable(true);
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(tab_bar_animation_, SIGNAL(frameChanged(int)),
|
|
|
|
SLOT(SetTabBarHeight(int)));
|
2010-10-01 21:27:01 +02:00
|
|
|
ui_->tab_bar->setMaximumHeight(0);
|
2010-05-21 12:57:40 +02:00
|
|
|
|
2010-05-20 16:12:15 +02:00
|
|
|
// Connections
|
2019-09-07 04:29:19 +02:00
|
|
|
connect(ui_->tab_bar, SIGNAL(currentChanged(int)), SLOT(DirtyTabBar()));
|
2010-05-23 00:20:00 +02:00
|
|
|
connect(ui_->tab_bar, SIGNAL(Save(int)), SLOT(SavePlaylist(int)));
|
2010-08-25 22:59:08 +02:00
|
|
|
|
2012-09-09 00:35:50 +02:00
|
|
|
// set up timer for delayed filter updates
|
|
|
|
filter_timer_->setSingleShot(true);
|
|
|
|
filter_timer_->setInterval(kFilterDelayMs);
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(filter_timer_, SIGNAL(timeout()), this, SLOT(UpdateFilter()));
|
2012-09-09 00:35:50 +02:00
|
|
|
|
2010-08-25 22:59:08 +02:00
|
|
|
// Replace playlist search filter with native search box.
|
2012-09-09 00:35:50 +02:00
|
|
|
connect(ui_->filter, SIGNAL(textChanged(QString)), SLOT(MaybeUpdateFilter()));
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(ui_->playlist, SIGNAL(FocusOnFilterSignal(QKeyEvent*)),
|
|
|
|
SLOT(FocusOnFilter(QKeyEvent*)));
|
2011-02-23 23:21:17 +01:00
|
|
|
ui_->filter->installEventFilter(this);
|
2010-05-20 16:12:15 +02:00
|
|
|
}
|
|
|
|
|
2020-09-18 16:15:19 +02:00
|
|
|
PlaylistContainer::~PlaylistContainer() { delete ui_; }
|
2010-05-20 16:12:15 +02:00
|
|
|
|
2019-09-07 04:29:19 +02:00
|
|
|
void PlaylistContainer::SetApplication(Application* app) {
|
|
|
|
Q_ASSERT(app);
|
|
|
|
app_ = app;
|
|
|
|
SetManager(app_->playlist_manager());
|
|
|
|
ui_->playlist->SetApplication(app_);
|
2020-07-09 09:10:00 +02:00
|
|
|
// This should not be called before SetApplication.
|
2020-07-11 21:51:32 +02:00
|
|
|
view()->SetItemDelegates(app->library_backend());
|
2019-09-07 04:29:19 +02:00
|
|
|
connect(app_, SIGNAL(SaveSettings(QSettings*)), SLOT(Save(QSettings*)));
|
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
PlaylistView* PlaylistContainer::view() const { return ui_->playlist; }
|
2010-05-20 16:12:15 +02:00
|
|
|
|
2012-10-31 07:04:22 +01:00
|
|
|
void PlaylistContainer::SetActions(QAction* new_playlist,
|
|
|
|
QAction* load_playlist,
|
|
|
|
QAction* save_playlist,
|
|
|
|
QAction* next_playlist,
|
|
|
|
QAction* previous_playlist) {
|
2013-05-11 23:17:54 +02:00
|
|
|
ui_->create_new->setDefaultAction(new_playlist);
|
|
|
|
ui_->save->setDefaultAction(save_playlist);
|
|
|
|
ui_->load->setDefaultAction(load_playlist);
|
|
|
|
|
2010-05-23 00:20:00 +02:00
|
|
|
ui_->tab_bar->SetActions(new_playlist, load_playlist);
|
2010-05-20 23:21:55 +02:00
|
|
|
|
2010-05-21 01:18:55 +02:00
|
|
|
connect(new_playlist, SIGNAL(triggered()), SLOT(NewPlaylist()));
|
|
|
|
connect(save_playlist, SIGNAL(triggered()), SLOT(SavePlaylist()));
|
|
|
|
connect(load_playlist, SIGNAL(triggered()), SLOT(LoadPlaylist()));
|
2011-04-19 22:11:24 +02:00
|
|
|
connect(next_playlist, SIGNAL(triggered()), SLOT(GoToNextPlaylistTab()));
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(previous_playlist, SIGNAL(triggered()),
|
|
|
|
SLOT(GoToPreviousPlaylistTab()));
|
2010-05-20 16:12:15 +02:00
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void PlaylistContainer::SetManager(PlaylistManager* manager) {
|
2010-05-20 23:21:55 +02:00
|
|
|
manager_ = manager;
|
2010-07-17 14:47:59 +02:00
|
|
|
ui_->tab_bar->SetManager(manager);
|
2010-05-20 23:21:55 +02:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(ui_->tab_bar, SIGNAL(CurrentIdChanged(int)), manager,
|
|
|
|
SLOT(SetCurrentPlaylist(int)));
|
|
|
|
connect(ui_->tab_bar, SIGNAL(Rename(int, QString)), manager,
|
|
|
|
SLOT(Rename(int, QString)));
|
|
|
|
connect(ui_->tab_bar, SIGNAL(Close(int)), manager, SLOT(Close(int)));
|
|
|
|
connect(ui_->tab_bar, SIGNAL(PlaylistFavorited(int, bool)), manager,
|
|
|
|
SLOT(Favorite(int, bool)));
|
2013-05-11 23:17:54 +02:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(ui_->tab_bar, SIGNAL(PlaylistOrderChanged(QList<int>)), manager,
|
|
|
|
SLOT(ChangePlaylistOrder(QList<int>)));
|
2010-05-20 23:21:55 +02:00
|
|
|
|
|
|
|
connect(manager, SIGNAL(CurrentChanged(Playlist*)),
|
|
|
|
SLOT(SetViewModel(Playlist*)));
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(manager, SIGNAL(PlaylistAdded(int, QString, bool)),
|
|
|
|
SLOT(PlaylistAdded(int, QString, bool)));
|
2015-03-25 22:13:39 +01:00
|
|
|
connect(manager, SIGNAL(PlaylistManagerInitialized()), SLOT(Started()));
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(manager, SIGNAL(PlaylistClosed(int)), SLOT(PlaylistClosed(int)));
|
|
|
|
connect(manager, SIGNAL(PlaylistRenamed(int, QString)),
|
|
|
|
SLOT(PlaylistRenamed(int, QString)));
|
2010-05-20 23:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlaylistContainer::SetViewModel(Playlist* playlist) {
|
2010-06-13 14:45:05 +02:00
|
|
|
if (view()->selectionModel()) {
|
2014-02-07 16:34:20 +01:00
|
|
|
disconnect(view()->selectionModel(),
|
|
|
|
SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
|
|
|
|
SLOT(SelectionChanged()));
|
2010-06-13 14:45:05 +02:00
|
|
|
}
|
2011-04-29 13:24:58 +02:00
|
|
|
if (playlist_ && playlist_->proxy()) {
|
2014-02-07 16:34:20 +01:00
|
|
|
disconnect(playlist_->proxy(), SIGNAL(modelReset()), this,
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
|
|
|
disconnect(playlist_->proxy(), SIGNAL(rowsInserted(QModelIndex, int, int)),
|
2011-04-29 13:24:58 +02:00
|
|
|
this, SLOT(UpdateNoMatchesLabel()));
|
2014-02-07 16:34:20 +01:00
|
|
|
disconnect(playlist_->proxy(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
|
2011-04-29 13:24:58 +02:00
|
|
|
this, SLOT(UpdateNoMatchesLabel()));
|
|
|
|
}
|
|
|
|
if (playlist_) {
|
2014-02-07 16:34:20 +01:00
|
|
|
disconnect(playlist_, SIGNAL(modelReset()), this,
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
|
|
|
disconnect(playlist_, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
|
|
|
disconnect(playlist_, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
2011-04-29 13:24:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
playlist_ = playlist;
|
2010-06-13 14:45:05 +02:00
|
|
|
|
2010-05-21 01:18:55 +02:00
|
|
|
// Set the view
|
2010-05-20 23:21:55 +02:00
|
|
|
playlist->IgnoreSorting(true);
|
2010-05-22 18:36:13 +02:00
|
|
|
view()->setModel(playlist->proxy());
|
|
|
|
view()->SetPlaylist(playlist);
|
2014-02-07 16:34:20 +01:00
|
|
|
view()->selectionModel()->select(manager_->current_selection(),
|
|
|
|
QItemSelectionModel::ClearAndSelect);
|
2010-05-20 23:21:55 +02:00
|
|
|
playlist->IgnoreSorting(false);
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(view()->selectionModel(),
|
|
|
|
SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
|
|
|
|
SLOT(SelectionChanged()));
|
2010-11-28 16:14:48 +01:00
|
|
|
emit ViewSelectionModelChanged();
|
2010-06-13 14:45:05 +02:00
|
|
|
|
2010-05-22 18:36:13 +02:00
|
|
|
// Update filter
|
2012-06-27 17:08:51 +02:00
|
|
|
ui_->filter->setText(playlist->proxy()->filterRegExp().pattern());
|
2010-05-22 18:36:13 +02:00
|
|
|
|
2011-04-29 13:24:58 +02:00
|
|
|
// Update the no matches label
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(playlist_->proxy(), SIGNAL(modelReset()),
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
|
|
|
connect(playlist_->proxy(), SIGNAL(rowsInserted(QModelIndex, int, int)),
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
|
|
|
connect(playlist_->proxy(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
2011-04-29 13:24:58 +02:00
|
|
|
connect(playlist_, SIGNAL(modelReset()), SLOT(UpdateNoMatchesLabel()));
|
2014-02-07 16:34:20 +01:00
|
|
|
connect(playlist_, SIGNAL(rowsInserted(QModelIndex, int, int)),
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
|
|
|
connect(playlist_, SIGNAL(rowsRemoved(QModelIndex, int, int)),
|
|
|
|
SLOT(UpdateNoMatchesLabel()));
|
2011-04-29 13:24:58 +02:00
|
|
|
UpdateNoMatchesLabel();
|
|
|
|
|
2010-05-21 11:41:57 +02:00
|
|
|
// Ensure that tab is current
|
2010-05-21 12:29:17 +02:00
|
|
|
if (ui_->tab_bar->current_id() != manager_->current_id())
|
|
|
|
ui_->tab_bar->set_current_id(manager_->current_id());
|
2010-05-21 11:41:57 +02:00
|
|
|
|
2010-05-21 01:18:55 +02:00
|
|
|
// Sort out the undo/redo actions
|
2010-05-20 23:21:55 +02:00
|
|
|
delete undo_;
|
|
|
|
delete redo_;
|
|
|
|
undo_ = playlist->undo_stack()->createUndoAction(this);
|
|
|
|
redo_ = playlist->undo_stack()->createRedoAction(this);
|
2015-10-14 03:01:08 +02:00
|
|
|
undo_->setIcon(IconLoader::Load("edit-undo", IconLoader::Base));
|
2010-05-20 23:21:55 +02:00
|
|
|
undo_->setShortcut(QKeySequence::Undo);
|
2015-10-14 03:01:08 +02:00
|
|
|
redo_->setIcon(IconLoader::Load("edit-redo", IconLoader::Base));
|
2010-05-20 23:21:55 +02:00
|
|
|
redo_->setShortcut(QKeySequence::Redo);
|
|
|
|
|
|
|
|
ui_->undo->setDefaultAction(undo_);
|
|
|
|
ui_->redo->setDefaultAction(redo_);
|
|
|
|
|
|
|
|
emit UndoRedoActionsChanged(undo_, redo_);
|
|
|
|
}
|
|
|
|
|
2010-05-21 00:48:11 +02:00
|
|
|
void PlaylistContainer::ActivePlaying() {
|
2016-01-14 10:40:26 +01:00
|
|
|
UpdateActiveIcon(IconLoader::Load("tiny-start", IconLoader::Other));
|
2010-05-21 00:48:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlaylistContainer::ActivePaused() {
|
2016-01-14 10:40:26 +01:00
|
|
|
UpdateActiveIcon(IconLoader::Load("tiny-pause", IconLoader::Other));
|
2010-05-21 00:48:11 +02:00
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void PlaylistContainer::ActiveStopped() { UpdateActiveIcon(QIcon()); }
|
2010-05-21 00:48:11 +02:00
|
|
|
|
|
|
|
void PlaylistContainer::UpdateActiveIcon(const QIcon& icon) {
|
|
|
|
// Unset all existing icons
|
2014-02-07 16:34:20 +01:00
|
|
|
for (int i = 0; i < ui_->tab_bar->count(); ++i) {
|
2012-10-31 06:53:09 +01:00
|
|
|
ui_->tab_bar->setTabIcon(i, QIcon());
|
2010-05-21 00:48:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set our icon
|
2014-02-07 16:34:20 +01:00
|
|
|
if (!icon.isNull()) ui_->tab_bar->set_icon_by_id(manager_->active_id(), icon);
|
2010-05-21 00:48:11 +02:00
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void PlaylistContainer::PlaylistAdded(int id, const QString& name,
|
|
|
|
bool favorite) {
|
2011-04-28 19:50:45 +02:00
|
|
|
const int index = ui_->tab_bar->count();
|
2013-05-11 23:17:54 +02:00
|
|
|
ui_->tab_bar->InsertTab(id, index, name, favorite);
|
2010-05-21 01:18:55 +02:00
|
|
|
|
|
|
|
// Are we startup up, should we select this tab?
|
2010-05-21 12:57:40 +02:00
|
|
|
if (starting_up_ && settings_.value("current_playlist", 1).toInt() == id) {
|
2010-05-21 01:18:55 +02:00
|
|
|
starting_up_ = false;
|
2010-05-21 12:29:17 +02:00
|
|
|
ui_->tab_bar->set_current_id(id);
|
2010-05-21 01:18:55 +02:00
|
|
|
}
|
2010-05-21 12:57:40 +02:00
|
|
|
|
|
|
|
if (ui_->tab_bar->count() > 1) {
|
|
|
|
// Have to do this here because sizeHint() is only valid when there's a
|
|
|
|
// tab in the bar.
|
|
|
|
tab_bar_animation_->setFrameRange(0, ui_->tab_bar->sizeHint().height());
|
|
|
|
|
|
|
|
if (!isVisible()) {
|
|
|
|
// Skip the animation since the window is hidden (eg. if we're still
|
|
|
|
// loading the UI).
|
|
|
|
tab_bar_visible_ = true;
|
2010-10-01 21:27:01 +02:00
|
|
|
ui_->tab_bar->setMaximumHeight(tab_bar_animation_->endFrame());
|
2010-05-21 12:57:40 +02:00
|
|
|
} else {
|
|
|
|
SetTabBarVisible(true);
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 23:21:55 +02:00
|
|
|
}
|
|
|
|
|
2017-05-30 19:19:08 +02:00
|
|
|
void PlaylistContainer::Started() { starting_up_ = false; }
|
2015-03-25 22:13:39 +01:00
|
|
|
|
2012-10-31 07:04:22 +01:00
|
|
|
void PlaylistContainer::PlaylistClosed(int id) {
|
2010-05-21 12:29:17 +02:00
|
|
|
ui_->tab_bar->RemoveTab(id);
|
2010-05-21 12:57:40 +02:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
if (ui_->tab_bar->count() <= 1) SetTabBarVisible(false);
|
2010-05-20 23:21:55 +02:00
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void PlaylistContainer::PlaylistRenamed(int id, const QString& new_name) {
|
2010-05-21 12:29:17 +02:00
|
|
|
ui_->tab_bar->set_text_by_id(id, new_name);
|
2010-05-20 23:21:55 +02:00
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void PlaylistContainer::NewPlaylist() { manager_->New(tr("Playlist")); }
|
2010-05-20 23:21:55 +02:00
|
|
|
|
2010-05-21 01:18:55 +02:00
|
|
|
void PlaylistContainer::LoadPlaylist() {
|
2010-05-22 22:28:11 +02:00
|
|
|
QString filename = settings_.value("last_load_playlist").toString();
|
2014-02-07 16:34:20 +01:00
|
|
|
filename = QFileDialog::getOpenFileName(this, tr("Load playlist"), filename,
|
|
|
|
manager_->parser()->filters());
|
2010-05-21 01:18:55 +02:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
if (filename.isNull()) return;
|
2010-05-22 22:28:11 +02:00
|
|
|
|
|
|
|
settings_.setValue("last_load_playlist", filename);
|
|
|
|
|
2010-05-23 00:20:00 +02:00
|
|
|
manager_->Load(filename);
|
|
|
|
}
|
2010-05-22 22:28:11 +02:00
|
|
|
|
2010-05-23 00:20:00 +02:00
|
|
|
void PlaylistContainer::SavePlaylist(int id = -1) {
|
2013-05-23 20:09:35 +02:00
|
|
|
// Use the tab name as the suggested name
|
|
|
|
QString suggested_name = ui_->tab_bar->tabText(ui_->tab_bar->currentIndex());
|
2010-07-31 15:10:08 +02:00
|
|
|
|
2013-05-23 20:09:35 +02:00
|
|
|
manager_->SaveWithUI(id, suggested_name);
|
2010-05-20 23:21:55 +02:00
|
|
|
}
|
|
|
|
|
2011-04-19 22:11:24 +02:00
|
|
|
void PlaylistContainer::GoToNextPlaylistTab() {
|
|
|
|
// Get the next tab' id
|
2014-02-07 16:34:20 +01:00
|
|
|
int id_next = ui_->tab_bar->id_of((ui_->tab_bar->currentIndex() + 1) %
|
|
|
|
ui_->tab_bar->count());
|
2011-04-19 22:11:24 +02:00
|
|
|
// Switch to next tab
|
|
|
|
manager_->SetCurrentPlaylist(id_next);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlaylistContainer::GoToPreviousPlaylistTab() {
|
|
|
|
// Get the next tab' id
|
2014-02-07 16:34:20 +01:00
|
|
|
int id_previous = ui_->tab_bar->id_of(
|
|
|
|
(ui_->tab_bar->currentIndex() + ui_->tab_bar->count() - 1) %
|
|
|
|
ui_->tab_bar->count());
|
2011-04-19 22:11:24 +02:00
|
|
|
// Switch to next tab
|
|
|
|
manager_->SetCurrentPlaylist(id_previous);
|
|
|
|
}
|
|
|
|
|
2019-09-07 04:29:19 +02:00
|
|
|
void PlaylistContainer::DirtyTabBar() {
|
|
|
|
dirty_ = true;
|
|
|
|
app_->DirtySettings();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlaylistContainer::Save(QSettings* settings_) {
|
|
|
|
if (starting_up_ || !dirty_) return;
|
|
|
|
dirty_ = false;
|
2010-05-20 23:21:55 +02:00
|
|
|
|
2019-09-07 04:29:19 +02:00
|
|
|
settings_->beginGroup(kSettingsGroup);
|
|
|
|
settings_->setValue("current_playlist", ui_->tab_bar->current_id());
|
|
|
|
settings_->endGroup();
|
2010-05-20 23:21:55 +02:00
|
|
|
}
|
2010-05-21 12:57:40 +02:00
|
|
|
|
|
|
|
void PlaylistContainer::SetTabBarVisible(bool visible) {
|
2014-02-07 16:34:20 +01:00
|
|
|
if (tab_bar_visible_ == visible) return;
|
2010-05-21 12:57:40 +02:00
|
|
|
tab_bar_visible_ = visible;
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
tab_bar_animation_->setDirection(visible ? QTimeLine::Forward
|
|
|
|
: QTimeLine::Backward);
|
2010-05-21 12:57:40 +02:00
|
|
|
tab_bar_animation_->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlaylistContainer::SetTabBarHeight(int height) {
|
2010-10-01 21:27:01 +02:00
|
|
|
ui_->tab_bar->setMaximumHeight(height);
|
2010-05-21 12:57:40 +02:00
|
|
|
}
|
2010-05-22 18:36:13 +02:00
|
|
|
|
2012-09-09 00:35:50 +02:00
|
|
|
void PlaylistContainer::MaybeUpdateFilter() {
|
|
|
|
// delaying the filter update on small playlists is undesirable
|
|
|
|
// and an empty filter applies very quickly, too
|
|
|
|
if (manager_->current()->rowCount() < kFilterDelayPlaylistSizeThreshold ||
|
|
|
|
ui_->filter->text().isEmpty()) {
|
|
|
|
UpdateFilter();
|
|
|
|
} else {
|
|
|
|
filter_timer_->start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-22 18:36:13 +02:00
|
|
|
void PlaylistContainer::UpdateFilter() {
|
2012-10-31 06:53:09 +01:00
|
|
|
manager_->current()->proxy()->setFilterFixedString(ui_->filter->text());
|
|
|
|
ui_->playlist->JumpToCurrentlyPlayingTrack();
|
2010-05-22 19:03:18 +02:00
|
|
|
|
2011-04-29 13:24:58 +02:00
|
|
|
UpdateNoMatchesLabel();
|
|
|
|
}
|
2010-05-22 19:03:18 +02:00
|
|
|
|
2011-04-29 13:24:58 +02:00
|
|
|
void PlaylistContainer::UpdateNoMatchesLabel() {
|
|
|
|
Playlist* playlist = manager_->current();
|
|
|
|
const bool has_rows = playlist->rowCount() != 0;
|
|
|
|
const bool has_results = playlist->proxy()->rowCount() != 0;
|
|
|
|
|
|
|
|
QString text;
|
2012-10-31 06:53:09 +01:00
|
|
|
if (has_rows && !has_results) {
|
2020-09-18 16:15:19 +02:00
|
|
|
if (ui_->filter->text().trimmed().compare("the answer to life the universe "
|
|
|
|
"and everything",
|
|
|
|
Qt::CaseInsensitive) == 0) {
|
2014-07-24 23:45:15 +02:00
|
|
|
text = "42";
|
|
|
|
} else {
|
2014-08-18 17:56:01 +02:00
|
|
|
text = tr(
|
|
|
|
"No matches found. Clear the search box to show the whole playlist "
|
|
|
|
"again.");
|
2014-07-24 23:45:15 +02:00
|
|
|
}
|
2011-04-29 13:24:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!text.isEmpty()) {
|
|
|
|
no_matches_label_->setText(text);
|
|
|
|
RepositionNoMatchesLabel(true);
|
|
|
|
no_matches_label_->show();
|
|
|
|
} else {
|
|
|
|
no_matches_label_->hide();
|
2011-04-28 19:50:45 +02:00
|
|
|
}
|
2010-05-22 19:03:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlaylistContainer::resizeEvent(QResizeEvent* e) {
|
|
|
|
QWidget::resizeEvent(e);
|
|
|
|
RepositionNoMatchesLabel();
|
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void PlaylistContainer::FocusOnFilter(QKeyEvent* event) {
|
2012-06-28 12:35:20 +02:00
|
|
|
ui_->filter->setFocus();
|
2016-03-25 01:36:46 +01:00
|
|
|
|
|
|
|
switch (event->key()) {
|
|
|
|
case Qt::Key_Backspace:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Qt::Key_Escape:
|
|
|
|
ui_->filter->clear();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ui_->filter->setText(ui_->filter->text() + event->text());
|
|
|
|
break;
|
2012-07-14 00:00:16 +02:00
|
|
|
}
|
2011-02-23 23:21:17 +01:00
|
|
|
}
|
|
|
|
|
2010-05-22 19:03:18 +02:00
|
|
|
void PlaylistContainer::RepositionNoMatchesLabel(bool force) {
|
2014-02-07 16:34:20 +01:00
|
|
|
if (!force && !no_matches_label_->isVisible()) return;
|
2010-05-22 19:03:18 +02:00
|
|
|
|
|
|
|
const int kBorder = 10;
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
QPoint pos =
|
|
|
|
ui_->playlist->viewport()->mapTo(ui_->playlist, QPoint(kBorder, kBorder));
|
2010-05-22 19:03:18 +02:00
|
|
|
QSize size = ui_->playlist->viewport()->size();
|
|
|
|
size.setWidth(size.width() - kBorder * 2);
|
|
|
|
size.setHeight(size.height() - kBorder * 2);
|
|
|
|
|
|
|
|
no_matches_label_->move(pos);
|
|
|
|
no_matches_label_->resize(size);
|
2010-05-22 18:36:13 +02:00
|
|
|
}
|
2010-06-13 14:45:05 +02:00
|
|
|
|
|
|
|
void PlaylistContainer::SelectionChanged() {
|
|
|
|
manager_->SelectionChanged(view()->selectionModel()->selection());
|
|
|
|
}
|
2011-02-23 23:21:17 +01:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
bool PlaylistContainer::eventFilter(QObject* objectWatched, QEvent* event) {
|
|
|
|
if (objectWatched == ui_->filter) {
|
2011-02-23 23:21:17 +01:00
|
|
|
if (event->type() == QEvent::KeyPress) {
|
2014-02-07 16:34:20 +01:00
|
|
|
QKeyEvent* e = static_cast<QKeyEvent*>(event);
|
|
|
|
switch (e->key()) {
|
2011-02-23 23:21:17 +01:00
|
|
|
case Qt::Key_Down:
|
|
|
|
case Qt::Key_PageUp:
|
|
|
|
case Qt::Key_PageDown:
|
|
|
|
case Qt::Key_Return:
|
|
|
|
case Qt::Key_Enter:
|
|
|
|
view()->setFocus(Qt::OtherFocusReason);
|
|
|
|
QApplication::sendEvent(ui_->playlist, event);
|
|
|
|
return true;
|
|
|
|
case Qt::Key_Escape:
|
2012-06-27 17:08:51 +02:00
|
|
|
ui_->filter->clear();
|
2011-02-24 01:00:10 +01:00
|
|
|
return true;
|
2011-02-23 23:21:17 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QWidget::eventFilter(objectWatched, event);
|
|
|
|
}
|
2018-01-03 16:24:56 +01:00
|
|
|
|
|
|
|
void PlaylistContainer::ReloadSettings() {
|
|
|
|
QSettings settings;
|
|
|
|
settings.beginGroup(Appearance::kSettingsGroup);
|
|
|
|
bool hide_toolbar = settings.value("b_hide_filter_toolbar", false).toBool();
|
|
|
|
ui_->toolbar->setVisible(!hide_toolbar);
|
2018-10-20 13:57:49 +02:00
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
settings.beginGroup(Player::kSettingsGroup);
|
|
|
|
if (settings.value("play_count_short_duration").toBool()) {
|
|
|
|
playlist_->set_max_play_count_point_nsecs(60ll * kNsecPerSec);
|
|
|
|
} else {
|
|
|
|
playlist_->set_max_play_count_point_nsecs(240ll * kNsecPerSec);
|
|
|
|
}
|
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
qLog(Debug) << "new max scrobble point:"
|
|
|
|
<< (playlist_->get_max_play_count_point_nsecs() / kNsecPerSec);
|
2018-01-03 16:24:56 +01:00
|
|
|
}
|