Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
8dbb96f
Add Grantlee lib to dependencies
poelzi Jan 18, 2021
5874dbe
Major track export overhaul
poelzi Jan 18, 2021
ad7ac51
Use the the last right click selected playlist, not the current
poelzi Jan 18, 2021
167550a
Add libgrantlee5-dev to debian build env
poelzi Jan 18, 2021
69f357d
Fix build problems
poelzi Jan 18, 2021
4672c8b
Make Key a Q_GADGET and add string properties for formatting
poelzi Jan 18, 2021
b97b6cc
Use index for position index and dup for duplication counter
poelzi Jan 19, 2021
0d9618e
Add support for exporting files from context menu
poelzi Jan 19, 2021
d129f2d
Export crate summary into file exporter context
poelzi Jan 19, 2021
e2d9ec9
Add render function which does not escape html characters
poelzi Jan 20, 2021
19f00f6
Add grantlee plugin with mixxx specific filters
poelzi Jan 21, 2021
715355c
Fix Exporter Test
poelzi Jan 21, 2021
fc287dc
Use CrateSummaryWrapper as QObject wrapper
poelzi Jan 22, 2021
993a5e7
Add zeropad filter for adding 0 prefixes
poelzi Jan 22, 2021
515d393
Move exportPlaylistItemsIntoFile to Parser
poelzi Jan 22, 2021
999edbf
Add support for creating a playlist on file export
poelzi Jan 23, 2021
7c86579
Add PlaylistSummary for repersenting playlists
poelzi Nov 22, 2020
f6fc540
Add PlaylistSummary wrapper and export to track exporter
poelzi Jan 23, 2021
cc9b5fa
Add round filter, move default patterns to code
poelzi Jan 23, 2021
998667f
Compile fixes
poelzi Jan 24, 2021
9324697
Merge branch 'main' of https://github.com/mixxxdj/mixxx into better-e…
poelzi Jan 25, 2021
7c1d480
Merge branch 'main' of https://github.com/mixxxdj/mixxx into better-e…
poelzi Jan 26, 2021
1d64ce4
Add function to ensure safe filename on all platforms
poelzi Feb 1, 2021
3057941
Use tabwidget for export dialog
poelzi Feb 1, 2021
dd3d9e6
cleanup group filter
poelzi Feb 1, 2021
3a79ffa
Fix missing assignment of crateWrapper
poelzi Feb 2, 2021
7fad172
Properly escape problematic filenames on all platforms
poelzi Feb 2, 2021
488671b
Use Dropdown Menu for pattern suggestions, not a ComboBox
poelzi Feb 3, 2021
4d0ce25
Implement default lookup function for keys (not working)
poelzi Feb 3, 2021
049c65d
fix clazy warnings
poelzi Feb 5, 2021
2118737
clazy fixes
poelzi Feb 7, 2021
87aa753
Use one button line in export
poelzi Feb 7, 2021
49aa05d
Escape playlist name in menu
poelzi Feb 7, 2021
1dd67eb
Prevent crashes on patterns like "{{ }}"
poelzi Feb 18, 2021
82652f0
Go back to a QComboBox but with custom item handling
poelzi Feb 19, 2021
28f0439
Merge branch 'main' of https://github.com/mixxxdj/mixxx into better-e…
poelzi Apr 12, 2021
fa3db2d
Merge remote-tracking branch 'upstream/main' into betterfileexportqt6
JoergAtGithub Sep 24, 2023
6f70c44
Fix handling of windows drive letters in paths (colon is allowed here)
JoergAtGithub Sep 24, 2023
6e43d32
Fixed trackexport_test.cpp
JoergAtGithub Sep 24, 2023
a3f9ab9
Fix pre-commit
JoergAtGithub Sep 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,6 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/library/export/coverartcopyworker.cpp
src/library/export/dlgtrackexport.ui
src/library/export/trackexportdlg.cpp
src/library/export/trackexportwizard.cpp
src/library/export/trackexportworker.cpp
src/library/externaltrackcollection.cpp
src/library/hiddentablemodel.cpp
Expand Down Expand Up @@ -921,7 +920,9 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/library/trackset/crate/cratefeaturehelper.cpp
src/library/trackset/crate/cratestorage.cpp
src/library/trackset/crate/cratetablemodel.cpp
src/library/trackset/crate/cratesummary.cpp
src/library/trackset/playlistfeature.cpp
src/library/trackset/playlistsummary.cpp
src/library/trackset/setlogfeature.cpp
src/library/trackset/tracksettablemodel.cpp
src/library/traktor/traktorfeature.cpp
Expand Down Expand Up @@ -1087,9 +1088,11 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/util/experiment.cpp
src/util/file.cpp
src/util/imagefiledata.cpp
src/util/fileutils.cpp
src/util/fileaccess.cpp
src/util/fileinfo.cpp
src/util/filename.cpp
src/util/formatter.cpp
src/util/imagefiledata.cpp
src/util/imageutils.cpp
src/util/indexrange.cpp
Expand Down Expand Up @@ -1865,6 +1868,8 @@ add_executable(mixxx-test
src/test/enginemixertest.cpp
src/test/enginemicrophonetest.cpp
src/test/enginesynctest.cpp
src/test/formatter_test.cpp
src/test/fileutils_test.cpp
src/test/fileinfo_test.cpp
src/test/frametest.cpp
src/test/globaltrackcache_test.cpp
Expand Down Expand Up @@ -2307,6 +2312,44 @@ elseif(GNU_GCC OR LLVM_CLANG)
endif()
target_link_libraries(mixxx-lib PRIVATE FpClassify)

# Grantlee5 (5.3.0 is the first version with Qt6 support)
find_package(Grantlee5 5.3.0 NAMES grantlee grantlee5 )

if(NOT Grantlee5_FOUND)
message(FATAL_ERROR "No Grantlee5 for Qt6 available")
else()
# An existing installation of Grantlee5 is available.
message(STATUS "Use existing system installation of Grantlee5")
endif()

target_link_libraries(mixxx-lib PUBLIC
Grantlee5::Templates
Grantlee5::TextDocument
)

# grantlee plugin
add_dependencies(mixxx-lib mixxxformatter)
add_library(mixxxformatter MODULE
src/util/formatterplugin/mixxxformatter.cpp
src/util/fileutils.cpp
)

set_target_properties(mixxxformatter PROPERTIES AUTOMOC ON)
target_include_directories(mixxxformatter PRIVATE src)

grantlee_adjust_plugin_name(mixxxformatter)

target_link_libraries(mixxxformatter
Grantlee5::Templates
)

add_custom_command(TARGET mixxxformatter POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Grantlee5::defaulttags> $<TARGET_FILE_DIR:mixxxformatter>
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Grantlee5::defaultfilters> $<TARGET_FILE_DIR:mixxxformatter>
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Grantlee5::loadertags> $<TARGET_FILE_DIR:mixxxformatter>
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Grantlee5::Templates> $<TARGET_FILE_DIR:mixxxformatter>"/grantlee/${Grantlee5_VERSION_MAJOR}.${Grantlee5_VERSION_MINOR}"
)

# LAME
find_package(mp3lame REQUIRED)
target_link_libraries(mixxx-lib PRIVATE mp3lame::mp3lame)
Expand Down Expand Up @@ -2543,6 +2586,16 @@ else()
RUNTIME_DEPENDENCY_SET mixxx
COMPONENT applocal)

