-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
SlicerT UI update #7453
SlicerT UI update #7453
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,15 +25,16 @@ | |
#include "SlicerTView.h" | ||
|
||
#include <QDropEvent> | ||
#include <QFileInfo> | ||
#include <qpixmap.h> | ||
#include <qpushbutton.h> | ||
|
||
#include "Clipboard.h" | ||
#include "DataFile.h" | ||
#include "Engine.h" | ||
#include "InstrumentTrack.h" | ||
#include "InstrumentView.h" | ||
#include "PixmapButton.h" | ||
#include "SampleLoader.h" | ||
#include "SlicerT.h" | ||
#include "Song.h" | ||
#include "StringPairDrag.h" | ||
#include "Track.h" | ||
#include "embed.h" | ||
|
@@ -43,57 +44,63 @@ namespace lmms { | |
namespace gui { | ||
|
||
SlicerTView::SlicerTView(SlicerT* instrument, QWidget* parent) | ||
: InstrumentViewFixedSize(instrument, parent) | ||
: InstrumentView(instrument, parent) | ||
, m_slicerTParent(instrument) | ||
, m_fullLogo(PLUGIN_NAME::getIconPixmap("full_logo")) | ||
, m_background(PLUGIN_NAME::getIconPixmap("toolbox")) | ||
{ | ||
// window settings | ||
setAcceptDrops(true); | ||
setAutoFillBackground(true); | ||
|
||
// render background | ||
QPalette pal; | ||
pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); | ||
setPalette(pal); | ||
setMaximumSize(QSize(10000, 10000)); | ||
setMinimumSize(QSize(516, 400)); | ||
setResizable(true); | ||
|
||
m_wf = new SlicerTWaveform(248, 128, instrument, this); | ||
m_wf->move(2, 6); | ||
m_wf->move(0, s_topBarHeight); | ||
|
||
m_snapSetting = new ComboBox(this, tr("Slice snap")); | ||
m_snapSetting->setGeometry(185, 200, 55, ComboBox::DEFAULT_HEIGHT); | ||
m_snapSetting->setToolTip(tr("Set slice snapping for detection")); | ||
m_snapSetting->setModel(&m_slicerTParent->m_sliceSnap); | ||
|
||
m_syncToggle = new LedCheckBox("Sync", this, tr("SyncToggle"), LedCheckBox::LedColor::Green); | ||
m_syncToggle->move(135, 187); | ||
m_syncToggle = new PixmapButton(this, tr("Sync sample")); | ||
m_syncToggle->setActiveGraphic(PLUGIN_NAME::getIconPixmap("sync_active")); | ||
m_syncToggle->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("sync_inactive")); | ||
m_syncToggle->setCheckable(true); | ||
m_syncToggle->setToolTip(tr("Enable BPM sync")); | ||
m_syncToggle->setModel(&m_slicerTParent->m_enableSync); | ||
|
||
m_bpmBox = new LcdSpinBox(3, "19purple", this); | ||
m_bpmBox->move(130, 201); | ||
m_bpmBox->setToolTip(tr("Original sample BPM")); | ||
m_bpmBox->setModel(&m_slicerTParent->m_originalBPM); | ||
|
||
m_noteThresholdKnob = createStyledKnob(); | ||
m_noteThresholdKnob->move(10, 197); | ||
m_noteThresholdKnob->setToolTip(tr("Threshold used for slicing")); | ||
m_noteThresholdKnob->setModel(&m_slicerTParent->m_noteThreshold); | ||
|
||
m_fadeOutKnob = createStyledKnob(); | ||
m_fadeOutKnob->move(64, 197); | ||
m_fadeOutKnob->setToolTip(tr("Fade Out per note in milliseconds")); | ||
m_fadeOutKnob->setModel(&m_slicerTParent->m_fadeOutFrames); | ||
|
||
m_midiExportButton = new QPushButton(this); | ||
m_midiExportButton->move(199, 150); | ||
m_midiExportButton->setIcon(PLUGIN_NAME::getIconPixmap("copy_midi")); | ||
m_midiExportButton->setToolTip(tr("Copy midi pattern to clipboard")); | ||
connect(m_midiExportButton, &PixmapButton::clicked, this, &SlicerTView::exportMidi); | ||
|
||
m_folderButton = new PixmapButton(this); | ||
m_folderButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("folder_icon")); | ||
m_folderButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("folder_icon")); | ||
m_folderButton->setToolTip(tr("Open sample selector")); | ||
connect(m_folderButton, &PixmapButton::clicked, this, &SlicerTView::openFiles); | ||
|
||
m_resetButton = new QPushButton(this); | ||
m_resetButton->move(18, 150); | ||
m_resetButton->setIcon(PLUGIN_NAME::getIconPixmap("reset_slices")); | ||
m_resetButton->setToolTip(tr("Reset Slices")); | ||
m_resetButton->setToolTip(tr("Reset slices")); | ||
connect(m_resetButton, &PixmapButton::clicked, m_slicerTParent, &SlicerT::updateSlices); | ||
|
||
update(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once you switch to layouts, you might not even need this update call |
||
} | ||
|
||
Knob* SlicerTView::createStyledKnob() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be easier to add another knob style in Knob.cpp and use that here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How would that be any easier? Even if it were, the knob styles are supposed to be for general use, not something specific like knobs used by only one plugin. |
||
|
@@ -178,16 +185,101 @@ void SlicerTView::dropEvent(QDropEvent* de) | |
void SlicerTView::paintEvent(QPaintEvent* pe) | ||
{ | ||
QPainter brush(this); | ||
brush.setPen(QColor(255, 255, 255)); | ||
brush.setFont(QFont(brush.font().family(), 7, -1, false)); | ||
|
||
brush.drawText(8, s_topTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Reset")); | ||
brush.drawText(188, s_topTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Midi")); | ||
int boxTopY = height() - s_bottomBoxHeight; | ||
|
||
// --- backgrounds and limiters | ||
brush.drawPixmap(QRect(0, boxTopY, s_leftBoxWidth, s_bottomBoxHeight), m_background); // left | ||
brush.fillRect( | ||
QRect(s_leftBoxWidth, boxTopY, width() - s_leftBoxWidth, s_bottomBoxHeight), QColor(23, 26, 31)); // right | ||
brush.fillRect(QRect(0, 0, width(), s_topBarHeight), QColor(20, 23, 27)); // top | ||
|
||
// top bar dividers | ||
brush.setPen(QColor(56, 58, 60)); | ||
brush.drawLine(0, s_topBarHeight - 1, width(), s_topBarHeight - 1); | ||
brush.drawLine(0, 0, width(), 0); | ||
|
||
// sample name divider | ||
brush.setPen(QColor(56, 58, 60)); | ||
brush.drawLine(0, boxTopY, width(), boxTopY); | ||
|
||
// boxes divider | ||
brush.setPen(QColor(56, 24, 94)); | ||
brush.drawLine(s_leftBoxWidth, boxTopY, s_leftBoxWidth, height()); | ||
|
||
// --- top bar | ||
brush.drawPixmap( | ||
QRect(10, (s_topBarHeight - m_fullLogo.height()) / 2, m_fullLogo.width(), m_fullLogo.height()), m_fullLogo); | ||
|
||
int y1_text = m_y1 + 27; | ||
|
||
// --- left box | ||
brush.setPen(QColor(255, 255, 255)); | ||
brush.drawText(s_x1 - 25, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Threshold")); | ||
brush.drawText(s_x2 - 25, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Fade Out")); | ||
brush.drawText(s_x3 - 25, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Reset")); | ||
brush.drawText(s_x4 - 8, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Midi")); | ||
brush.drawText(s_x5 - 16, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("BPM")); | ||
brush.drawText(s_x6 - 8, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Snap")); | ||
|
||
int kor = 15; // knob outer radius | ||
int kir = 9; // knob inner radius | ||
|
||
// draw knob backgrounds | ||
brush.setRenderHint(QPainter::Antialiasing); | ||
|
||
// draw outer radius 2 times to make smooth | ||
brush.setPen(QPen(QColor(159, 124, 223, 100), 4)); | ||
brush.drawArc(QRect(s_x1 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); | ||
brush.drawArc(QRect(s_x2 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); | ||
|
||
brush.setPen(QPen(QColor(159, 124, 223, 255), 2)); | ||
brush.drawArc(QRect(s_x1 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); | ||
brush.drawArc(QRect(s_x2 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); | ||
|
||
// inner knob circle | ||
brush.setBrush(QColor(106, 90, 138)); | ||
brush.setPen(QColor(0, 0, 0, 0)); | ||
brush.drawEllipse(QPoint(s_x1, m_y1 + 15), kir, kir); | ||
brush.drawEllipse(QPoint(s_x2, m_y1 + 15), kir, kir); | ||
|
||
// current sample bar | ||
brush.fillRect(QRect(0, boxTopY - s_sampleBoxHeight, width(), s_sampleBoxHeight), QColor(5, 5, 5)); | ||
|
||
brush.setPen(QColor(56, 58, 60)); | ||
brush.drawLine(width() - 24, boxTopY - s_sampleBoxHeight, width() - 24, boxTopY); | ||
|
||
brush.setPen(QColor(255, 255, 255, 180)); | ||
brush.setFont(QFont(brush.font().family(), 8, -1, false)); | ||
QString sampleName = m_slicerTParent->getSampleName(); | ||
if (sampleName == "") { sampleName = "No sample loaded"; } | ||
|
||
brush.drawText(5, boxTopY - s_sampleBoxHeight, width(), s_sampleBoxHeight, Qt::AlignLeft, sampleName); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like lots of manual layout computations. Ideally the different components would be implemented as widgets of their own which would then be put into Qt's layouts so that they can resize dynamically. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pretty sure that using Qt's layouts would be more work and more complex. I use that many offsets to get everything to align pixel-perfectly, so even if I used layouts, I would have to add the offset in some way or another. And the move parts are honestly the simplest, the complex part is drawing the text, dividers, gradients, knobs and backgrounds. Don't really see how that could be implemented any differently. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would definitively be possible with the right resize policies and margins. Layouts are used exactly for situations like these so that complex layout calculations do not have to be reimplemented over and over again. Using widgets in layouts might also lead to more reusable components. However, I guess it's nothing for now. |
||
} | ||
|
||
void SlicerTView::resizeEvent(QResizeEvent* re) | ||
{ | ||
m_y1 = height() - s_bottomBoxOffset; | ||
|
||
// left box | ||
m_noteThresholdKnob->move(s_x1 - 25, m_y1); | ||
m_fadeOutKnob->move(s_x2 - 25, m_y1); | ||
|
||
m_resetButton->move(s_x3 - 15, m_y1 + 3); | ||
m_midiExportButton->move(s_x4 + 2, m_y1 + 3); | ||
|
||
m_bpmBox->move(s_x5 - 13, m_y1 + 4); | ||
m_snapSetting->move(s_x6 - 8, m_y1 + 3); | ||
|
||
// right box | ||
m_syncToggle->move((width() - 100), m_y1 + 5); | ||
|
||
m_folderButton->move(width() - 20, height() - s_bottomBoxHeight - s_sampleBoxHeight + 1); | ||
michaelgregorius marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
int waveFormHeight = height() - s_bottomBoxHeight - s_topBarHeight - s_sampleBoxHeight; | ||
|
||
brush.drawText(8, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Threshold")); | ||
brush.drawText(63, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Fade Out")); | ||
brush.drawText(127, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("BPM")); | ||
brush.drawText(188, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Snap")); | ||
m_wf->resize(width(), waveFormHeight); | ||
} | ||
|
||
} // namespace gui | ||
|
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.
Michael did point this out, basically, you can use a QVBoxLayout to get the elements listed vertically, and the bottom toolbox can be wrapped in a QHBoxLayout. That way, you'll have to do little calculation.