PDA

View Full Version : Changing the mouse button which selects items



Rikonator
7th August 2011, 18:32
I'm trying to create a level editor with re-implemented QTableWidget and QTableWidgetItem.

The thing is, I want to implement the mouse events such that the Middle Mouse Button corresponds to selection instead of the Left Mouse Button (so that the left mouse button only places the tiles). I want to do this with a ContiguousSelection Selection Mode.

I really haven't been able to figure this out. I know in my re-implementations of mousePressEvent and mouseMoveEvent I can setSelection (even with this approach, I dunno how to set the QRect for a single item selection), but I want to know if there is a better way.

Thanks for your help!

Talei
7th August 2011, 20:40
If I understand You correctly why not to check in reimp. mouseEvent what mouse key was pressed and act accordingly?
I.e.:

void myTableView::mouseReleaseEvent(QMouseEvent *e)
{
if( e->button() == Qt::LeftButton )
doSelection();
}
Or use setSelectionModel() and subclass QItemSelectionModel accordingly to above (in that case ignore mouse event in subclassed TableView and do selection in SelectionModel).

Rikonator
8th August 2011, 14:58
Thanks for your reply!

So, if I do something like this:



void mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::MidButton)
{
doSelection();
setRectStartPoint( event->pos() );
}
}

void mouseReleaseEvent(QMouseEvent *event)
{
if(event->buttons() & (Qt::LeftButton|Qt::RightButton) )//This is to check that both Left & Right
{ //Were released. Or so I understand
setTileOnTop( indexAt( event->pos() ) ); //from the documentation. Please tell
} //if I'm wrong
else if(event->button() == Qt::LeftButton)
{
setTile( indexAt( event->pos() ) );
}
else if(event->button() == Qt::RightButton)
{
removeTile( indexAt( event->pos() ) );
}
}

void mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::MidButton)
{
doSelectionOfRect( event->pos() );
}
else if(event->buttons() &Qt::LeftButton)
{
setTile( indexAx( event->pos() ) );
}
else if(event->buttons() & Qt::RightButton)
{
removeTile( indexAt( event->pos() ) );
}
}


Will it work? Will I only do the selection with MidButton and nothing else?

Because if it will, then my problem is solved.

Talei
8th August 2011, 18:31
That should (probably because I didn't run Your code) do the trick.
Basically as long as You don't pass event to default imp. i.e. QView::mouseReleaseEvent( event ); then selection on mouse pressEvent don't occure. In Your case (above code) You check if it is middle button so It should be ok.

Rikonator
9th August 2011, 18:36
It worked, thanks for your help!

I have another question about my Level Editor, but it does not relate to the mouse-selection issue. I dunno if I can ask it here or if I'll have to make an entirely new topic.

The issue is about copying and pasting using the QClipboard. In my editor, each Tile (re-implemented QTableWidgetItem) has a QImage for the tile image and an unsigned long for the tile's map number.

What I want is, when my Level (re-implemented QTableWidget) has its copy slot called, it copies both the image and the code to the clipboard, for each tile in the selection range. And when paste is called, it puts the copied Qimage and unsigned long for each tile, in the correct tile.

Now, I know absolutely nothing about the specifics of clipboard and QMimeData. And I dunno if something like this would work for each tile;



void copy()
{
...
//For each tile t in the selection range
QMimeData *data = new QMimeData;

//The following is most probably wrong, since I don't think I can set both text
//data and image data for the same QMimeData...

data->setImageData( t->image() );
data->setText( QString::number( t->mapNumber(), 16 ).toUpper() ) );
QApplication::clipboard()->setMimeData( data );
...
}

void PasteCommand::redo()
{
...
//For each tile t in the selection range
QMimeData *data = QApplication::clipboard()->mimeData();

//Again, the inclusion of two different types of data in the same QMimeData
//is most probably wrong...

if( data->hasImage() )
t->setImage( data->imageData() );
if( data->hasText() )
t->setMapNum( numberFromText( data->text() ) );

...
}


I really have no clue on how to go about doing this.

I had an idea to copy only the map numbers to the clipboard, and then include the images corresponding to the number from my tile boxes (they hold the tiles imported from the tile sheets) when paste is called, but the code to get the image for each map number would be impractical. Furthermore, I allow the editor to place one type of tile on top of the other, creating a new tile with a new number. So, if I encounter such a tile, I'll first have to separate the number and get individual tiles and then set one on top of the other again.

I can always not include copy() and paste() functionality since I'm the only one using the editor, but I guess I shouldn't do things by half standards. And besides, it'll be a good learning experience.

Thanks for your help! And please tell me if I should make a new topic for this question.