Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QtWebEngine
  4. Can't Figure out QWebEngineView::findText()

Can't Figure out QWebEngineView::findText()

Scheduled Pinned Locked Moved Solved QtWebEngine
7 Posts 2 Posters 3.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    PSI_lbc
    wrote on last edited by
    #1

    I have a Form for processing purchases. It used to use a QWebView which is or is going to be deprecated. I updated to the latest Qt/Creator 5.7.1 in order to use the QWebEngineView..which is the QWebView replacement.

    Creator does not have a QWebEngineView widget to just drop on a from, so a QWidget is added and then promoted to a QWebEngineView. The purpose of the view is to load a local html file that will transfer control to a https card processing portal on a button press. During processing at the on_webView_loadFinished signal, I would use the QWebView::findText() method to search the active webpage to monitor progress, check for errors, etc. It worked fine as a QWebView..not so much in QWebEngineView.

    When I get the QWebEngineView::loadFinished signal the bool passed is “true” signifying all is good, page is loaded. I can access the webpage title QWebEngineView::title() property but I’m not having any luck using the QWebEngineView::findText() method. I just cannot figure it out.

    I the QWebView version, I would have tests like..

    if ( webView->findText( USERNOTCONNECTED ) )
    {
    ..
    }

    In the QWebEngineView version I can’t find any Qt examples on how to use it. Essentially I created a function to return a bool if the text being searched for is located in the webpage content nd “selected”. There is a findText() method in QWebEngineView for the view itself and also of the view->page(). Not sure which to use or if it make a difference. The QWebEngineView::selectedText() method always returns “”..so whatever is being searched for is never found.

    I did find a similar problem thread..( https://forum.qt.io/topic/55362/solved-webengineview-findtext ).. but the “solution” seems incomplete and I could not get it to work.

    What I tried..

    @
    void frmBuyIt::isFoundText( bool value )
    {
    // textFound is a frmBuyIt class bool member
    textFound = value;
    }

    bool frmBuyIt::FoundText( QWebEngineView *view, QString it )
    {
    // examine page content for a specific text string..

    #if DEBUG_BUYIT
    qDebug() << "frmBuyIt::FoundText looking for: "<< it;
    #endif

    // QWebEngineView doesnt' work..
    // use C++11 to use lambdas. Add CONFIG += c++11 in your .pro file and recompile. <-did this

    //dnw
    view->findText( it, QWebEnginePage::FindFlags(), [=](bool found) { frmBuyIt::isFoundText(found); qDebug()<<"view "<< it << textFound; });
    // if the text was found, then it is "selected"..according to docs
    QString vst = view->selectedText();

    //dnw
    view->page()->findText( it, QWebEnginePage::FindFlags(), [=](bool found) { frmBuyIt::isFoundText(found); qDebug()<<"page "<< it << textFound; });
    // if the text was found it is "selected"..according to docs
    QString pst = view->page()->selectedText();

    // if the text was found, then it's "selected"..according to docs
    bool found = ( vst == it );

    #if DEBUG_BUYIT
    qDebug() << "frmBuyIt::FoundText: "<< it << found << vst << pst;
    #endif

    return found;
    }
    @

    1 Reply Last reply
    0
    • T Offline
      T Offline
      ThatDud3
      wrote on last edited by ThatDud3
      #2

      Please read porting guide completely
      http://doc.qt.io/qt-5/qtwebenginewidgets-qtwebkitportingguide.html

      Communication with embedded web engine is now asynchronous - so you don't know if your lambda will be executed before you try to evaluate Selected text - usually not
      Try to move all debug print inside your lambda function or add two buttons just for testing - one to do findtext the other to get SelectedText and make sure you print it inside your lambda this time

      P 1 Reply Last reply
      0
      • T ThatDud3

        Please read porting guide completely
        http://doc.qt.io/qt-5/qtwebenginewidgets-qtwebkitportingguide.html

        Communication with embedded web engine is now asynchronous - so you don't know if your lambda will be executed before you try to evaluate Selected text - usually not
        Try to move all debug print inside your lambda function or add two buttons just for testing - one to do findtext the other to get SelectedText and make sure you print it inside your lambda this time

        P Offline
        P Offline
        PSI_lbc
        wrote on last edited by
        #3

        @ThatDud3

        Please read porting guide completely
        Thx, but I did that prior to posting this.

        Try to move all debug print inside your lambda function..

        I've never used a Lambda before..but isn't that where the qDebug statement is in the example I posted?

        @
        view->findText( it, QWebEnginePage::FindFlags(), [=](bool found) { frmBuyIt::isFoundText(found); qDebug()<<"view "<< it << textFound; });
        @

        1 Reply Last reply
        0
        • T Offline
          T Offline
          ThatDud3
          wrote on last edited by
          #4

          well next time please use code formatting and it will be nice if you can show us some debugging output too...
          The problem is not with the lambda (if it compiles it will be run) it is just a matter of time - so on that line you basically just schedule you lambda to be run and then immediately execute next line

          QString vst = view->selectedText();
          

          without even giving your view a chance to execute 'findText' and hit your lambda
          so even last line probably executes before Blink/WebEngine even get a chance to start executing commands, so by the time you hit final debug print - of course it is false

          bool found = ( vst == it ); // executes before your lambdas
          qDebug() << "frmBuyIt::FoundText: "<< it << found << vst << pst; // before lambda
          

          so I thought we were discussing this last debug print - you actually never showed a single line of debug output..

          Other issues with your code - you call same functions twice (on view and page) but because WebEngine will execute these async there is no guarantee which one will complete first, and even if they are guaranteed to complete in order what if the view gets it right and then page invalidates result and gets it wrong - you final debug will print it wrong.

          some general pointers

          1. once you 'schedule' something for execution by WebEngine you must wait until it completes
          2. if your lambdas grab some vars from local scope you must ensure they still exist by the time lambda is executed and tries to use them i.e. in that case do not go out of scope

          NB! do not try to just Sleep arbitrary long interval thinking lambda has completed - Sleep will block you thread (GUI) and that was very bad thing esp. for older WebKit, not so sure about Blink...
          The easiest test for you would be with two buttons :
          Click button one =>

          view->findText( it, QWebEnginePage::FindFlags(), [=](bool found) { qDebug()<<"view findText "<< found; });
          

          Wait until you see its debug output and then
          Click button 2 =>

          qDebug()<<"view selectedText "<< view->selectedText();
          

          and watch the debugger output

          P 1 Reply Last reply
          0
          • T ThatDud3

            well next time please use code formatting and it will be nice if you can show us some debugging output too...
            The problem is not with the lambda (if it compiles it will be run) it is just a matter of time - so on that line you basically just schedule you lambda to be run and then immediately execute next line

            QString vst = view->selectedText();
            

            without even giving your view a chance to execute 'findText' and hit your lambda
            so even last line probably executes before Blink/WebEngine even get a chance to start executing commands, so by the time you hit final debug print - of course it is false

            bool found = ( vst == it ); // executes before your lambdas
            qDebug() << "frmBuyIt::FoundText: "<< it << found << vst << pst; // before lambda
            

            so I thought we were discussing this last debug print - you actually never showed a single line of debug output..

            Other issues with your code - you call same functions twice (on view and page) but because WebEngine will execute these async there is no guarantee which one will complete first, and even if they are guaranteed to complete in order what if the view gets it right and then page invalidates result and gets it wrong - you final debug will print it wrong.

            some general pointers

            1. once you 'schedule' something for execution by WebEngine you must wait until it completes
            2. if your lambdas grab some vars from local scope you must ensure they still exist by the time lambda is executed and tries to use them i.e. in that case do not go out of scope

            NB! do not try to just Sleep arbitrary long interval thinking lambda has completed - Sleep will block you thread (GUI) and that was very bad thing esp. for older WebKit, not so sure about Blink...
            The easiest test for you would be with two buttons :
            Click button one =>

            view->findText( it, QWebEnginePage::FindFlags(), [=](bool found) { qDebug()<<"view findText "<< found; });
            

            Wait until you see its debug output and then
            Click button 2 =>

            qDebug()<<"view selectedText "<< view->selectedText();
            

            and watch the debugger output

            P Offline
            P Offline
            PSI_lbc
            wrote on last edited by
            #5

            In your wtf.h class definition

            protected slots:
                void handleHTML( QString sHtml );
                void handleSearch( bool result );
            
            signals:
                void gotHTML( QString sHtml );
                void gotSearch( bool result );
            

            In your wtf.cpp class definition

            void wtf::handleHTML( QString sHtml )
            {
              qDebug() << “wtf::handleHTML:” << sHtml;
            }
            
            void wtf::handleSearch( bool result )
            {
              // searched for text string result
              qDebug() << “wtf::handleSearch: "<< result;
            
              // remove hi-lighted "found" text
              ui->webView->page()->findText("");
            }
            

            In your wtf class instantiation..

            connect(this, SIGNAL(gotHTML(QString)), this, SLOT(handleHTML(QString)));
            connect(this, SIGNAL(gotSearch(bool)), this, SLOT(handleSearch(bool)));
            

            Usage:

            Assuming the QWebEngineView is a widget on your wtf.ui..

            Somewhere in the wtf::on_webView_loadFinished( bool ok ) slot code put the following..

            To scrape the html..

            ui->webView->page()->toHtml([this](const QString& result) mutable {emit gotHTML(result);});
            

            To find something..

            QString idk = “something”;
            ui->webView->page()->findText(idk, QWebEnginePage::FindFlags(), [this](bool found) {
              if (true) emit handleSearch( found );
              });
            

            The findText() example from the QWebEnginePage class docs..(it would have been nice to see in QWebEngineView, too!!!)

            ui->webView->page()->findText(QStringLiteral("Qt"), QWebEnginePage::FindFlags(), [this](bool found) {
              if (!found) QMessageBox::information(ui->webView, QString(), QStringLiteral("No occurrences found"));
              });
            

            The concept of QWebEngineView::findText() is really, really weird. If you’re looking for specific text on a webpage, you want to know the searched for text is there NOW..not when some callback function gets around to it.

            It would seem to make much more sense to scrape the page toHtml() or toString() and then use QString::contains() to do searches. Heck, if the page has been rendered to a view, the QWebEngineView has already read the page content..couldn’t it just save the page data as it goes..in a QString or QByteArray or a QWhatever..? JMO. Done complaining.

            P T 2 Replies Last reply
            0
            • P PSI_lbc

              In your wtf.h class definition

              protected slots:
                  void handleHTML( QString sHtml );
                  void handleSearch( bool result );
              
              signals:
                  void gotHTML( QString sHtml );
                  void gotSearch( bool result );
              

              In your wtf.cpp class definition

              void wtf::handleHTML( QString sHtml )
              {
                qDebug() << “wtf::handleHTML:” << sHtml;
              }
              
              void wtf::handleSearch( bool result )
              {
                // searched for text string result
                qDebug() << “wtf::handleSearch: "<< result;
              
                // remove hi-lighted "found" text
                ui->webView->page()->findText("");
              }
              

              In your wtf class instantiation..

              connect(this, SIGNAL(gotHTML(QString)), this, SLOT(handleHTML(QString)));
              connect(this, SIGNAL(gotSearch(bool)), this, SLOT(handleSearch(bool)));
              

              Usage:

              Assuming the QWebEngineView is a widget on your wtf.ui..

              Somewhere in the wtf::on_webView_loadFinished( bool ok ) slot code put the following..

              To scrape the html..

              ui->webView->page()->toHtml([this](const QString& result) mutable {emit gotHTML(result);});
              

              To find something..

              QString idk = “something”;
              ui->webView->page()->findText(idk, QWebEnginePage::FindFlags(), [this](bool found) {
                if (true) emit handleSearch( found );
                });
              

              The findText() example from the QWebEnginePage class docs..(it would have been nice to see in QWebEngineView, too!!!)

              ui->webView->page()->findText(QStringLiteral("Qt"), QWebEnginePage::FindFlags(), [this](bool found) {
                if (!found) QMessageBox::information(ui->webView, QString(), QStringLiteral("No occurrences found"));
                });
              

              The concept of QWebEngineView::findText() is really, really weird. If you’re looking for specific text on a webpage, you want to know the searched for text is there NOW..not when some callback function gets around to it.

              It would seem to make much more sense to scrape the page toHtml() or toString() and then use QString::contains() to do searches. Heck, if the page has been rendered to a view, the QWebEngineView has already read the page content..couldn’t it just save the page data as it goes..in a QString or QByteArray or a QWhatever..? JMO. Done complaining.

              P Offline
              P Offline
              PSI_lbc
              wrote on last edited by
              #6

              @PSI_lbc

              // remove hi-lighted "found" text
                ui->webView->page()->findText("");
              

              NOTE: this only does 1 instance of the "found" text. If there are multiple found instances of a word, the findText("") will hight-light all of them..not just the first occurrence.

              The call must be repeated to un-highlight all of them.

              Probably a bug.

              1 Reply Last reply
              0
              • P PSI_lbc

                In your wtf.h class definition

                protected slots:
                    void handleHTML( QString sHtml );
                    void handleSearch( bool result );
                
                signals:
                    void gotHTML( QString sHtml );
                    void gotSearch( bool result );
                

                In your wtf.cpp class definition

                void wtf::handleHTML( QString sHtml )
                {
                  qDebug() << “wtf::handleHTML:” << sHtml;
                }
                
                void wtf::handleSearch( bool result )
                {
                  // searched for text string result
                  qDebug() << “wtf::handleSearch: "<< result;
                
                  // remove hi-lighted "found" text
                  ui->webView->page()->findText("");
                }
                

                In your wtf class instantiation..

                connect(this, SIGNAL(gotHTML(QString)), this, SLOT(handleHTML(QString)));
                connect(this, SIGNAL(gotSearch(bool)), this, SLOT(handleSearch(bool)));
                

                Usage:

                Assuming the QWebEngineView is a widget on your wtf.ui..

                Somewhere in the wtf::on_webView_loadFinished( bool ok ) slot code put the following..

                To scrape the html..

                ui->webView->page()->toHtml([this](const QString& result) mutable {emit gotHTML(result);});
                

                To find something..

                QString idk = “something”;
                ui->webView->page()->findText(idk, QWebEnginePage::FindFlags(), [this](bool found) {
                  if (true) emit handleSearch( found );
                  });
                

                The findText() example from the QWebEnginePage class docs..(it would have been nice to see in QWebEngineView, too!!!)

                ui->webView->page()->findText(QStringLiteral("Qt"), QWebEnginePage::FindFlags(), [this](bool found) {
                  if (!found) QMessageBox::information(ui->webView, QString(), QStringLiteral("No occurrences found"));
                  });
                

                The concept of QWebEngineView::findText() is really, really weird. If you’re looking for specific text on a webpage, you want to know the searched for text is there NOW..not when some callback function gets around to it.

                It would seem to make much more sense to scrape the page toHtml() or toString() and then use QString::contains() to do searches. Heck, if the page has been rendered to a view, the QWebEngineView has already read the page content..couldn’t it just save the page data as it goes..in a QString or QByteArray or a QWhatever..? JMO. Done complaining.

                T Offline
                T Offline
                ThatDud3
                wrote on last edited by
                #7

                @PSI_lbc said in Can't Figure out QWebEngineView::findText():

                The concept of QWebEngineView::findText() is really, really weird. If you’re looking for specific text on a webpage, you want to know the searched for text is there NOW..not when some callback function gets around to it.

                This is by design - it affects all functions that interact with the browser, everything is asynchronous e.g. runJavaScript(code) too.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved