-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BaseTrackTableModel: Fix column header mapping #13782
base: 2.5
Are you sure you want to change the base?
Conversation
Co-authored-by: Daniel Schürmann <[email protected]>
…n properties for all track tables. This simplifies the maintenance of track properties, and cannot go wrong, because th GCC compiler does not allow missing columns or resorting within the table.
We are past string freeze for 2.5 - Shouldn't this go into main instead? |
We may decide. I have no particular demand. It is at 2.5 because @uklotzde has picked that target. |
src/library/columncache.cpp
Outdated
DEBUG_ASSERT(it.key() < NUM_COLUMNS); | ||
DEBUG_ASSERT(m_columnIndexByEnum[it.key()] == -1); | ||
m_columnIndexByEnum[it.key()] = fieldIndex(it.value()); | ||
DEBUG_ASSERT(std::size(kColumnNameByEnum) == std::size(m_columnIndexByEnum)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be a static assert.
src/library/columncache.cpp
Outdated
const QString& ColumnCache::columnName(Column column) const { | ||
DEBUG_ASSERT(static_cast<std::size_t>(column) < std::size(kColumnNameByEnum)); | ||
return kColumnNameByEnum[column]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there may be some constexpr
opportunity here by switching to a constexpr
friendly type like QStringView
and making kColumnNameByEnum
constexpr
accordingly by storing char16_t
s instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a QString form a QStringView is a deep copy.
kColumnNameByEnum uses LIBRARYTABLE_ID and friends a QStringLiteral which is basically a constexpr, but does not have the keyword because of MSVC limitations.
So using a QStringView here for the sake of becoming a constexpr, will introduce more deep copies later where now implicit sharing is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With a pointer it works.
index.sibling(index.row(), | ||
fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ARTIST)) | ||
.data() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this deserves a utility function IMO.
.toString() | ||
.toFloat(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.toString() | |
.toFloat(); | |
.toFloat(); |
src/library/columncache.cpp
Outdated
[ColumnCache::COLUMN_LIBRARYTABLE_ID] = LIBRARYTABLE_ID, | ||
[ColumnCache::COLUMN_LIBRARYTABLE_ARTIST] = LIBRARYTABLE_ARTIST, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is unfortunately not valid C++.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my understanding this is the C++ 20 feature "designated initializers".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-(
Error: /home/runner/work/mixxx/mixxx/src/library/columncache.cpp:27:9: error: array designators are a C99 extension [-Werror,-Wc99-designator]
[ColumnCache::COLUMN_LIBRARYTABLE_ID] = {LIBRARYTABLE_ID,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup. Designated initializers are cool, but they deliberately work differently to allow for for example default arguments. I'm afraid there is no real way of achieving this trick in C++. You'll implicitly have to assume that the order of the list matches the enum order. The better strategy would instead simply be to not rely on the enum order at all though. Instead of having a bunch of globals arrays, consider having a single array of structs that bundles these together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll implicitly have to assume that the order of the list matches the enum order.
A appreciate exactly this behavior a feature. This makes sure the list is complete and consistent.
I don't understand you proposal.
I would like to treat this as a compiler feature we can use like #pragma once
, and just silence clazy.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to treat this as a compiler feature we can use like #pragma once, and just silence clazy.
I'm not sure its worth the trouble trying to opt into this extension and maintain it on every compiler. I'm also not sure what the semantics are when the enum suddenly gets different values (are entries in the array that are now empty unitialized, zero or default initialized?) I don't think we should mix C99 extensions with C++ code.
Have you instead considered putting this into a utility function with a switch-case? Performance is likely comparable and this time we don't have issues if the enum suddenly gets gaps and we can rely on -Wswitch
for exhaustiveness (also we don't need NUM_COLUMNS
anymore, which is always a hack).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also not sure what the semantics are when the enum suddenly gets different values
That is the great thing with this "feature". Compiling fails. So you cannot mess up the initalization you can do if this are single cals or an anonymous initalizer like in MSVC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this time we don't have issues if the enum suddenly gets gaps
Than we have an initialized element. This can not happen currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I won't stress this for now then. Lets focus on the other stuff first.
03fd6d9
to
80d69e5
Compare
src/library/basesqltablemodel.cpp
Outdated
return m_tableColumns.size() + sourceTableIndex - 1; | ||
} | ||
} | ||
return tableIndex; | ||
} | ||
|
||
int BaseSqlTableModel::maxFieldIndex() const { | ||
// Subtract one to remove the id column which is in both | ||
return m_tableColumns.size() + (m_trackSource ? m_trackSource->maxFieldIndex() : 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't look correct to me.
The brittle max index = size minus one semantics are error prone.
maxFieldIndex()
should better become endFieldIndex()
which would be more consistent with how ranges are represented in C++.
98227f7
to
dcddaa9
Compare
Done |
No objections. I didn't review the additional changes in detail because they don't seem to affect my use case. I'll update my fork after the changes have reached main. Hint: This could have been achieved by merging smaller, independent PRs from different contributors. One at a time. Would cause less friction and frustration. |
This finishes the work of @uklotzde in #13682 to fix the column header mapping in case using additional columns in his fork, not used in Mixxx.
I avoid a redundant initialization loop and in addition this improves the maintenance a lot by using a const kColumnPropertiesByEnum[] table to initialize thee header properties. This has the advantage that the compiler (tested with gcc) can check weather the table is complete.
If an entry is missing or not in consecutive order we will get:
Note: This requires a Transifex roundtrip to move the header translations to the new translation scope, to the new common place for all.