#include "widget/wtracktableview.h"
#include <QDrag>
#include <QModelIndex>
#include <QScrollBar>
#include <QShortcut>
#include <QUrl>
#include "control/controlobject.h"
#include "library/dao/trackschema.h"
#include "library/library.h"
#include "library/library_prefs.h"
#include "library/librarytablemodel.h"
#include "library/trackcollection.h"
#include "library/trackcollectionmanager.h"
#include "mixer/playermanager.h"
#include "moc_wtracktableview.cpp"
#include "preferences/colorpalettesettings.h"
#include "preferences/dialog/dlgpreflibrary.h"
#include "sources/soundsourceproxy.h"
#include "track/track.h"
#include "track/trackref.h"
#include "util/assert.h"
#include "util/dnd.h"
#include "util/time.h"
#include "widget/wtrackmenu.h"
#include "widget/wtracktableviewheader.h"
namespace {
// ConfigValue key for QTable vertical scrollbar position
const ConfigKey kVScrollBarPosConfigKey{
// mixxx::library::prefs::kConfigGroup is defined in another
// unit of compilation and cannot be reused here!
QStringLiteral("[Library]"),
QStringLiteral("VScrollBarPos")};
const ConfigKey kConfigKeyAllowTrackLoadToPlayingDeck{
QStringLiteral("[Controls]"),
QStringLiteral("AllowTrackLoadToPlayingDeck")};
// Default color for the focus border of TableItemDelegates
const QColor kDefaultFocusBorderColor = Qt::white;
} // anonymous namespace
WTrackTableView::WTrackTableView(QWidget* parent,
UserSettingsPointer pConfig,
Library* pLibrary,
double backgroundColorOpacity,
bool sorting)
: WLibraryTableView(parent,
pConfig,
kVScrollBarPosConfigKey),
m_pConfig(pConfig),
m_pLibrary(pLibrary),
m_backgroundColorOpacity(backgroundColorOpacity),
m_pFocusBorderColor(kDefaultFocusBorderColor),
m_sorting(sorting),
m_selectionChangedSinceLastGuiTick(true),
m_loadCachedOnly(false) {
// Connect slots and signals to make the world go 'round.
connect(this, &WTrackTableView::doubleClicked, this, &WTrackTableView::slotMouseDoubleClicked);
m_pCOTGuiTick = new ControlProxy("[Master]", "guiTick50ms", this);
m_pCOTGuiTick->connectValueChanged(this, &WTrackTableView::slotGuiTick50ms);
m_pKeyNotation = new ControlProxy(mixxx::library::prefs::kKeyNotationConfigKey, this);
m_pKeyNotation->connectValueChanged(this, &WTrackTableView::keyNotationChanged);
m_pSortColumn = new ControlProxy("[Library]", "sort_column", this);
m_pSortColumn->connectValueChanged(this, &WTrackTableView::applySortingIfVisible);
m_pSortOrder = new ControlProxy("[Library]", "sort_order", this);
m_pSortOrder->connectValueChanged(this, &WTrackTableView::applySortingIfVisible);
connect(this,
&WTrackTableView::scrollValueChanged,
this,
&WTrackTableView::slotScrollValueChanged);
QShortcut* setFocusShortcut =
new QShortcut(QKeySequence(tr("ESC", "Focus")), this);
connect(setFocusShortcut,
&QShortcut::activated,
this,
QOverload<>::of(&WTrackTableView::setFocus));
}
WTrackTableView::~WTrackTableView() {
WTrackTableViewHeader* pHeader =
qobject_cast<WTrackTableViewHeader*>(horizontalHeader());
if (pHeader) {
pHeader->saveHeaderState();
}
}
void WTrackTableView::enableCachedOnly() {
if (!m_loadCachedOnly) {
// don't try to load and search covers, drawing only
// covers which are already in the QPixmapCache.
emit onlyCachedCoverArt(true);
m_loadCachedOnly = true;
}
m_lastUserAction = mixxx::Time::elapsed();
}
void WTrackTableView::slotScrollValueChanged(int /*unused*/) {
enableCachedOnly();
}
void WTrackTableView::selectionChanged(
const QItemSelection& selected, const QItemSelection& deselected) {
m_selectionChangedSinceLastGuiTick = true;
enableCachedOnly();
QTableView::selectionChanged(selected, deselected);
}
void WTrackTableView::slotGuiTick50ms(double /*unused*/) {
// if the user is stopped in the same row for more than 0.1 s,
// we load un-cached cover arts as well.
mixxx::Duration timeDelta = mixxx::Time::elapsed() - m_lastUserAction;
if (m_loadCachedOnly && timeDelta > mixxx::Duration::fromMillis(100)) {
// Show the currently selected track in the large cover art view and
// highlights crate and playlists. Doing this in selectionChanged
// slows down scrolling performance so we wait until the user has
// stopped interacting first.
if (m_selectionChangedSinceLastGuiTick) {
const QModelIndexList indices = selectionModel()->selectedRows();
if (indices.size() == 1 &&a