Sorry if this is a repeat, but I'm trying to figure out the implementation of SoRayPickAction in Open Inventor. I'm trying to implement it so that it will, when the mouse is clicked, select a particular node so then I can translate, rotate, etc. I have three nodes: desk, lamp, and frame (picture frame). However, I don't think that my code is at all right. I also have various methods such a MouseButtonCallback (which will check if the mouse is clicked and then use a navigator) and MouseMoveCallback (same idea). So here's the code that I have, but do you have any suggestions? Right now, well, it doesn't do anything.
SbViewportRegion viewport(400,300);
SoRayPickAction m(viewport);
m.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
m.apply(callback_node);
const SoPickedPoint *mpp = m.getPickedPoint();
if(mpp != NULL) {
std::cout << "test" << std::endl;
}
Might you also know of an action in OpenInventor that can "place" a node in the scene, i.e. place the lamp on top of the desk, frame on the wall, etc. Is it with paths? I don't even know what I'm looking for, unfortunately. Thanks so much for your help!!
Edit: How does this look?
SoSeparator *desk2;
SoSeparator *lamp2;
SoSeparator *pic_frame2;
SoSeparator *picked;
void MouseButtonCallback(void* data, SoEventCallback* node)
{
SoHandleEventAction* action = node->getAction();
const SoMouseButtonEvent* event = static_cast<const SoMouseButtonEvent*>(action- >getEvent());
Navigator* nav = static_cast<Navigator*>(data);
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
nav->OnMouseDown(event, action);
else
nav->OnMouseUp(event, action);
const SbViewportRegion & viewportRegion = action->getViewportRegion();
SoRayPickAction pickAction(viewportRegion);
SbVec2s mousePos = event->getPosition(viewportRegion);
pickAction.setPoint(mousePos);
pickAction.setPickAll(TRUE);
pickAction.setRadius(2.0F);
pickAction.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
pickAction.apply(node);
const SoPickedPoint *mpp = pickAction.getPickedPoint();
if(mpp != NULL) {
SoPath *path = mpp->getPath();
if(desk2 != NULL && path->containsNode(desk2))
{ //but this doesn't respond with cout when I try to test it :(
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
*picked = *desk2;
}
else if(lamp2 != NULL && path->containsNode(lamp2))
{
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
*picked = *lamp2;
}
else if(pic_frame2 != NULL && path->containsNode(pic_frame2))
{
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
*picked = *pic_frame2;
}
action->setHandled();
}
void MouseMoveCallback(void* data, SoEventCallback* node)
{
SoHandleEventAction* action = node->getAction();
const SoLocation2Event* event = static_cast<const SoLocation2Event*>(action->getEvent());
Navigator* nav = static_cast<Navigator*>(data);
nav->OnMouseMove(event, action);
const SbViewportRegion & viewportRegion = action->getViewportRegion();
SoRayPickAction pickAction(viewportRegion);
SbVec2s mousePos = event->getPosition(viewportRegion);
pickAction.setPoint(mousePos);
pickAction.setPickAll(TRUE);
pickAction.setRadius(2.0F);
pickAction.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
pickAction.apply(node);
const SoPickedPoint *mpp = pickAction.getPickedPoint();
if(mpp != NULL) {
SoPath *path = mpp->getPath();
if(desk2 != NULL && path->containsNode(desk2))
{
*picked = *desk2; //can't remember how to set pointers, will figure that out
}
else if(lamp2 != NULL && path->containsNode(lamp2))
{
*picked = *lamp2;
}
else if(pic_frame2 != NULL && path->containsNode(pic_frame2))
{
*picked = *pic_frame2;
}
}
action->setHandled();
}
(part of main method)
//desk
SoTransform *desk_transform = new SoTransform;
desk_transform->translation.setValue(SbVec3f(380,340,330));
SoSeparator* desk2 = new SoSeparator();
desk2->addChild(desk_transform);
desk2->addChild(desk);
root->addChild(desk2);
SoTransformerManip* picked_transform = new SoTransformerManip();
picked_transform->translation.setValue(SbVec3f(200,340,330));
SoSeparator* pick2 = new SoSeparator();
pick2->addChild(picked_transform);
pick2->addChild(picked);
root->addChild(pick2);
std::auto_ptr<btCollisionShape> picked_shape(new btBoxShape(btVector3(10.0f, 10.0f, 10.0f)));
CollisionEngine* picked_collision = new CollisionEngine(collision_world.get(), picked_shape.get());
picked_collision->translation_in.connectFrom(&picked_transform->translation);
picked_collision->rotation_in.connectFrom(&picked_transform->rotation);
picked_transform->translation.connectFrom(&picked_collision->translation_out);
You have the picked point. You then get an SoPath as you guessed. Then see if the path contains a node you want to do something with.
SbViewportRegion viewport(400,300);
SoRayPickAction m(viewport);
m.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
m.apply(callback_node);
const SoPickedPoint *mpp = m.getPickedPoint();
if(mpp != NULL) {
std::cout << "test" << std::endl;
SoPath * path = pickedPoint->getPath();
if (deskSeparator != NULL && path->containsNode(deskSeparator)
{
}
else if (lampSeparator != NULL && path->containsNode(lampSeparator)
{
}
else if (radomeSeparator != NULL && path->containsNode(radomeSeparator)
{
if ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON2 )
|| ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON1 ) && event->wasShiftDown() ) )
{
modelPointMoving = true;
const SoDetail * detail = modelPickedPoint->getDetail( 0 );
int face = -1;
if ( detail && detail->isOfType( SoFaceDetail::getClassTypeId() ) )
{
const SoFaceDetail * faceDetail = static_cast<const SoFaceDetail *>( detail );
face = faceDetail->getFaceIndex();
}
updateStatusBar( face, point.getValue(), normal.getValue() );
graphicModel.postNote( pickedPoint );
break;
}
else if ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON1 ) )
{
}
else if ( SoMouseButtonEvent::isButtonReleaseEvent( event, SoMouseButtonEvent::BUTTON1 ) )
{
}
}
}
You'll eventually want to connect the pick ray to the mouse position sort of like this:
// Set an 2-pixel wide region around the pixel.
SbVec2s mousePosition = event->getPosition( viewportRegion );
pickAction.setPoint( mousePosition );
pickAction.setPickAll( TRUE );
pickAction.setRadius( 2.0F );
This is done before you .apply() the pick action of course.
I guess my code is a mixture of yours and mine but I think it should give you a start. Also, this is sitting inside a function to process mouse events:
void
RenderWindow::mouseEvent( void *, SoEventCallback * eventCallback )
{
const SoEvent *event = eventCallback->getEvent();
if ( ! event )
{
qDebug() << " ** Error in mousePressCallback: Event not found.";
return;
}
//SoType eventType = event->getTypeId();
//SbName eventTypeName = eventType.getName();
//const char * eventTypeString = eventTypeName.getString();
SoHandleEventAction * action = eventCallback->getAction();
const SbViewportRegion & viewportRegion = action->getViewportRegion();
SoRayPickAction pickAction( viewportRegion );
Up in main or a setup routine I register the mouse event (for both click action and location (moving the mouse over the viewport):
// Add a mouse event callback to catch mouse button presses.
SoEventCallback * mouseEventCallback = new SoEventCallback();
mouseEventCallback->setName( "MOUSE_EVENT_CALLBACK" );
mouseEventCallback->addEventCallback( SoMouseButtonEvent::getClassTypeId(), &::mouseEvent, static_cast<void *>( this ) );
// Add a mouse event callback to catch mouse motion.
mouseEventCallback->addEventCallback( SoLocation2Event::getClassTypeId(), &::mouseEvent, static_cast<void *>( this ) );
rootSeparator->addChild( mouseEventCallback );
Now that I look at it I wrote the chunks in reverse order ;-). Sorry.
Good Luck
Related
I've been following Kamran Bigdely-Shamloo's article on how to get positional information from the HTC Vive and it has worked well so far. My next step was to "listen" to button presses. I've read the documentation and it says here that all I need to do is query IVRSystem::GetControllerStateand it'll return a
"struct with the current state of the controller"
This struct however always contains variables that have the 0 value. The following function is called in a while (true) loop from the main function.
bool CMainApplication::HandleInput()
{
SDL_Event sdlEvent;
bool bRet = false;
while ( SDL_PollEvent( &sdlEvent ) != 0 )
{
if ( sdlEvent.type == SDL_QUIT )
{
bRet = true;
}
else if ( sdlEvent.type == SDL_KEYDOWN )
{
if ( sdlEvent.key.keysym.sym == SDLK_ESCAPE
|| sdlEvent.key.keysym.sym == SDLK_q )
{
bRet = true;
}
if( sdlEvent.key.keysym.sym == SDLK_c )
{
m_bShowCubes = !m_bShowCubes;
}
}
}
// Process SteamVR events
// Periodically returns an event of type 404 ("VREvent_SceneApplicationChanged = 404, // data is process - The App actually drawing the scene changed (usually to or from the compositor)"
vr::VREvent_t event;
vr::VREvent_Controller_t controllerEvent;
std::chrono::milliseconds ms4;
while( m_pHMD->PollNextEvent( &event, sizeof( event ) ) )
{
ms4 = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
);
ProcessVREvent( &event);
printPositionalData(&event, ms4);
}
vr::VRControllerState_t state;
// Check every device attached, usually it's four devices
// Second if statement is never reached
for (int i = 0; i < 1000; i++) {
if (m_pHMD->GetControllerState(i, &state, sizeof(state))) {
dprintf("%d", i);
if (state.ulButtonPressed != 0 || state.unPacketNum != 0 || state.ulButtonTouched != 0) {
dprintf("Some action?");
}
}
}
dprintf("\n");
// Process SteamVR action state
// UpdateActionState is called each frame to update the state of the actions themselves. The application
// controls which action sets are active with the provided array of VRActiveActionSet_t structs.
vr::VRActiveActionSet_t actionSet = { 0 };
actionSet.ulActionSet = m_actionsetDemo;
vr::VRInput()->UpdateActionState( &actionSet, sizeof(actionSet), 1 );
m_bShowCubes = !GetDigitalActionState( m_actionHideCubes );
vr::VRInputValueHandle_t ulHapticDevice;
if ( GetDigitalActionRisingEdge( m_actionTriggerHaptic, &ulHapticDevice ) )
{
if ( ulHapticDevice == m_rHand[Left].m_source )
{
vr::VRInput()->TriggerHapticVibrationAction( m_rHand[Left].m_actionHaptic, 0, 1, 4.f, 1.0f, vr::k_ulInvalidInputValueHandle );
}
if ( ulHapticDevice == m_rHand[Right].m_source )
{
vr::VRInput()->TriggerHapticVibrationAction( m_rHand[Right].m_actionHaptic, 0, 1, 4.f, 1.0f, vr::k_ulInvalidInputValueHandle );
}
}
vr::InputAnalogActionData_t analogData;
if ( vr::VRInput()->GetAnalogActionData( m_actionAnalongInput, &analogData, sizeof( analogData ), vr::k_ulInvalidInputValueHandle ) == vr::VRInputError_None && analogData.bActive )
{
m_vAnalogValue[0] = analogData.x;
m_vAnalogValue[1] = analogData.y;
}
m_rHand[Left].m_bShowController = true;
m_rHand[Right].m_bShowController = true;
vr::VRInputValueHandle_t ulHideDevice;
if ( GetDigitalActionState( m_actionHideThisController, &ulHideDevice ) )
{
if ( ulHideDevice == m_rHand[Left].m_source )
{
m_rHand[Left].m_bShowController = false;
}
if ( ulHideDevice == m_rHand[Right].m_source )
{
m_rHand[Right].m_bShowController = false;
}
}
for ( EHand eHand = Left; eHand <= Right; ((int&)eHand)++ )
{
vr::InputPoseActionData_t poseData;
if ( vr::VRInput()->GetPoseActionData( m_rHand[eHand].m_actionPose, vr::TrackingUniverseStanding, 0, &poseData, sizeof( poseData ), vr::k_ulInvalidInputValueHandle ) != vr::VRInputError_None
|| !poseData.bActive || !poseData.pose.bPoseIsValid )
{
m_rHand[eHand].m_bShowController = false;
}
else
{
m_rHand[eHand].m_rmat4Pose = ConvertSteamVRMatrixToMatrix4( poseData.pose.mDeviceToAbsoluteTracking );
vr::InputOriginInfo_t originInfo;
if ( vr::VRInput()->GetOriginTrackedDeviceInfo( poseData.activeOrigin, &originInfo, sizeof( originInfo ) ) == vr::VRInputError_None
&& originInfo.trackedDeviceIndex != vr::k_unTrackedDeviceIndexInvalid )
{
std::string sRenderModelName = GetTrackedDeviceString( originInfo.trackedDeviceIndex, vr::Prop_RenderModelName_String );
if ( sRenderModelName != m_rHand[eHand].m_sRenderModelName )
{
m_rHand[eHand].m_pRenderModel = FindOrLoadRenderModel( sRenderModelName.c_str() );
m_rHand[eHand].m_sRenderModelName = sRenderModelName;
}
}
}
}
return bRet;
m_pHMD is initalized as follows:
vr::IVRSystem *m_pHMD;
....
m_pHMD = vr::VR_Init( &eError, vr::VRApplication_Background );
I must be doing something wrong because in the following snippet, the if statement is passed only for the first four iterations, which should be a controller, the vive tracker, the headset and the lighthouses. This tells me that I am able to access these states, but I am somehow not able to read the information.
for (int i = 0; i < 1000; i++) {
if (m_pHMD->GetControllerState(i, &state, sizeof(state))) {
dprintf("%d", i);
if (state.ulButtonPressed != 0 || state.unPacketNum != 0 || state.ulButtonTouched != 0) {
dprintf("Some action?");
}
}
I can't imagine its a bug, so my guess is that my configuration is faulty, or I'm doing the wrong query.
Any help is greatly appreciated!
Apparently I was making two mistakes.
Mistake #1 was that I was using the wrong sample file. I used hellovr_opengl from the OpenVr sample folder, but instead hellovr_dx12 was the working solution. It must have a different kind of configration as well, since I copied a function which was working into the hellovr_opengl project and there, it did not work! Then I copied the functions I added to the hellovr_dx12 project and was able to get the controller states of the Vive controller.
However, I wanted to get the states of the Vive Tracker, which didn't work. After some googling I found out about an issue with the current SteamVR driver, so I reverted it back to a beta hoftix, which solved the Vive Tracker issue for me.
You have to call;
vr::VRInput()->SetActionManifestPath
I am using observer design pattern and updating the GUI from model which is working great. For each operation or function call from GUI, the model sends a series of updates at various stages to notify the GUI accordingly to do updates. This resulted in rather big if-else block in UpdateView() method. Is this how it should be or can this improved by applying another design pattern? I have split message from each function to a different handler which helps quite a bit. Note: the code is not compiled below but i took the essence of what I am doing. I have studied design patterns for a while but I am implementing it for the first time.
class Msg
{
int operation;
int opCode;
}
// in the model class
Device::Calibrate()
{
Msg msg;
msg.operation = CALIBRATE;
// ..... do some work -----
msg.opCode = DEPENDENT_MODULE_NOT_LOADED;
Notify( msg )
// .... do some work ------
msg.opCode = HARDWARE_MODULE_1_FAILED
Notify( msg )
// .... do some work ------
msg.opCode = CALIBRATION_IN_PROGRESS
Notify( msg )
// --- so on -----
}
void CMainDlg::UpdateView(const Msg * msg )
{
if( msg->operation == VERIFY ) // all message from Verify() button pressed
OnVerify( msg );
if( msg->operation == CALIBRATE ) // all messages from Calibrate button pressed
OnCalibrate();
}
void CMainDlg::OnCalibrate(const Msg * msg)
{
if (msg->opCode == DEPENDENT_MODULE_NOT_LOADED)
{
}
else if msg->opCode == HARDWARE_MODULE_1_FAILED)
{
}
else if msg->opCode == HARDWARE_MODULE_2_FAILED)
{
}
else if msg->opCode == CALIBRATION_IN_PROGRESS)
{
}
else if msg->opCode == OUTPUT_FILE_COULD_NOT_BE_CREATED)
{
}
else if msg->opCode == CALIBRATION_FAILED)
{
}
else if msg->opCode == CALIBRATION_PASSED)
{
}
}
In my code I would like to destroy one of two contacted bodies. Within the beginContact the following method in CCPhysicsSprite is called:
-(void)contactMade:(CCPhysicsSprite*)contactedSprite {
int spriteTag1 = self.tag;
int spriteTag2 = contactedSprite.tag;
if (((spriteTag1 == 3) && (spriteTag2 == 4)) || ((spriteTag1 == 4) && (spriteTag2 == 3)) {
CCPhysicsSprite* heroSprite = (CCPhysicsSprite*)[self getChildByTag:4];
b2World* world;
world->DestroyBody(heroSprite.b2Body);
heroSprite.b2Body = NULL;
[heroSprite.parent removeChild:heroSprite];
}
I get a signal SIGABRT pointing to
b2Assert(m_bodyCount > 0);
After searching on this issue. I read that the contact body has to be saved and destroyed after the timestep. How can I do this, given that I have set my contact conditions in the CCPhyscisSprite.
You can add a flag ( like : isDead ... ) to your physical object and in collision event just change that flag value to TRUE .
-(void) CollisionBegin:(b2Fixture*)target With:(b2Fixture*) source
{
if ( target->GetBody()->GetType() == b2_dynamicBody)
{
yourCustomClass *temp = (yourCustomClass *)target->GetBody()->GetUserData();
temp->isDead = true ;
}
}
Then in update function after step get all physical world's object and find that specific object by flag ( Here : isDead ) , and destroy that .
-(void) update: (ccTime) dt
{
int32 velocityIterations = 8;
int32 positionIterations = 3;
world->Step(dt, velocityIterations, positionIterations);
// remove your box2d object here , after step function
for ( b2Body *b = world->GetBodyList(); b; )
{
b2Body *baba = b->GetNext();
if ( b->GetUserData() != NULL && b->GetType() == b2_dynamicBody)
{
yourCustomClass *t = (yourCustomClass *)b->GetUserData();
if ( t->isDead )
{
world->DestroyBody(b); // remove physical body
[self removeChild:t]; // remove node from super layer
}
}
b = baba ;
}
}
I have some simple box2d bodies setup with a contact listener like so:
#import "MyContactListener.h"
MyContactListener::MyContactListener() : _contacts() {
}
MyContactListener::~MyContactListener() {
}
void MyContactListener::BeginContact(b2Contact* contact) {
// We need to copy out the data because the b2Contact passed in
// is reused.
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
_contacts.push_back(myContact);
b2Body *A = contact->GetFixtureA()->GetBody();
b2Body *B = contact->GetFixtureA()->GetBody();
NSLog(#"Collision detected!");
PLAYSOUND(COLLISION);
}
void MyContactListener::EndContact(b2Contact* contact) {
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
std::vector<MyContact>::iterator pos;
pos = std::find(_contacts.begin(), _contacts.end(), myContact);
if (pos != _contacts.end()) {
_contacts.erase(pos);
}
}
void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) {
}
void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) {
}
And I need to play a sound when two bodies have collided. However this implementation detects continuous collisions so the sound is played when the bodies are touching. My knowledge of box2d and C++ is already very limited, is there a simple way to detect a new collision without detecting continuous collisions?
You have the right basic idea, but it needs some refinement.
In your BeginContact(...) call, you have:
PLAYSOUND(COLLISION);
Instead of playing the sound here, what you should do is enqueue some other system to play the sound for this particular pair. Set the userdata tag of your bodies to the pointer to the class (or some other ID to keep track of entities). Like so:
class EntityContactListener : public ContactListener
{
private:
GameWorld* _gameWorld;
EntityContactListener() {}
typedef struct
{
Entity* entA;
Entity* entB;
} CONTACT_PAIR_T;
vector<CONTACT_PAIR_T> _contactPairs;
public:
virtual ~EntityContactListener() {}
EntityContactListener(GameWorld* gameWorld) :
_gameWorld(gameWorld)
{
_contactPairs.reserve(128);
}
void NotifyCollisions()
{
Message* msg;
MessageManager& mm = GameManager::Instance().GetMessageMgr();
for(uint32 idx = 0; idx < _contactPairs.size(); idx++)
{
Entity* entA = _contactPairs[idx].entA;
Entity* entB = _contactPairs[idx].entB;
//DebugLogCPP("Contact Notification %s<->%s",entA->ToString().c_str(),entB->ToString().c_str());
msg = mm.CreateMessage();
msg->Init(entA->GetID(), entB->GetID(), Message::MESSAGE_COLLISION);
mm.EnqueueMessge(msg, 0);
msg = mm.CreateMessage();
msg->Init(entB->GetID(), entA->GetID(), Message::MESSAGE_COLLISION);
mm.EnqueueMessge(msg, 0);
}
_contactPairs.clear();
}
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
}
// BEWARE: You may get multiple calls for the same event.
void BeginContact(b2Contact* contact)
{
Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData();
Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData();
//DebugLogCPP("Begin Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str());
if(entA->GetGroupID() == entB->GetGroupID())
{ // Can't collide if they are in the same group.
return;
}
assert(entA != NULL);
assert(entB != NULL);
for(uint32 idx = 0; idx < _contactPairs.size(); idx++)
{
if(_contactPairs[idx].entA == entA && _contactPairs[idx].entB == entB)
return;
// Not sure if this is needed...
if(_contactPairs[idx].entA == entB && _contactPairs[idx].entA == entB)
return;
}
CONTACT_PAIR_T pair;
pair.entA = entA;
pair.entB = entB;
_contactPairs.push_back(pair);
}
// BEWARE: You may get multiple calls for the same event.
void EndContact(b2Contact* contact)
{
/*
Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData();
Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData();
DebugLogCPP("End Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str());
*/
}
};
The last part of this is to NOT play the sound again for a short time even if a collision occurs. You can do this by creating a stopwatch or counting down from a fixed time on the entity update cycles.
Was this helpful?
First set a timer like this..
[self schedule:#selector(check collision:)];
and in this method
- (void)tick:(ccTime) dt
{
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext())
{
//--------------My contact Listener Start-------------------------
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin(); pos != _contactListener->_contacts.end(); ++pos)
{
MyContact contact = *pos;
// Here get your sprite and make their fixture and check...
if ((contact.fixtureA == tempballFixture && contact.fixtureB == _mainballFixture) ||
(contact.fixtureA == _mainballFixture && contact.fixtureB == tempballFixture))
{
if(mainDelegate.music_playing == TRUE)
{
[[SimpleAudioEngine sharedEngine] playEffect:#"Rock impact.mp3"];
}
//-------------collision count for update score value--------
}
}
Right now I am displaying something like /home/binary/ in QText browser. Now I want the open the folder by clicking on this text. How to do that ? Thanks in advance
Here is my sample code. I am display the result
s
bool MainWindow::displayResult(multimap<string,
string> &resultMap, string &filePath)
{
multimap::iterator iter;
bool fileStatus = false;
int noOfLocFound = 0, forAppending = 0;
QString no;
noOfLocFound = resultMap.size();
if ( noOfLocFound != 0 )
ui->textBrowser->append( "<i>File found at <b>" + no.setNum (
noOfLocFound ) + " locations");
for ( forAppending = 0,iter = resultMap.begin(); iter !=
resultMap.end(); iter++,
forAppending++ )
{
string file = iter->first;
string dir = iter->second;
if ( forAppending == 0)
filePath.append(dir);
else
filePath.append(","+dir);
QString qdir = QString::fromStdString(dir);
cout << "Display";
ui->textBrowser->append( qdir );
fileStatus = true;
}
if ( fileStatus == false )
{
ui->textBrowser->append("File not
found");
return false;
}
return true;
}
By "open the folder", do you mean, open a file dialog for the user to select something inside of the given directory?
If so, you would probably want to connect your QTextBrowser's clicked signal to a slot that looked something like:
// connect events, in MyWindow constructor, or whereever...
connect(textbrowser, SIGNAL(mousePressEvent(QMouseEvent*)), this, SLOT(openFileDialog(QMouseEvent*)));
void MyWindow::openFileDialog(QMouseEvent* event) {
Q_UNUSED(event);
QStringList files = QFileDialog::getOpenFileNames(this, "Select a file...",
textbrowser.plainText());
// do something with the files here...
}