Setting focus to a running QProcess



  • So I am having trouble figuring out a way to bring an application to the forefront for a QProcess. My application is a System Dock that allows users to drag executables from their local PC, and add it to the dock. When adding to the dock, it creates a button with the object name as the directory location of the application added.

    The thread is created in the Widget window like so:
    @
    /*
    // app button clicked (slot)
    */
    void Widget::appButtonClicked()
    {
    // get sender of the signal
    QToolButton *button = qobject_cast<QToolButton *>(sender());

    // format the exe location
    QString temp = button->objectName();
    temp = temp.replace("/", "\\\\");
    temp = "\"" + temp + "\"";
    
    // start the new process
    newProcess = new Process();
    newProcess->exeLocation = temp;
    newProcess->start();
    

    }
    @

    On the button push, I run a QProcess in a thread so that I don't freeze the GUI and allows other processes to be opened as well:
    @
    #include "process.h"

    /*
    // cc
    */
    Process::Process(QObject *parent) :
    QThread(parent)
    {
    exeLocation = "";
    }

    /*
    // class execution loop
    */
    void Process::run()
    {
    // start the proccess
    QProcess process;
    process.start(exeLocation);
    process.waitForFinished(-1);
    }
    @

    What I also am going to do is append the thread to a QList<QThread *> on creation so that I know which process's are active at all times.

    But, I am looking to change the code for button press signal to check if the application has already been opened. As in, I only want one instance of the application running at a time. If it is already running, then I want bring that process to focus / bring the screen to the front.

    Is there any that there is a way to do this in Qt, or is this going to be platform specific? I am currently developing on Windows 7.


  • Moderators

    Bringing the process to the front will be a system-specific thing, I believe.

    Also, there's no need to run your QProcesses in separate threads. You can use "QProcess:startDetached()":/doc/qt-4.8/qprocess.html#startDetached to run the process without blocking, and you can connect to the QProcess's "finished()":/doc/qt-4.8/qprocess.html#finished signal to catch when the process ends.



  • Ah, very nice. Thanks! I have just read this snipet actually that I am going to try to do using the process id:
    http://www.qtcentre.org/threads/42554-QProcess-and-focus-problem

    So I will save my QProcess to a list when created, then to bring it to focus ill have to search the list on click and compare the process id's, then bring it to focus.

    I think it may work :)



  • Gread idea



  • Actually, for some reason, the finished signal is not working with the startDetached() call after I create it on the heap...very odd.

    @
    /*
    // app button clicked (slot)
    */
    void Widget::appButtonClicked()
    {
    // get sender of the signal
    QToolButton *button = qobject_cast<QToolButton *>(sender());

    // format the exe location
    QString temp = button->objectName();
    temp = temp.replace("/", "\\\\");
    temp = "\"" + temp + "\"";
    
    QProcess *exeprocess = new QProcess(this);
    connect(exeprocess, SIGNAL(finished(int)), this, SLOT(processFinished(int)));
    exeprocess->setObjectName(button->objectName());
    exeprocess->startDetached(temp);
    
    // append the process to the list
    processList.append(exeprocess);
    

    }

    /*
    // process finished
    */
    void Widget::processFinished(int state)
    {
    // get sender of the signal
    QProcess *exitprocess = qobject_cast<QProcess *>(sender());

    // loop through the list and match the process id
    for (i=0;i<processList.size();i++){
        if (processList[i]->pid() == exitprocess->pid()){
            // delete the icon
            delete (processList.takeAt(i));
            return;
        }
    }
    

    }
    @



  • That is odd...



  • Found this on another thread:

    QProcess::startDetached() [doc.qt.nokia.com] are static methods and therefore never send signals.



  • So I have somewhat figured it out...and I am kind of stuck but I think I know why. Here's what I did.

    @
    /*
    // app button clicked (slot)
    */
    void Widget::appButtonClicked()
    {
    // get sender of the signal
    QToolButton *button = qobject_cast<QToolButton *>(sender());

    for (i=0;i<processList.size();i++){
        // check if the process is already open
        QStringList objectNameSplit;
        objectNameSplit = QString(processList[i]->objectName()).split("*");
        if (objectNameSplit.size() > 1){
            if (objectNameSplit[0] == button->objectName()){
                Q_PID pidQt = (Q_PID)QString(objectNameSplit[1]).toInt();
                EnumWindows(EnumWindowsProc, (LPARAM)pidQt);  // get the window handles
                return;
            }
        }
    }
    
    // format the exe location
    QString temp = button->objectName();
    temp = temp.replace("/", "\\\\");
    temp = "\"" + temp + "\"";
    
    QString tempWd;
    QStringList tempArgs;
    qint64 tempPid;
    
    // start the process
    QProcess *exeprocess = new QProcess();
    exeprocess->startDetached(temp, tempArgs, tempWd, &tempPid);
    
    // set the object name for future reference
    QString objectName = button->objectName() + "*" + QVariant(tempPid).toString();
    exeprocess->setObjectName(objectName);
    
    // append the process to the list
    processList.append(exeprocess);
    

    }
    @

    When I started the process, I got the process ID. Next if the application is already open, I used the windows API EnumWindows which loops through each window until call false within the callback functions.

    Here is the standard windows api call back function:
    @
    /*
    // window enumeration callback (GLOBAL FUNCTION NOT IN CLASS)
    */
    BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
    {
    // get the window process ID
    DWORD searchedProcessId = (DWORD)lParam;
    DWORD windowProcessId = 0;
    GetWindowThreadProcessId(hWnd,&windowProcessId);

    // check the process id match
    if (windowProcessId == searchedProcessId){
        ShowWindow(hWnd, SW_SHOW);
        return FALSE;
    }
    return TRUE;  //continue enumeration
    

    }
    @

    where I pass in the process ID...If it matches, then I return false and stop the enumeration loop. Unfortunately the ShowWindow function fails to bring the window to the foreground...

    Question, when QProcess starts, does it handle a point to the parent process? or the child process created by the QProcess? Because I might be trying to bring the dock app to the foreground instead of the opened exectuable.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.