-
-
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
Allow assigning more than one Hotcue to a Color in a Colorpalette #2902
Allow assigning more than one Hotcue to a Color in a Colorpalette #2902
Conversation
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.
These were some of the questions that came up and where I'm now stuck. I'd really appreciate some guidance here.
@@ -46,3 +49,27 @@ class ColorPaletteEditorModel : public QStandardItemModel { | |||
bool m_bEmpty; | |||
bool m_bDirty; | |||
}; | |||
|
|||
class HotcueIndexListItem : public QStandardItem { |
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.
The entire purpose of creating this class is to shift the "(de-)serialization" logic out of the model into the item so the item is responsible for translating between the String input and the data actually supposed to be represented as the string.
|
||
HotcueIndexListItem(const QList<int>& hotcueList = {}); | ||
|
||
void setData(const QVariant& value, int role = Qt::UserRole + 1) override; |
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 still don't quite understand the purpose of roles. I get that setData
and data
are "generic" accessors to get data for different purposes (such as displaying the data itself, providing a tooltip description etc). Since I only intent to intercept the data for editing and displaying, I should be able to reuse those roles instead of making my own role, right? Or what exactly am I supposed to do with the custom role.
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.
Right.
HotcueIndexListItem::HotcueIndexListItem(const QList<int>& hotcueList = {}) | ||
: QStandardItem(), m_hotcueIndexList(hotcueList) { | ||
} | ||
QVariant HotcueIndexListItem::data(int role = Qt::UserRole + 1) const { |
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.
My understanding here is that this acts as a getter for certain roles, right? Can't I just reuse the displayrole here and call the parent for every other role?
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.
mixxx/src/library/browse/browsethread.cpp
Line 95 in 472ec12
class YearItem: public QStandardItem { |
I think you want the display role like here.
// m_hotcueIndexList.append(hotcueIndex); | ||
// } | ||
// } | ||
const auto hotcueIndexStrings = value.toStringList(); |
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 just using a stringlist here because I wanted to test whether it was possible to somehow use that. Though I simply can't know since I don't fully understand how QVariant is supposed to work with a stringlist in this context. The Qt docs don't mention that.
c273c3f
to
0861564
Compare
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.
Cleaned up the code a bit. It still doesn't build because I'm unable to handle some stuff conceptually (see comments). I'm still not sure whether subclassing QStandardItem to parse and store a parsed version of the data for later access is a good idea. Could I get some feedback on that approach?
@@ -47,25 +56,39 @@ bool ColorPaletteEditorModel::dropMimeData(const QMimeData* data, Qt::DropAction | |||
|
|||
bool ColorPaletteEditorModel::setData(const QModelIndex& modelIndex, const QVariant& value, int role) { |
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 still confused when setData on the model and when setData on the Item is called...
@@ -8,6 +15,8 @@ QIcon toQIcon(const QColor& color) { | |||
return QIcon(pixmap); | |||
} | |||
|
|||
const QRegularExpression hotcueListMatchingRegex(QStringLiteral("([0-9]+)[ ,]+")); |
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 tried making this part of the class but that didn't work. Is it fine to just leave it here?
@@ -46,3 +49,25 @@ class ColorPaletteEditorModel : public QStandardItemModel { | |||
bool m_bEmpty; | |||
bool m_bDirty; | |||
}; | |||
|
|||
class HotcueIndexListItem : public QStandardItem { | |||
Q_OBJECT |
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.
Remove this macro and it will build.
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.
It currently doesn't build because of a bunch of syntax and typeerrors. I don't see how removing it would suddenly fix the build. Can I still remove the Q_OBJECT
though? It doesn't use any signals/slots or moc specific mechisms, though the parent QStandardItem does.
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.
Q_OBJECT macro defines some things in objects Inherited from QObject. QStandardItem does not inherit from QObject.
return QStandardItem::UserType; | ||
}; | ||
|
||
QList<int> getHotcueIndexList() const { |
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.
Here you can return a const &
QList<mixxx::RgbColor> colors; | ||
QMap<int, int> hotcueColorIndices; | ||
for (int i = 0; i < rowCount(); i++) { | ||
QStandardItem* pColorItem = item(i, 0); | ||
QStandardItem* pHotcueIndexItem = item(i, 1); | ||
mixxx::RgbColor::optional_t color = mixxx::RgbColor::fromQString(pColorItem->text()); | ||
auto pHotcueIndexItem = static_cast<HotcueIndexListItem*>(item(i, 1)); |
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 the place where you may check (ASSERT) the type()
Thanks for your reviews so far @daschuer. Unfortunately, I'm still a bit split on whether subclassing QStandardItem is actually the right approach here: When data is entered it passes through |
This PR is marked as stale because it has been open 90 days with no activity. |
Make it possible to assign the same color to different hotcues by writing them as a comma-separated list into the table cell
0861564
to
8ffb21e
Compare
I'd like to propose to add this to 2.3 as it fixes a missing feature / bug highlighted by #3746 |
// If we have a non consequitive list of hotcue indexes, indexes are shifted down | ||
// due to the sorting nature of QMap. This is intended, this way we have a color for every hotcue. | ||
return ColorPalette(name, colors, hotcueColorIndices.values()); |
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 fear handling this silently results in confusion for the user. While we unfortunately don't have a "default color" we could insert into these empty positions, we should still test whether this shifting will occur and warn the user in that case.
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.
Opinions? @Holzhaus
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.
If you want to implement a warning icon/message that is displayed in the edit dialog, go ahead.
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.
How is this supposed to work? I typed2,3
, 2, 3
and 2-3
into a lineedit field, and none of them works (field became empty after pressing enter or clicking elsewhere).
Ah ok, I didn't merge this correctly. It works, but there are some issues:
|
That is indeed a bug I overlooked, thanks for finding it.
Indeed, though its a bit more difficult to implement. I'll investigate.
I agree, though that increases complexity quite a bit, I'll see if I can refactor the code and work this in afterwards. The entire feature hacks around some of Qts Model/View idioms, so either its not suited for what I'm trying to do or I don't understand Qt well enough to implement it properly. If anyone has ideas how to implement this better, please share. |
Allow hotcue index assignments to consist of a mix of regular indicies and ranges of indicies. For example "1 - 3, 5" to express the list `[1, 2, 3, 5]`.
I implemented both of your suggestions. What do you think? |
8d865d4
to
d7d7ef0
Compare
I would love for this to go into 2.3, but as I said, I'd like to polish it more, but I don't know whether I'll find time for that. I guess I should just focus creating unit tests and any other polishing is optional. |
I suggest we merge now and polish later, if you find the time. |
The list af ideas to make it more intuitive, was just a brainstorming of alternative. Any improvement is welcome. If a test looks ugly it is ok. Just a ugly test is better then no test. I don't think it is worth the effort to refactor the functions out. That can be done if it is needed. If you think you are ready here, just remove the draft state and we can merge. |
Thanks, I'll create some unit tests and then we can merge. If I won't find time today, I'll try to next week. |
Thank you. |
I moved the free functions and constants into their own file and wrote some unit tests. 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.
Thank you, works well!
return QStandardItem::UserType; | ||
}; | ||
|
||
const QList<int>& getHotcueIndexList() const { |
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.
const QList<int>& getHotcueIndexList() const { | |
const QList<int>& getHotcueIndexList() const { |
QList is implicitly shared, should we really return a const reference here?
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.
Good question. My guess was that explicitly constructing a QList with that reference at the call site when needed should still be pretty fast because of implicit sharing.
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 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.
Yes, references should be always const, except in a locals scope like fool[i].bar() and similar.
@Holzhaus thanks for the review. I addressed all but one of your suggestions. |
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.
Thank you, LGTM.
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.
Ah, I just noticed we lost the mixxx namespace for rangelist.
variables of pointers should be prefixed with `p`
enable detection of list containing duplicates
a1cf8ad
to
cd95da5
Compare
Thanks, I went back changed that commit and rebased the rest. Should be fine now. |
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.
LGTM, thanks.
documents feature introduced in mixxxdj/mixxx#2902
See Zulip Topic for Context
The current commit is broken and I'm only pushing it like this because I need some help implementing it.
I had implemented an approach previously that just parses the comma separated list using a regex using
a simple pure function but that led to a bunch of duplicated code later. So I instead decided to subclass
QStandardItem and parse the data in there. However, this is where I kinda got stuck. First of all because
I was unable to find answers to some questions in the Qt docs and second of all because I'm not familiar
enough with C++ to know whether my solution could even work.