install(IMPORTED_RUNTIME_ARTIFACTS
mixxxformatter
Grantlee5::defaulttags
Grantlee5::defaultfilters
Grantlee5::loadertags
Grantlee5::Templates
DESTINATION "${MIXXX_INSTALL_DATADIR}/grantlee/${Grantlee5_VERSION_MAJOR}.${Grantlee5_VERSION_MINOR}"
RUNTIME_DEPENDENCY_SET mixxx
COMPONENT applocal)

if(WIN32)
install(IMPORTED_RUNTIME_ARTIFACTS Qt${QT_VERSION_MAJOR}::QWindowsIntegrationPlugin
DESTINATION "${MIXXX_INSTALL_DATADIR}/platforms"
Expand Down
1 change: 1 addition & 0 deletions packaging/debian/control.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Build-Depends: debhelper (>= 11),
# Only needed for running tests that use SQLite.
libqt5sql5-sqlite,
libqt5x11extras5-dev,
libgrantlee5-dev,
cmake (>= 3.13),
libjack-dev,
portaudio19-dev,
Expand Down
146 changes: 144 additions & 2 deletions src/library/dao/playlistdao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,32 @@ PlaylistDAO::PlaylistDAO()
void PlaylistDAO::initialize(const QSqlDatabase& database) {
DAO::initialize(database);
populatePlaylistMembershipCache();

// create temporary views
QString queryString = QLatin1String(
"CREATE TEMPORARY VIEW IF NOT EXISTS PlaylistsCountsDurations "
"AS SELECT "
" Playlists.id AS id, "
" Playlists.name AS name, "
" LOWER(Playlists.name) AS sort_name, "
" COUNT(case library.mixxx_deleted when 0 then 1 else null end) "
" AS count, "
" SUM(case library.mixxx_deleted "
" when 0 then library.duration else 0 end) AS durationSeconds "
"FROM Playlists "
"LEFT JOIN PlaylistTracks "
" ON PlaylistTracks.playlist_id = Playlists.id "
"LEFT JOIN library "
" ON PlaylistTracks.track_id = library.id "
" WHERE Playlists.hidden = 0 "
" GROUP BY Playlists.id");
queryString.append(
mixxx::DbConnection::collateLexicographically(
" ORDER BY sort_name"));
QSqlQuery query(m_database);
if (!query.exec(queryString)) {
LOG_FAILED_QUERY(query);
}
}

void PlaylistDAO::populatePlaylistMembershipCache() {
Expand Down Expand Up @@ -472,8 +498,8 @@ unsigned int PlaylistDAO::playlistCount() const {
}

QList<QPair<int, QString>> PlaylistDAO::getPlaylists(const HiddenType hidden) const {
//qDebug() << "PlaylistDAO::getPlaylists(hidden =" << hidden
// << QThread::currentThread() << m_database.connectionName();
// qDebug() << "PlaylistDAO::getPlaylists(hidden =" << hidden
// << QThread::currentThread() << m_database.connectionName();

QSqlQuery query(m_database);
query.prepare(
Expand Down Expand Up @@ -1272,6 +1298,122 @@ void PlaylistDAO::getPlaylistsTrackIsIn(TrackId trackId,
}
}

QList<PlaylistSummary> PlaylistDAO::createPlaylistSummaryForTracks(const QList<TrackId>& tracks) {
QSet<int> allPlaylistIds;
QSet<int> playlistIds;
QMap<int, int> trackCount;
for (TrackId trackId : tracks) {
PlaylistDAO::getPlaylistsTrackIsIn(trackId, &playlistIds);
allPlaylistIds += playlistIds;
for (int playlistId : qAsConst(playlistIds)) {
trackCount[playlistId] = trackCount.value(playlistId, 0) + 1;
}
}
QList<PlaylistSummary> summaries = PlaylistDAO::createPlaylistSummary(&allPlaylistIds);
for (PlaylistSummary summary : summaries) {
DEBUG_ASSERT(trackCount.contains(summary.id()));
summary.setMatches(trackCount.value(summary.id()));
}
return summaries;
}

QList<PlaylistSummary> PlaylistDAO::createPlaylistSummary(const QSet<int>* playlistIds) {
QList<PlaylistSummary> playlistLabels;

// Setup the sidebar playlist model
QSqlTableModel playlistTableModel(this, m_database);
playlistTableModel.setTable("PlaylistsCountsDurations");

if (playlistIds) {
QStringList idList;
for (const auto& playlistId : *playlistIds) {
idList.append(QString::number(playlistId));
}
playlistTableModel.setFilter(QString("id in [%1]").arg(idList.join(",")));
}

playlistTableModel.select();
while (playlistTableModel.canFetchMore()) {
playlistTableModel.fetchMore();
}
QSqlRecord record = playlistTableModel.record();
int nameColumn = record.indexOf("name");
int idColumn = record.indexOf("id");
int countColumn = record.indexOf("count");
int durationColumn = record.indexOf("durationSeconds");

for (int row = 0; row < playlistTableModel.rowCount(); ++row) {
int id =
playlistTableModel
.data(playlistTableModel.index(row, idColumn))
.toInt();
QString name =
playlistTableModel
.data(playlistTableModel.index(row, nameColumn))
.toString();
int count =
playlistTableModel
.data(playlistTableModel.index(row, countColumn))
.toInt();
int duration =
playlistTableModel
.data(playlistTableModel.index(row, durationColumn))
.toInt();
PlaylistSummary playlist(id, name);
playlist.setCount(count);
playlist.setDuration(duration);
playlistLabels.append(playlist);
}
return playlistLabels;
}
PlaylistSummary PlaylistDAO::getPlaylistSummary(int playlistId) {
if (playlistId == -1) {
return PlaylistSummary();
}
QSqlTableModel playlistTableModel(this, m_database);
playlistTableModel.setTable("PlaylistsCountsDurations");

playlistTableModel.setFilter(QString("id = %1").arg(playlistId));

playlistTableModel.select();
while (playlistTableModel.canFetchMore()) {
playlistTableModel.fetchMore();
}
QSqlRecord record = playlistTableModel.record();
int nameColumn = record.indexOf("name");
int idColumn = record.indexOf("id");
int countColumn = record.indexOf("count");
int durationColumn = record.indexOf("durationSeconds");

if (playlistTableModel.rowCount() == 0) {
return PlaylistSummary();
}
VERIFY_OR_DEBUG_ASSERT(playlistTableModel.rowCount() == 1) {
qWarning() << "playlist id matched to multiple results";
}

int id =
playlistTableModel
.data(playlistTableModel.index(0, idColumn))
.toInt();
QString name =
playlistTableModel
.data(playlistTableModel.index(0, nameColumn))
.toString();
int count =
playlistTableModel
.data(playlistTableModel.index(0, countColumn))
.toInt();
int duration =
playlistTableModel
.data(playlistTableModel.index(0, durationColumn))
.toInt();
PlaylistSummary summary(id, name);
summary.setCount(count);
summary.setDuration(duration);
return summary;
}

void PlaylistDAO::setAutoDJProcessor(AutoDJProcessor* pAutoDJProcessor) {
m_pAutoDJProcessor = pAutoDJProcessor;
}
Expand Down
6 changes: 5 additions & 1 deletion src/library/dao/playlistdao.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

#include <QHash>
#include <QObject>
#include <QSqlDatabase>
#include <QSet>
#include <QSqlDatabase>

#include "library/dao/dao.h"
#include "library/trackset/playlistsummary.h"
#include "track/trackid.h"
#include "util/class.h"

Expand Down Expand Up @@ -129,6 +130,9 @@ class PlaylistDAO : public QObject, public virtual DAO {
bool isTrackInPlaylist(TrackId trackId, const int playlistId) const;

void getPlaylistsTrackIsIn(TrackId trackId, QSet<int>* playlistSet) const;
QList<PlaylistSummary> createPlaylistSummary(const QSet<int>* playlistIds = nullptr);
QList<PlaylistSummary> createPlaylistSummaryForTracks(const QList<TrackId>& tracks);
PlaylistSummary getPlaylistSummary(int playlistId);

void setAutoDJProcessor(AutoDJProcessor* pAutoDJProcessor);

Expand Down
Loading