PDA

View Full Version : DragDrop Color



prashant
7th September 2009, 12:05
I am creating a custom color picker by sub classing QFrame. There are three main functionality I would be needing.

1. A color picker
2. dragdrop color to other picker
3. right click menu

There won't be any problem in 1 and 3. How ever for 2 there are:

When you drop color to target, a menu appears with two options: swap & replace
If user select "swap", it should swap the colors of source and target
If user select "replace", it should replace the color of target with source.

drag & drop is having some problem:


void DragWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasColor()) {
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
}
else {
event->acceptProposedAction();
}
}
else {
event->ignore();
}
}

void DragWidget::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasColor()) {
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
}
else {
event->acceptProposedAction();
}
}
else {
event->ignore();
}

}

void DragWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasColor()) {
myColor = qvariant_cast<QColor>(event->mimeData()->colorData());

if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else {
event->ignore();
}
}


void DragWidget::mousePressEvent(QMouseEvent *event)
{
QMimeData *mimeData = new QMimeData;
mimeData->setColorData(QVariant(myColor));

QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
}

wysota
7th September 2009, 13:02
What problem is the drag & drop having?

http://catb.org/~esr/faqs/smart-questions.html

prashant
7th September 2009, 13:10
Nothing is happening.

wysota
7th September 2009, 15:30
Too bad.

http://catb.org/~esr/faqs/smart-questions.html

prashant
7th September 2009, 15:52
Got it.....

in "mousePressEvent" I have to add this:


Qt::DropAction dropAction = drag->exec(Qt::CopyAction,Qt::CopyAction);

wysota
7th September 2009, 15:59
Good for you.
http://catb.org/~esr/faqs/smart-questions.html

prashant
7th September 2009, 18:44
It seems there is something wrong here and it's creating another problem.



void DragWidget::mousePressEvent(QMouseEvent *event)
{

// Pack mime data
QMimeData *mimeData = new QMimeData;
mimeData->setColorData(QVariant(myColor));

// Prepare cursor image
QPixmap pixmap(this->size());
QPainter painter;
painter.begin(&pixmap);
painter.fillRect(pixmap.rect(), myColor);
painter.end();

// We establish QDrag object, draw cursor and embed data
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(event->pos());

sourcePicker = drag->source();

// We send it
drag->exec(Qt::CopyAction);


}

void DragWidget::mouseReleaseEvent(QMouseEvent *event)
{

if (event->type() == QEvent::MouseButtonRelease){
QColor color = QColorDialog::getColor(QColor(myColor), this);
if (color.isValid()) {
setPalette(QPalette(color));
setAutoFillBackground(true);
myColor = color;
}
}
else
event->ignore();
}


With this line in "mousePressEvent":


drag->exec(Qt::CopyAction);

drag n drop is working fine but "mouseReleaseEvent" is not getting called. If I comment this
line "releaseEvent" is getting called.

Secondly, I have to add the functionality to make this widget as color picker also, I added color picking dialog in "releaseEvent". This won't work as expected because the "dropping"
event is actually a "releaseEvent" and as you drop on target picker dialog shows up.

A hack to this problem is to show color dialog when there is "down" and "up" on same widget. Using a bool var, you set state true, when there is a mouse down and in mouse up
event, check the state of this var, if it's true, show color dialog and set it again to false.
Am I right here or there is a better way of doing this?

How do I setup a menu, which appears at dropping? "swap color" or "replace color"

Prashant

wysota
7th September 2009, 19:53
What's the point of checking the event type in mouseReleaseEvent()?

Drop event is a drop event and not mouse release event. Here is an extract from my QwwTwoColorIndicator:

void QwwTwoColorIndicator::mouseMoveEvent(QMouseEvent *ev) {
Q_D(QwwTwoColorIndicator);
if (d->fgP || d->bgP) {
if (dragEnabled() && (ev->pos() - d->pressPos).manhattanLength() >= QApplication::startDragDistance()) {
QColor col = d->fgP ? fgColor() : bgColor();
ColorDrag *drag = new ColorDrag(this, col, col.name());
drag->exec();
d->fgP = d->bgP = false;
update();
}
} else if (testAttribute(Qt::WA_Hover)) update();
QWidget::mouseMoveEvent(ev);
}

void QwwTwoColorIndicator::mouseReleaseEvent(QMouseEven t *ev) {
Q_D(QwwTwoColorIndicator);
if (ev->button() == Qt::LeftButton) {
if (d->fgP && d->foregroundRect().contains(ev->pos())) {
emit fgClicked();
if (d->active) {
#if QT_VERSION >= 0x040500
QColor c = QColorDialog::getColor(d->fg, this, tr("Choose foreground color"), QColorDialog::ShowAlphaChannel);
#else
QColor c = QColorDialog::getColor(d->fg, this);
#endif
if (c.isValid()) {
setFgColor(c);
}
}
} else if (d->bgP && d->backgroundRect().contains(ev->pos())) {
emit bgClicked();
if (d->active) {
#if QT_VERSION >= 0x040500
QColor c = QColorDialog::getColor(d->bg, this, tr("Choose background color"), QColorDialog::ShowAlphaChannel);
#else
QColor c = QColorDialog::getColor(d->bg, this);
#endif
if (c.isValid()) {
setBgColor(c);
}
}
}
d->fgP = d->bgP = false;
update();
}
}

void QwwTwoColorIndicator::dropEvent(QDropEvent *ev) {
Q_D(QwwTwoColorIndicator);
QColor col;
if (ev->mimeData()->hasColor())
col = qvariant_cast<QColor>(ev->mimeData()->colorData());
else
col.setNamedColor(ev->mimeData()->text());
if (d->foregroundRect().contains(ev->pos())) {
setFgColor(col);
} else if (d->backgroundRect().contains(ev->pos())) {
setBgColor(col);
}
ev->setDropAction(Qt::CopyAction);
}
There is also dragEnterEvent and dragMoveEvent implemented.