File indexing completed on 2024-04-21 05:01:41

0001 /*
0002     This class provides the interface for Plasma and QtQuick
0003 
0004     SPDX-FileCopyrightText: 2013-2023 Alexander Reinholdt <alexander.reinholdt@kdemail.net>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 // application specific includes
0009 #include "smb4kdeclarative.h"
0010 #include "core/smb4kbasicnetworkitem.h"
0011 #include "core/smb4kbookmark.h"
0012 #include "core/smb4kbookmarkhandler.h"
0013 #include "core/smb4kclient.h"
0014 #include "core/smb4khost.h"
0015 #include "core/smb4kmounter.h"
0016 #include "core/smb4kprofilemanager.h"
0017 #include "core/smb4kshare.h"
0018 #include "core/smb4ksynchronizer.h"
0019 #include "core/smb4kworkgroup.h"
0020 #include "smb4k/smb4kcustomsettingseditor.h"
0021 #include "smb4k/smb4khomesuserdialog.h"
0022 #include "smb4k/smb4kpassworddialog.h"
0023 #include "smb4k/smb4kpreviewdialog.h"
0024 #include "smb4k/smb4kprintdialog.h"
0025 #include "smb4k/smb4ksynchronizationdialog.h"
0026 #include "smb4kbookmarkdialog.h"
0027 #include "smb4kbookmarkeditor.h"
0028 #include "smb4kbookmarkobject.h"
0029 #include "smb4kmountdialog.h"
0030 #include "smb4knetworkobject.h"
0031 #include "smb4kprofileobject.h"
0032 
0033 //
0034 // Qt includes
0035 #include <QDebug>
0036 #include <QPointer>
0037 
0038 // KDE includes
0039 #include <KConfigDialog>
0040 #include <KMessageBox>
0041 #include <KPluginFactory>
0042 #include <KPluginMetaData>
0043 
0044 class Smb4KDeclarativePrivate
0045 {
0046 public:
0047     QList<Smb4KNetworkObject *> workgroupObjects;
0048     QList<Smb4KNetworkObject *> hostObjects;
0049     QList<Smb4KNetworkObject *> shareObjects;
0050     QList<Smb4KNetworkObject *> mountedObjects;
0051     QList<Smb4KBookmarkObject *> bookmarkObjects;
0052     QList<Smb4KBookmarkObject *> bookmarkCategoryObjects;
0053     QList<Smb4KProfileObject *> profileObjects;
0054     QList<NetworkItemPtr> requestQueue;
0055     QPointer<Smb4KPasswordDialog> passwordDialog;
0056     int timerId;
0057 };
0058 
0059 Smb4KDeclarative::Smb4KDeclarative(QObject *parent)
0060     : QObject(parent)
0061     , d(new Smb4KDeclarativePrivate)
0062 {
0063     d->passwordDialog = new Smb4KPasswordDialog();
0064     d->timerId = 0;
0065 
0066     connect(Smb4KClient::self(), &Smb4KClient::workgroups, this, &Smb4KDeclarative::slotWorkgroupsListChanged);
0067     connect(Smb4KClient::self(), &Smb4KClient::hosts, this, &Smb4KDeclarative::slotHostsListChanged);
0068     connect(Smb4KClient::self(), &Smb4KClient::shares, this, &Smb4KDeclarative::slotSharesListChanged);
0069     connect(Smb4KClient::self(), &Smb4KClient::aboutToStart, this, &Smb4KDeclarative::busy);
0070     connect(Smb4KClient::self(), &Smb4KClient::finished, this, &Smb4KDeclarative::idle);
0071     connect(Smb4KClient::self(), &Smb4KClient::requestCredentials, this, &Smb4KDeclarative::slotCredentialsRequested);
0072 
0073     connect(Smb4KMounter::self(), &Smb4KMounter::mountedSharesListChanged, this, &Smb4KDeclarative::slotMountedSharesListChanged);
0074     connect(Smb4KMounter::self(), &Smb4KMounter::aboutToStart, this, &Smb4KDeclarative::busy);
0075     connect(Smb4KMounter::self(), &Smb4KMounter::finished, this, &Smb4KDeclarative::idle);
0076     connect(Smb4KMounter::self(), &Smb4KMounter::requestCredentials, this, &Smb4KDeclarative::slotCredentialsRequested);
0077 
0078     connect(Smb4KBookmarkHandler::self(), &Smb4KBookmarkHandler::updated, this, &Smb4KDeclarative::slotBookmarksListChanged);
0079 
0080     connect(Smb4KProfileManager::self(), &Smb4KProfileManager::profilesListChanged, this, &Smb4KDeclarative::slotProfilesListChanged);
0081     connect(Smb4KProfileManager::self(), &Smb4KProfileManager::activeProfileChanged, this, &Smb4KDeclarative::slotActiveProfileChanged);
0082     connect(Smb4KProfileManager::self(), &Smb4KProfileManager::profileUsageChanged, this, &Smb4KDeclarative::slotProfileUsageChanged);
0083 
0084     //
0085     // Do the initial loading of items
0086     //
0087     slotBookmarksListChanged();
0088     slotProfilesListChanged(Smb4KProfileManager::self()->profilesList());
0089     slotActiveProfileChanged(Smb4KProfileManager::self()->activeProfile());
0090     slotProfileUsageChanged(Smb4KProfileManager::self()->useProfiles());
0091 }
0092 
0093 Smb4KDeclarative::~Smb4KDeclarative()
0094 {
0095     qDeleteAll(d->workgroupObjects);
0096     d->workgroupObjects.clear();
0097 
0098     qDeleteAll(d->hostObjects);
0099     d->hostObjects.clear();
0100 
0101     qDeleteAll(d->shareObjects);
0102     d->shareObjects.clear();
0103 
0104     qDeleteAll(d->mountedObjects);
0105     d->mountedObjects.clear();
0106 
0107     qDeleteAll(d->bookmarkObjects);
0108     d->bookmarkObjects.clear();
0109 
0110     qDeleteAll(d->bookmarkCategoryObjects);
0111     d->bookmarkCategoryObjects.clear();
0112 
0113     qDeleteAll(d->profileObjects);
0114     d->profileObjects.clear();
0115 }
0116 
0117 QQmlListProperty<Smb4KNetworkObject> Smb4KDeclarative::workgroups()
0118 {
0119     return QQmlListProperty<Smb4KNetworkObject>(this, &d->workgroupObjects);
0120 }
0121 
0122 QQmlListProperty<Smb4KNetworkObject> Smb4KDeclarative::hosts()
0123 {
0124     return QQmlListProperty<Smb4KNetworkObject>(this, &d->hostObjects);
0125 }
0126 
0127 QQmlListProperty<Smb4KNetworkObject> Smb4KDeclarative::shares()
0128 {
0129     return QQmlListProperty<Smb4KNetworkObject>(this, &d->shareObjects);
0130 }
0131 
0132 QQmlListProperty<Smb4KNetworkObject> Smb4KDeclarative::mountedShares()
0133 {
0134     return QQmlListProperty<Smb4KNetworkObject>(this, &d->mountedObjects);
0135 }
0136 
0137 QQmlListProperty<Smb4KBookmarkObject> Smb4KDeclarative::bookmarks()
0138 {
0139     return QQmlListProperty<Smb4KBookmarkObject>(this, &d->bookmarkObjects);
0140 }
0141 
0142 QQmlListProperty<Smb4KBookmarkObject> Smb4KDeclarative::bookmarkCategories()
0143 {
0144     return QQmlListProperty<Smb4KBookmarkObject>(this, &d->bookmarkCategoryObjects);
0145 }
0146 
0147 QQmlListProperty<Smb4KProfileObject> Smb4KDeclarative::profiles()
0148 {
0149     return QQmlListProperty<Smb4KProfileObject>(this, &d->profileObjects);
0150 }
0151 
0152 void Smb4KDeclarative::lookup(Smb4KNetworkObject *object)
0153 {
0154     if (object) {
0155         switch (object->type()) {
0156         case Smb4KNetworkObject::Network: {
0157             Smb4KClient::self()->lookupDomains();
0158             break;
0159         }
0160         case Smb4KNetworkObject::Workgroup: {
0161             // Check if the workgroup is known.
0162             WorkgroupPtr workgroup = Smb4KGlobal::findWorkgroup(object->url().host().toUpper());
0163 
0164             if (workgroup) {
0165                 Smb4KClient::self()->lookupDomainMembers(workgroup);
0166             }
0167 
0168             break;
0169         }
0170         case Smb4KNetworkObject::Host: {
0171             // Check if the host is known.
0172             HostPtr host = Smb4KGlobal::findHost(object->url().host().toUpper());
0173 
0174             if (host) {
0175                 Smb4KClient::self()->lookupShares(host);
0176             }
0177 
0178             break;
0179         }
0180         case Smb4KNetworkObject::Share: {
0181             break;
0182         }
0183         default: {
0184             // Shares are ignored
0185             break;
0186         }
0187         }
0188     } else {
0189         // If the object is 0, scan the whole network.
0190         Smb4KClient::self()->lookupDomains();
0191     }
0192 }
0193 
0194 Smb4KNetworkObject *Smb4KDeclarative::findNetworkItem(const QUrl &url, int type)
0195 {
0196     Smb4KNetworkObject *object = nullptr;
0197 
0198     if (url.isValid()) {
0199         switch (type) {
0200         case Smb4KNetworkObject::Workgroup: {
0201             for (Smb4KNetworkObject *obj : qAsConst(d->workgroupObjects)) {
0202                 if (url == obj->url()) {
0203                     object = obj;
0204                     break;
0205                 } else {
0206                     continue;
0207                 }
0208             }
0209             break;
0210         }
0211         case Smb4KNetworkObject::Host: {
0212             for (Smb4KNetworkObject *obj : qAsConst(d->hostObjects)) {
0213                 if (url == obj->url()) {
0214                     object = obj;
0215                     break;
0216                 } else {
0217                     continue;
0218                 }
0219             }
0220             break;
0221         }
0222         case Smb4KNetworkObject::Share: {
0223             for (Smb4KNetworkObject *obj : qAsConst(d->shareObjects)) {
0224                 if (url == obj->url()) {
0225                     object = obj;
0226                     break;
0227                 } else {
0228                     continue;
0229                 }
0230             }
0231             break;
0232         }
0233         default: {
0234             break;
0235         }
0236         }
0237     }
0238 
0239     return object;
0240 }
0241 
0242 void Smb4KDeclarative::openMountDialog()
0243 {
0244     QPointer<Smb4KMountDialog> mountDialog = new Smb4KMountDialog();
0245     mountDialog->open();
0246 }
0247 
0248 void Smb4KDeclarative::mountShare(Smb4KNetworkObject *object)
0249 {
0250     if (object && object->type() == Smb4KNetworkObject::Share) {
0251         SharePtr share = Smb4KGlobal::findShare(object->url(), object->workgroupName());
0252 
0253         if (share) {
0254             if (share->isHomesShare()) {
0255                 QPointer<Smb4KHomesUserDialog> homesUserDialog = new Smb4KHomesUserDialog();
0256                 bool proceed = false;
0257 
0258                 if (homesUserDialog->setShare(share)) {
0259                     // We want to get a return value here, so we use exec()
0260                     if (homesUserDialog->exec() == QDialog::Accepted) {
0261                         proceed = true;
0262                     }
0263                 }
0264 
0265                 delete homesUserDialog;
0266 
0267                 if (!proceed) {
0268                     return;
0269                 }
0270             }
0271 
0272             Smb4KMounter::self()->mountShare(share);
0273         }
0274     }
0275 }
0276 
0277 void Smb4KDeclarative::mountBookmark(Smb4KBookmarkObject *object)
0278 {
0279     if (object) {
0280         BookmarkPtr bookmark = Smb4KBookmarkHandler::self()->findBookmarkByUrl(object->url());
0281 
0282         SharePtr share = SharePtr(new Smb4KShare());
0283         share->setUrl(object->url());
0284         share->setWorkgroupName(object->workgroupName());
0285         share->setHostIpAddress(object->hostIpAddress());
0286 
0287         Smb4KMounter::self()->mountShare(share);
0288 
0289         share.clear();
0290     }
0291 }
0292 
0293 void Smb4KDeclarative::unmount(Smb4KNetworkObject *object)
0294 {
0295     if (object && object->type()) {
0296         if (object->mountpoint().isValid()) {
0297             SharePtr share = Smb4KGlobal::findShareByPath(object->mountpoint().path());
0298 
0299             if (share) {
0300                 Smb4KMounter::self()->unmountShare(share);
0301             }
0302         }
0303     }
0304 }
0305 
0306 void Smb4KDeclarative::unmountAll()
0307 {
0308     Smb4KMounter::self()->unmountAllShares(false);
0309 }
0310 
0311 bool Smb4KDeclarative::isShareMounted(const QUrl &url)
0312 {
0313     QList<SharePtr> shares = Smb4KGlobal::findShareByUrl(url);
0314 
0315     for (const SharePtr &share : qAsConst(shares)) {
0316         if (!share->isForeign()) {
0317             return true;
0318         }
0319     }
0320 
0321     return false;
0322 }
0323 
0324 void Smb4KDeclarative::print(Smb4KNetworkObject *object)
0325 {
0326     if (object && object->type() == Smb4KNetworkObject::Share) {
0327         SharePtr printer = Smb4KGlobal::findShare(object->url(), object->workgroupName());
0328 
0329         if (printer) {
0330             QPointer<Smb4KPrintDialog> printDialog = new Smb4KPrintDialog();
0331 
0332             if (printDialog->setPrinterShare(printer)) {
0333                 printDialog->open();
0334             } else {
0335                 delete printDialog;
0336             }
0337         }
0338     }
0339 }
0340 
0341 void Smb4KDeclarative::addBookmark(Smb4KNetworkObject *object)
0342 {
0343     if (object) {
0344         QList<SharePtr> shares;
0345 
0346         SharePtr share = Smb4KGlobal::findShare(object->url(), object->workgroupName());
0347 
0348         if (share) {
0349             shares << share;
0350         } else {
0351             QList<SharePtr> mountedShares = Smb4KGlobal::findShareByUrl(object->url());
0352 
0353             if (!mountedShares.isEmpty()) {
0354                 shares << mountedShares.first();
0355             }
0356         }
0357 
0358         if (!shares.isEmpty()) {
0359             QPointer<Smb4KBookmarkDialog> bookmarkDialog = new Smb4KBookmarkDialog();
0360 
0361             if (bookmarkDialog->setShares(shares)) {
0362                 bookmarkDialog->open();
0363             } else {
0364                 delete bookmarkDialog;
0365             }
0366         }
0367     }
0368 }
0369 
0370 void Smb4KDeclarative::removeBookmark(Smb4KBookmarkObject *object)
0371 {
0372     if (object) {
0373         //
0374         // Find the bookmark in the list and remove it.
0375         //
0376         BookmarkPtr bookmark = Smb4KBookmarkHandler::self()->findBookmarkByUrl(object->url());
0377 
0378         if (bookmark) {
0379             Smb4KBookmarkHandler::self()->removeBookmark(bookmark);
0380         }
0381     }
0382 }
0383 
0384 void Smb4KDeclarative::editBookmarks()
0385 {
0386     QPointer<Smb4KBookmarkEditor> bookmarkEditor = new Smb4KBookmarkEditor();
0387     bookmarkEditor->open();
0388 }
0389 
0390 void Smb4KDeclarative::synchronize(Smb4KNetworkObject *object)
0391 {
0392     if (object && object->type() == Smb4KNetworkObject::Share) {
0393         for (const SharePtr &share : Smb4KGlobal::mountedSharesList()) {
0394             if (share->url() == object->url()) {
0395                 QPointer<Smb4KSynchronizationDialog> synchronizationDialog = new Smb4KSynchronizationDialog();
0396                 if (synchronizationDialog->setShare(share)) {
0397                     synchronizationDialog->open();
0398                 } else {
0399                     delete synchronizationDialog;
0400                 }
0401             }
0402         }
0403     }
0404 }
0405 
0406 void Smb4KDeclarative::openCustomOptionsDialog(Smb4KNetworkObject *object)
0407 {
0408     if (object) {
0409         NetworkItemPtr networkItem;
0410 
0411         switch (object->type()) {
0412         case Smb4KNetworkObject::Host: {
0413             for (const HostPtr &host : Smb4KGlobal::hostsList()) {
0414                 if (host->url() == object->url()) {
0415                     networkItem = host;
0416                     break;
0417                 }
0418             }
0419             break;
0420         }
0421         case Smb4KNetworkObject::Share: {
0422             for (const SharePtr &share : Smb4KGlobal::sharesList()) {
0423                 if (share->url() == object->url()) {
0424                     networkItem = share;
0425                     break;
0426                 }
0427             }
0428             break;
0429         }
0430         default: {
0431             break;
0432         }
0433         }
0434 
0435         if (!networkItem.isNull()) {
0436             QPointer<Smb4KCustomSettingsEditor> customSettingsEditor = new Smb4KCustomSettingsEditor();
0437             if (customSettingsEditor->setNetworkItem(networkItem)) {
0438                 customSettingsEditor->open();
0439             } else {
0440                 delete customSettingsEditor;
0441             }
0442         }
0443     }
0444 }
0445 
0446 void Smb4KDeclarative::startClient()
0447 {
0448     Smb4KClient::self()->start();
0449 }
0450 
0451 void Smb4KDeclarative::abortClient()
0452 {
0453     Smb4KClient::self()->abort();
0454 }
0455 
0456 void Smb4KDeclarative::startMounter()
0457 {
0458     Smb4KMounter::self()->start();
0459 }
0460 
0461 void Smb4KDeclarative::abortMounter()
0462 {
0463     Smb4KMounter::self()->abort();
0464 }
0465 
0466 QString Smb4KDeclarative::activeProfile() const
0467 {
0468     QString activeProfile;
0469 
0470     for (Smb4KProfileObject *profile : qAsConst(d->profileObjects)) {
0471         if (profile->isActiveProfile()) {
0472             activeProfile = profile->profileName();
0473             break;
0474         } else {
0475             continue;
0476         }
0477     }
0478 
0479     return activeProfile;
0480 }
0481 
0482 void Smb4KDeclarative::setActiveProfile(const QString &profile)
0483 {
0484     Smb4KProfileManager::self()->setActiveProfile(profile);
0485 }
0486 
0487 bool Smb4KDeclarative::profileUsage() const
0488 {
0489     return Smb4KProfileManager::self()->useProfiles();
0490 }
0491 
0492 void Smb4KDeclarative::preview(Smb4KNetworkObject *object)
0493 {
0494     if (object->type() == Smb4KNetworkObject::Share) {
0495         SharePtr share = Smb4KGlobal::findShare(object->url(), object->workgroupName());
0496 
0497         if (share) {
0498             QPointer<Smb4KPreviewDialog> previewDialog = new Smb4KPreviewDialog();
0499 
0500             if (previewDialog->setShare(share)) {
0501                 previewDialog->open();
0502             } else {
0503                 delete previewDialog;
0504             }
0505         }
0506     }
0507 }
0508 
0509 void Smb4KDeclarative::openConfigurationDialog()
0510 {
0511     //
0512     // Check if the configuration dialog exists and try to show it.
0513     //
0514     if (KConfigDialog::exists(QStringLiteral("Smb4KConfigDialog"))) {
0515         KConfigDialog::showDialog(QStringLiteral("Smb4KConfigDialog"));
0516         return;
0517     }
0518 
0519     //
0520     // If the dialog does not exist, load and show it:
0521     //
0522     KPluginMetaData metaData(QStringLiteral("smb4kconfigdialog"));
0523     KPluginFactory::Result<KPluginFactory> result = KPluginFactory::loadFactory(metaData);
0524 
0525     if (result.errorReason == KPluginFactory::NO_PLUGIN_ERROR) {
0526         QPointer<KConfigDialog> dlg = result.plugin->create<KConfigDialog>();
0527 
0528         if (dlg) {
0529             dlg->setObjectName(QStringLiteral("Smb4KConfigDialog"));
0530             dlg->show();
0531         }
0532     }
0533 }
0534 
0535 void Smb4KDeclarative::timerEvent(QTimerEvent *event)
0536 {
0537     Q_UNUSED(event);
0538 
0539     if (!d->requestQueue.isEmpty()) {
0540         if (!d->passwordDialog->isVisible()) {
0541             NetworkItemPtr networkItem = d->requestQueue.takeFirst();
0542 
0543             if (networkItem && d->passwordDialog->setNetworkItem(networkItem)) {
0544                 d->passwordDialog->show();
0545             }
0546         }
0547     } else {
0548         killTimer(d->timerId);
0549         d->timerId = 0;
0550     }
0551 }
0552 
0553 void Smb4KDeclarative::slotWorkgroupsListChanged()
0554 {
0555     qDeleteAll(d->workgroupObjects);
0556     d->workgroupObjects.clear();
0557 
0558     for (const WorkgroupPtr &workgroup : Smb4KGlobal::workgroupsList()) {
0559         d->workgroupObjects << new Smb4KNetworkObject(workgroup.data());
0560     }
0561 
0562     Q_EMIT workgroupsListChanged();
0563 }
0564 
0565 void Smb4KDeclarative::slotHostsListChanged()
0566 {
0567     qDeleteAll(d->hostObjects);
0568     d->hostObjects.clear();
0569 
0570     for (const HostPtr &host : Smb4KGlobal::hostsList()) {
0571         d->hostObjects << new Smb4KNetworkObject(host.data());
0572     }
0573 
0574     Q_EMIT hostsListChanged();
0575 }
0576 
0577 void Smb4KDeclarative::slotSharesListChanged()
0578 {
0579     qDeleteAll(d->shareObjects);
0580     d->shareObjects.clear();
0581 
0582     for (const SharePtr &share : Smb4KGlobal::sharesList()) {
0583         d->shareObjects << new Smb4KNetworkObject(share.data());
0584     }
0585 
0586     Q_EMIT sharesListChanged();
0587 }
0588 
0589 void Smb4KDeclarative::slotMountedSharesListChanged()
0590 {
0591     qDeleteAll(d->mountedObjects);
0592     d->mountedObjects.clear();
0593 
0594     for (const SharePtr &mountedShare : Smb4KGlobal::mountedSharesList()) {
0595         d->mountedObjects << new Smb4KNetworkObject(mountedShare.data());
0596     }
0597 
0598     Q_EMIT mountedSharesListChanged();
0599 }
0600 
0601 void Smb4KDeclarative::slotBookmarksListChanged()
0602 {
0603     qDeleteAll(d->bookmarkObjects);
0604     d->bookmarkObjects.clear();
0605 
0606     qDeleteAll(d->bookmarkCategoryObjects);
0607     d->bookmarkCategoryObjects.clear();
0608 
0609     QList<BookmarkPtr> bookmarksList = Smb4KBookmarkHandler::self()->bookmarkList();
0610     QStringList categoriesList = Smb4KBookmarkHandler::self()->categoryList();
0611 
0612     for (const BookmarkPtr &bookmark : qAsConst(bookmarksList)) {
0613         d->bookmarkObjects << new Smb4KBookmarkObject(bookmark.data());
0614     }
0615 
0616     for (const QString &category : qAsConst(categoriesList)) {
0617         d->bookmarkCategoryObjects << new Smb4KBookmarkObject(category);
0618     }
0619 
0620     Q_EMIT bookmarksListChanged();
0621 }
0622 
0623 void Smb4KDeclarative::slotProfilesListChanged(const QStringList &profiles)
0624 {
0625     qDeleteAll(d->profileObjects);
0626     d->profileObjects.clear();
0627 
0628     for (const QString &p : profiles) {
0629         Smb4KProfileObject *profile = new Smb4KProfileObject();
0630         profile->setProfileName(p);
0631 
0632         if (QString::compare(p, Smb4KProfileManager::self()->activeProfile()) == 0) {
0633             profile->setActiveProfile(true);
0634         } else {
0635             profile->setActiveProfile(false);
0636         }
0637 
0638         d->profileObjects << profile;
0639     }
0640 
0641     Q_EMIT profilesListChanged();
0642 }
0643 
0644 void Smb4KDeclarative::slotActiveProfileChanged(const QString &activeProfile)
0645 {
0646     for (Smb4KProfileObject *profile : qAsConst(d->profileObjects)) {
0647         if (QString::compare(profile->profileName(), activeProfile) == 0) {
0648             profile->setActiveProfile(true);
0649         } else {
0650             profile->setActiveProfile(false);
0651         }
0652     }
0653 
0654     Q_EMIT activeProfileChanged();
0655 }
0656 
0657 void Smb4KDeclarative::slotProfileUsageChanged(bool /*use*/)
0658 {
0659     Q_EMIT profileUsageChanged();
0660 }
0661 
0662 void Smb4KDeclarative::slotCredentialsRequested(const NetworkItemPtr &networkItem)
0663 {
0664     d->requestQueue.append(networkItem);
0665 
0666     if (d->timerId == 0) {
0667         d->timerId = startTimer(500);
0668     }
0669 }