LCOV - code coverage report
Current view: top level - muse/framework/tours/internal - toursprovider.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 74 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2025 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "toursprovider.h"
      24              : 
      25              : #include <QGuiApplication>
      26              : 
      27              : #include "log.h"
      28              : 
      29              : static const char* SHOW_TOOLTIP_PROPERTY_NAME("toolTipShowLocked");
      30              : 
      31              : using namespace muse;
      32              : using namespace muse::tours;
      33              : 
      34            0 : ToursProvider::ToursProvider(const modularity::ContextPtr& iocCtx)
      35            0 :     : QObject(), Contextable(iocCtx)
      36              : {
      37            0 :     connect(&m_openTimer, &QTimer::timeout, this, &ToursProvider::doShow);
      38              : 
      39            0 :     connect(qApp, &QGuiApplication::applicationStateChanged, this, &ToursProvider::onApplicationStateChanged);
      40            0 : }
      41              : 
      42            0 : void ToursProvider::showTour(const Tour& tour)
      43              : {
      44            0 :     m_tour = tour;
      45            0 :     m_currentStep = 0;
      46            0 :     m_totalSteps = m_tour.steps.size();
      47              : 
      48            0 :     showNext();
      49            0 : }
      50              : 
      51            0 : void ToursProvider::showNext()
      52              : {
      53            0 :     if (m_currentStep >= m_totalSteps) {
      54            0 :         clear();
      55            0 :         return;
      56              :     }
      57              : 
      58            0 :     m_openTimer.start();
      59              : }
      60              : 
      61            0 : void ToursProvider::onTourStepClosed(QQuickItem* parentItem)
      62              : {
      63              :     //! NOTE: Restore showing tooltip for tour's control
      64            0 :     setBlockShowingTooltipForItem(parentItem, false);
      65            0 : }
      66              : 
      67            0 : void ToursProvider::doShow()
      68              : {
      69            0 :     m_openTimer.stop();
      70              : 
      71            0 :     if (qApp->applicationState() != Qt::ApplicationActive) {
      72            0 :         m_needShowTourAfterApplicationActivation = true;
      73            0 :         return;
      74              :     }
      75              : 
      76            0 :     const TourStep& step = m_tour.steps[m_currentStep];
      77            0 :     size_t index = m_currentStep + 1;
      78              : 
      79            0 :     m_currentStep++;
      80              : 
      81            0 :     const ui::INavigationControl* parentControl = findControl(step.controlUri);
      82            0 :     if (!parentControl) {
      83              :         //! NOTE: It's okay that the control is not found,
      84              :         //! for example, the user has hidded the control.
      85            0 :         LOGD() << "Control not found: " << step.controlUri << ", skipping step";
      86            0 :         showNext();
      87            0 :         return;
      88              :     }
      89              : 
      90            0 :     QQuickItem* parentControlItem = parentControl->visualItem();
      91            0 :     IF_ASSERT_FAILED(parentControlItem) {
      92            0 :         return;
      93              :     }
      94              : 
      95            0 :     connect(parentControlItem, &QObject::destroyed, this, [this]() {
      96            0 :         emit closeCurrentTourStep();
      97            0 :         showNext();
      98            0 :     });
      99              : 
     100            0 :     parentControl->triggered().onNotify(this, [this]() {
     101            0 :         emit closeCurrentTourStep();
     102            0 :         showNext();
     103            0 :     });
     104              : 
     105              :     //! NOTE: Avoid showing tooltip for control when tour for that control is shown
     106            0 :     setBlockShowingTooltipForItem(parentControlItem, true);
     107              : 
     108            0 :     emit openTourStep(parentControlItem, step.title, step.description, step.previewImageOrGifUrl, step.videoExplanationUrl, index,
     109              :                       m_totalSteps);
     110              : }
     111              : 
     112            0 : const ui::INavigationControl* ToursProvider::findControl(const Uri& controlUri)
     113              : {
     114            0 :     String controlPath = String::fromStdString(controlUri.path());
     115              : 
     116            0 :     StringList pathItems = controlPath.split('/');
     117            0 :     IF_ASSERT_FAILED(pathItems.size() == 3) {
     118            0 :         LOGE() << "Invalid control uri: " << controlUri;
     119            0 :         return nullptr;
     120              :     }
     121              : 
     122            0 :     std::string section = pathItems[0].toStdString();
     123            0 :     std::string panel = pathItems[1].toStdString();
     124            0 :     std::string controlName = pathItems[2].toStdString();
     125              : 
     126            0 :     return navigationController()->findControl(section, panel, controlName);
     127            0 : }
     128              : 
     129            0 : void ToursProvider::clear()
     130              : {
     131            0 :     m_openTimer.stop();
     132              : 
     133            0 :     m_tour = Tour();
     134            0 :     m_currentStep = 0;
     135            0 :     m_totalSteps = 0;
     136            0 : }
     137              : 
     138            0 : void ToursProvider::setBlockShowingTooltipForItem(QQuickItem* item, bool block)
     139              : {
     140            0 :     if (!item) {
     141            0 :         return;
     142              :     }
     143              : 
     144            0 :     item->setProperty(SHOW_TOOLTIP_PROPERTY_NAME, QVariant::fromValue(block));
     145              : }
     146              : 
     147            0 : void ToursProvider::onApplicationStateChanged(Qt::ApplicationState state)
     148              : {
     149            0 :     if (!m_needShowTourAfterApplicationActivation) {
     150            0 :         return;
     151              :     }
     152              : 
     153            0 :     m_needShowTourAfterApplicationActivation = false;
     154              : 
     155            0 :     if (state == Qt::ApplicationActive) {
     156            0 :         doShow();
     157              :     }
     158              : }
     159              : 
     160            0 : bool ToursProvider::canControlTourPopupClosing() const
     161              : {
     162              : #ifdef Q_OS_LINUX
     163              :     //! NOTE: There is a problem on Linux for popups that when you turn off automatic closing,
     164              :     //! if the user switches to another program, the popup will still be shown on top of the other program.
     165              :     //! Let's turn on automatic closing of the popup for Linux.
     166            0 :     return false;
     167              : #else
     168              :     return true;
     169              : #endif
     170              : }
        

Generated by: LCOV version 2.0-1