File indexing completed on 2025-04-20 13:28:33
0001 /* 0002 SPDX-FileCopyrightText: 2010-2012 Lamarque Souza <lamarque@kde.org> 0003 SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #include "mobileconnectionwizard.h" 0009 #include "uiutils.h" 0010 0011 #include <QVBoxLayout> 0012 0013 #include <KLocalizedString> 0014 #include <Solid/Device> 0015 0016 #include <NetworkManagerQt/ModemDevice> 0017 0018 #include <ModemManagerQt/Manager> 0019 #include <ModemManagerQt/Modem> 0020 0021 #define NUMBER_OF_STATIC_ENTRIES 3 0022 0023 MobileConnectionWizard::MobileConnectionWizard(NetworkManager::ConnectionSettings::ConnectionType connectionType, QWidget *parent) 0024 : QWizard(parent) 0025 { 0026 if (connectionType == NetworkManager::ConnectionSettings::Unknown) { 0027 mInitialMethodType = false; 0028 } else { 0029 mInitialMethodType = true; 0030 0031 if (connectionType == NetworkManager::ConnectionSettings::Bluetooth) { 0032 mType = NetworkManager::ConnectionSettings::Gsm; 0033 } else { 0034 mType = connectionType; 0035 } 0036 } 0037 0038 mProviders = new MobileProviders(); 0039 setWindowTitle(i18nc("Mobile Connection Wizard", "New Mobile Broadband Connection")); 0040 addPage(createIntroPage()); 0041 addPage(createCountryPage()); 0042 addPage(createProvidersPage()); 0043 addPage(createPlansPage()); 0044 addPage(createConfirmPage()); 0045 setOptions(QWizard::NoBackButtonOnStartPage); 0046 } 0047 0048 MobileConnectionWizard::~MobileConnectionWizard() 0049 { 0050 delete mProviders; 0051 } 0052 0053 MobileProviders::ErrorCodes MobileConnectionWizard::getError() 0054 { 0055 if (mProviders) { 0056 return mProviders->getError(); 0057 } 0058 return MobileProviders::Success; 0059 } 0060 0061 void MobileConnectionWizard::initializePage(int id) 0062 { 0063 switch (id) { 0064 case 1: { // Country Page 0065 if (country.isEmpty()) { 0066 country = mProviders->countryFromLocale(); 0067 } 0068 0069 if (country.isEmpty()) 0070 mCountryList->setCurrentRow(0); 0071 else { 0072 const QList<QListWidgetItem *> items = mCountryList->findItems(mProviders->getCountryName(country), Qt::MatchExactly); 0073 if (!items.empty()) { 0074 mCountryList->setCurrentItem(items.first()); 0075 } 0076 } 0077 0078 if (!mInitialMethodType) { 0079 NetworkManager::Device::Ptr iface = NetworkManager::findNetworkInterface(mDeviceComboBox->itemData(mDeviceComboBox->currentIndex()).toString()); 0080 if (iface) { 0081 NetworkManager::ModemDevice::Ptr nmModemIface = iface.objectCast<NetworkManager::ModemDevice>(); 0082 if (nmModemIface && UiUtils::modemSubType(nmModemIface->currentCapabilities()) == NetworkManager::ModemDevice::CdmaEvdo) { 0083 mType = NetworkManager::ConnectionSettings::Cdma; 0084 } else { 0085 mType = NetworkManager::ConnectionSettings::Gsm; 0086 } 0087 } else { 0088 mType = static_cast<NetworkManager::ConnectionSettings::ConnectionType>(mDeviceComboBox->itemData(mDeviceComboBox->currentIndex()).toUInt()); 0089 } 0090 } 0091 0092 if (mProviders->getError() != MobileProviders::Success) { 0093 accept(); 0094 } 0095 break; 0096 } 0097 0098 case 2: // Providers Page 0099 country = mCountryList->currentItem()->text(); 0100 mProvidersList->clear(); 0101 lineEditProvider->clear(); 0102 radioAutoProvider->setChecked(true); 0103 0104 switch (type()) { 0105 case NetworkManager::ConnectionSettings::Gsm: 0106 mProvidersList->insertItems(0, mProviders->getProvidersList(country, NetworkManager::ConnectionSettings::Gsm)); 0107 break; 0108 case NetworkManager::ConnectionSettings::Cdma: 0109 mProvidersList->insertItems(0, mProviders->getProvidersList(country, NetworkManager::ConnectionSettings::Cdma)); 0110 break; 0111 default: 0112 break; 0113 } 0114 mProvidersList->setCurrentRow(0); 0115 if (mProvidersList->count() > 0) { 0116 mProvidersList->setEnabled(true); 0117 radioAutoProvider->setEnabled(true); 0118 mProvidersList->setFocus(); 0119 } else { 0120 mProvidersList->setEnabled(false); 0121 radioAutoProvider->setEnabled(false); 0122 radioManualProvider->setChecked(true); 0123 // TODO: this does not work, try reimplementing QWizardPage::isComplete() 0124 // button(QWizard::NextButton)->setEnabled(false); 0125 } 0126 break; 0127 0128 case 3: // Plans Page 0129 disconnect(mPlanComboBox, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &MobileConnectionWizard::slotEnablePlanEditBox); 0130 mPlanComboBox->clear(); 0131 if (type() != NetworkManager::ConnectionSettings::Gsm) { 0132 goto OUT_3; 0133 } 0134 if (radioManualProvider->isChecked()) { 0135 mPlanComboBox->addItem(i18nc("Mobile Connection Wizard", "My plan is not listed…")); 0136 0137 if (lineEditProvider->text().isEmpty()) { 0138 lineEditProvider->setText(i18nc("Mobile Connection Wizard", "Unknown Provider")); 0139 } 0140 } else { 0141 if (mProvidersList->currentItem() != nullptr) { 0142 const QStringList mApns = mProviders->getApns(mProvidersList->currentItem()->text()); 0143 0144 if (!mApns.isEmpty()) { 0145 mPlanComboBox->insertItems(0, mApns); 0146 mPlanComboBox->setItemText(0, i18nc("Mobile Connection Wizard", "Default")); 0147 } 0148 } 0149 0150 if (mPlanComboBox->count()) { 0151 mPlanComboBox->insertSeparator(1); 0152 } 0153 mPlanComboBox->addItem(i18nc("Mobile Connection Wizard", "My plan is not listed…")); 0154 } 0155 mPlanComboBox->setCurrentIndex(0); 0156 slotEnablePlanEditBox(mPlanComboBox->currentIndex()); 0157 OUT_3: 0158 connect(mPlanComboBox, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &MobileConnectionWizard::slotEnablePlanEditBox); 0159 break; 0160 0161 case 4: // Confirm Page 0162 if (radioManualProvider->isChecked()) { 0163 labelProvider->setText(" " + lineEditProvider->text() + ", " + country); 0164 provider = lineEditProvider->text(); 0165 } else { 0166 labelProvider->setText(" " + mProvidersList->currentItem()->text() + ", " + country); 0167 provider = mProvidersList->currentItem()->text(); 0168 } 0169 0170 if (type() == NetworkManager::ConnectionSettings::Cdma) { 0171 labelPlanLabel->hide(); 0172 labelPlan->hide(); 0173 labelApn->hide(); 0174 userApn->clear(); 0175 apn.clear(); 0176 } else { 0177 labelPlanLabel->show(); 0178 labelPlan->show(); 0179 labelApn->show(); 0180 0181 if (mPlanComboBox->currentText() == i18nc("Mobile Connection Wizard", "My plan is not listed…")) { 0182 labelPlan->setText(" " + userApn->text()); 0183 labelApn->setText(" " + i18nc("Mobile Connection Wizard", "APN: %1", userApn->text())); 0184 apn = userApn->text(); 0185 } else { 0186 int i = mPlanComboBox->currentIndex(); 0187 i = i > 1 ? (i - 1) : 0; // ignores separator's index (i == 1). 0188 0189 QStringList mApns = mProviders->getApns(mProvidersList->currentItem()->text()); 0190 labelPlan->setText(" " + mPlanComboBox->currentText()); 0191 labelApn->setText(" " + i18nc("Mobile Connection Wizard", "APN: %1", mApns.at(i))); 0192 apn = mApns.at(i); 0193 } 0194 } 0195 break; 0196 } 0197 } 0198 0199 int MobileConnectionWizard::nextId() const 0200 { 0201 // Providers page 0202 if (currentId() == 2 && type() != NetworkManager::ConnectionSettings::Gsm) { 0203 // Jumps to Confirm page instead of Plans page if type != Gsm. 0204 return 4; 0205 } else { 0206 return QWizard::nextId(); 0207 } 0208 } 0209 0210 QVariantList MobileConnectionWizard::args() 0211 { 0212 QVariantList temp; 0213 0214 switch (type()) { 0215 case NetworkManager::ConnectionSettings::Cdma: 0216 temp << provider << mProviders->getCdmaInfo(provider); 0217 break; 0218 0219 case NetworkManager::ConnectionSettings::Gsm: 0220 temp << provider /*<< mProviders->getNetworkIds(provider)*/ << mProviders->getApnInfo(apn); 0221 break; 0222 0223 default: 0224 break; 0225 } 0226 return temp; 0227 } 0228 0229 /**********************************************************/ 0230 /* Intro page */ 0231 /**********************************************************/ 0232 0233 QWizardPage *MobileConnectionWizard::createIntroPage() 0234 { 0235 auto page = new QWizardPage(); 0236 page->setTitle(i18nc("Mobile Connection Wizard", "Set up a Mobile Broadband Connection")); 0237 auto layout = new QVBoxLayout; 0238 0239 auto label = 0240 new QLabel(i18nc("Mobile Connection Wizard", "This assistant helps you easily set up a mobile broadband connection to a cellular (3G) network.")); 0241 label->setWordWrap(true); 0242 layout->addWidget(label); 0243 0244 label = new QLabel(QLatin1Char('\n') + i18nc("Mobile Connection Wizard", "You will need the following information:")); 0245 layout->addWidget(label); 0246 0247 label = new QLabel(QStringLiteral(" . %1\n . %2\n . %3") 0248 .arg(i18nc("Mobile Connection Wizard", "Your broadband provider's name"), 0249 i18nc("Mobile Connection Wizard", "Your broadband billing plan name"), 0250 i18nc("Mobile Connection Wizard", "(in some cases) Your broadband billing plan APN (Access Point Name)"))); 0251 layout->addWidget(label); 0252 0253 if (!mInitialMethodType) { 0254 label = new QLabel('\n' + i18nc("Mobile Connection Wizard", "Create a connection for &this mobile broadband device:")); 0255 layout->addWidget(label); 0256 0257 mDeviceComboBox = new KComboBox(); 0258 mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any GSM device")); 0259 mDeviceComboBox->setItemData(0, NetworkManager::ConnectionSettings::Gsm); 0260 mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any CDMA device")); 0261 mDeviceComboBox->setItemData(1, NetworkManager::ConnectionSettings::Cdma); 0262 mDeviceComboBox->insertSeparator(NUMBER_OF_STATIC_ENTRIES - 1); 0263 label->setBuddy(mDeviceComboBox); 0264 layout->addWidget(mDeviceComboBox); 0265 0266 connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &MobileConnectionWizard::introDeviceAdded); 0267 connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &MobileConnectionWizard::introDeviceRemoved); 0268 connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, this, &MobileConnectionWizard::introStatusChanged); 0269 0270 introAddInitialDevices(); 0271 } 0272 0273 page->setLayout(layout); 0274 0275 return page; 0276 } 0277 0278 void MobileConnectionWizard::introAddDevice(const NetworkManager::Device::Ptr &device) 0279 { 0280 QString desc; 0281 0282 ModemManager::ModemDevice::Ptr modem = ModemManager::findModemDevice(device->udi()); 0283 if (modem) { 0284 ModemManager::Modem::Ptr modemInterface = modem->interface(ModemManager::ModemDevice::ModemInterface).objectCast<ModemManager::Modem>(); 0285 if (modemInterface->powerState() == MM_MODEM_POWER_STATE_ON) { 0286 desc.append(modemInterface->manufacturer()); 0287 desc.append(QLatin1Char(' ')); 0288 desc.append(modemInterface->model()); 0289 } else { 0290 QString deviceName = modemInterface->device(); 0291 for (const Solid::Device &d : Solid::Device::allDevices()) { 0292 if (d.udi().contains(deviceName, Qt::CaseInsensitive)) { 0293 deviceName = d.product(); 0294 if (!deviceName.startsWith(d.vendor())) { 0295 deviceName = d.vendor() + QLatin1Char(' ') + deviceName; 0296 } 0297 desc.append(deviceName); 0298 break; 0299 } 0300 } 0301 } 0302 } 0303 0304 NetworkManager::ModemDevice::Ptr nmModemIface = device.objectCast<NetworkManager::ModemDevice>(); 0305 if (!nmModemIface) { 0306 return; 0307 } 0308 0309 if (UiUtils::modemSubType(nmModemIface->currentCapabilities()) == NetworkManager::ModemDevice::GsmUmts) { 0310 if (desc.isEmpty()) { 0311 desc.append(i18nc("Mobile Connection Wizard", "Installed GSM device")); 0312 } 0313 } else if (UiUtils::modemSubType(nmModemIface->currentCapabilities()) == NetworkManager::ModemDevice::CdmaEvdo) { 0314 if (desc.isEmpty()) { 0315 desc.append(i18nc("Mobile Connection Wizard", "Installed CDMA device")); 0316 } 0317 } else { 0318 return; 0319 } 0320 0321 mDeviceComboBox->addItem(desc, device->uni()); 0322 0323 if (mDeviceComboBox->count() == NUMBER_OF_STATIC_ENTRIES) { 0324 mDeviceComboBox->setCurrentIndex(0); 0325 } else { 0326 mDeviceComboBox->setCurrentIndex(NUMBER_OF_STATIC_ENTRIES); 0327 } 0328 } 0329 0330 void MobileConnectionWizard::introDeviceAdded(const QString &uni) 0331 { 0332 introAddDevice(NetworkManager::findNetworkInterface(uni)); 0333 } 0334 0335 void MobileConnectionWizard::introDeviceRemoved(const QString &uni) 0336 { 0337 int index = mDeviceComboBox->findData(uni); 0338 0339 mDeviceComboBox->removeItem(index); 0340 0341 if (mDeviceComboBox->count() == NUMBER_OF_STATIC_ENTRIES) { 0342 mDeviceComboBox->setCurrentIndex(0); 0343 if (currentId() > 0) { 0344 close(); 0345 } 0346 } else { 0347 mDeviceComboBox->setCurrentIndex(NUMBER_OF_STATIC_ENTRIES); 0348 } 0349 } 0350 0351 void MobileConnectionWizard::introStatusChanged(NetworkManager::Status status) 0352 { 0353 switch (status) { 0354 case NetworkManager::Unknown: 0355 case NetworkManager::Asleep: 0356 case NetworkManager::Disconnected: 0357 case NetworkManager::Disconnecting: 0358 introRemoveAllDevices(); 0359 break; 0360 case NetworkManager::Connecting: 0361 case NetworkManager::ConnectedLinkLocal: 0362 case NetworkManager::ConnectedSiteOnly: 0363 case NetworkManager::Connected: 0364 introAddInitialDevices(); 0365 break; 0366 } 0367 } 0368 0369 void MobileConnectionWizard::introAddInitialDevices() 0370 { 0371 for (const NetworkManager::Device::Ptr &n : NetworkManager::networkInterfaces()) { 0372 introAddDevice(n); 0373 } 0374 0375 if (mDeviceComboBox->count() == NUMBER_OF_STATIC_ENTRIES) { 0376 mDeviceComboBox->setCurrentIndex(0); 0377 } else { 0378 mDeviceComboBox->setCurrentIndex(NUMBER_OF_STATIC_ENTRIES); 0379 } 0380 } 0381 0382 void MobileConnectionWizard::introRemoveAllDevices() 0383 { 0384 mDeviceComboBox->clear(); 0385 mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any GSM device")); 0386 mDeviceComboBox->setItemData(0, NetworkManager::ConnectionSettings::Gsm); 0387 mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any CDMA device")); 0388 mDeviceComboBox->setItemData(1, NetworkManager::ConnectionSettings::Cdma); 0389 mDeviceComboBox->insertSeparator(NUMBER_OF_STATIC_ENTRIES - 1); 0390 mDeviceComboBox->setCurrentIndex(0); 0391 } 0392 0393 /**********************************************************/ 0394 /* Country page */ 0395 /**********************************************************/ 0396 0397 QWizardPage *MobileConnectionWizard::createCountryPage() 0398 { 0399 auto page = new QWizardPage(); 0400 page->setTitle(i18nc("Mobile Connection Wizard", "Choose your Provider's Country")); 0401 auto layout = new QVBoxLayout; 0402 0403 auto label = new QLabel(i18nc("Mobile Connection Wizard", "Country List:")); 0404 layout->addWidget(label); 0405 0406 mCountryList = new QListWidget(); 0407 mCountryList->addItem(i18nc("Mobile Connection Wizard", "My country is not listed")); 0408 mCountryList->insertItems(1, mProviders->getCountryList()); 0409 layout->addWidget(mCountryList); 0410 0411 page->setLayout(layout); 0412 0413 return page; 0414 } 0415 0416 /**********************************************************/ 0417 /* Providers page */ 0418 /**********************************************************/ 0419 0420 QWizardPage *MobileConnectionWizard::createProvidersPage() 0421 { 0422 auto page = new QWizardPage(); 0423 page->setTitle(i18nc("Mobile Connection Wizard", "Choose your Provider")); 0424 auto layout = new QVBoxLayout; 0425 0426 radioAutoProvider = new QRadioButton(i18nc("Mobile Connection Wizard", "Select your provider from a &list:")); 0427 radioAutoProvider->setChecked(true); 0428 layout->addWidget(radioAutoProvider); 0429 0430 mProvidersList = new QListWidget(); 0431 connect(mProvidersList, &QListWidget::itemSelectionChanged, this, &MobileConnectionWizard::slotCheckProviderList); 0432 connect(mProvidersList, &QListWidget::itemClicked, this, &MobileConnectionWizard::slotCheckProviderList); 0433 layout->addWidget(mProvidersList); 0434 0435 radioManualProvider = new QRadioButton(i18nc("Mobile Connection Wizard", "I cannot find my provider and I wish to enter it &manually:")); 0436 layout->addWidget(radioManualProvider); 0437 connect(radioManualProvider, &QRadioButton::toggled, this, &MobileConnectionWizard::slotEnableProviderEdit); 0438 0439 lineEditProvider = new KLineEdit(); 0440 layout->addWidget(lineEditProvider); 0441 connect(lineEditProvider, &KLineEdit::textEdited, this, &MobileConnectionWizard::slotCheckProviderEdit); 0442 0443 page->setLayout(layout); 0444 0445 return page; 0446 } 0447 0448 void MobileConnectionWizard::slotEnableProviderEdit(bool checked) 0449 { 0450 if (checked) { 0451 lineEditProvider->setFocus(); 0452 } else { 0453 mProvidersList->setFocus(); 0454 } 0455 } 0456 0457 void MobileConnectionWizard::slotCheckProviderEdit() 0458 { 0459 radioManualProvider->setChecked(true); 0460 // TODO: this does not work, try reimplementing QWizardPage::isComplete() 0461 // button(QWizard::NextButton)->setEnabled(true); 0462 } 0463 0464 void MobileConnectionWizard::slotCheckProviderList() 0465 { 0466 radioAutoProvider->setChecked(true); 0467 lineEditProvider->clear(); 0468 } 0469 0470 /**********************************************************/ 0471 /* Plan page */ 0472 /**********************************************************/ 0473 0474 QWizardPage *MobileConnectionWizard::createPlansPage() 0475 { 0476 auto page = new QWizardPage(); 0477 page->setTitle(i18nc("Mobile Connection Wizard", "Choose your Billing Plan")); 0478 auto layout = new QBoxLayout(QBoxLayout::TopToBottom); 0479 0480 auto label = new QLabel(i18nc("Mobile Connection Wizard", "&Select your plan:")); 0481 layout->addWidget(label); 0482 0483 mPlanComboBox = new KComboBox(); 0484 label->setBuddy(mPlanComboBox); 0485 layout->addWidget(mPlanComboBox); 0486 0487 label = new QLabel('\n' + i18nc("Mobile Connection Wizard", "Selected plan &APN (Access Point Name):")); 0488 layout->addWidget(label); 0489 0490 userApn = new KLineEdit(); 0491 userApn->setEnabled(false); 0492 label->setBuddy(userApn); 0493 layout->addWidget(userApn); 0494 0495 auto layout2 = new QHBoxLayout(); 0496 label = new QLabel(); 0497 label->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-warning")).pixmap(32)); 0498 layout2->addWidget(label, 0, Qt::AlignTop); 0499 label = new QLabel(i18nc("Mobile Connection Wizard", 0500 "Warning: Selecting an incorrect plan may result in billing issues for your broadband account or may prevent connectivity.\n\nIf " 0501 "you are unsure of your plan please ask your provider for your plan's APN.")); 0502 label->setWordWrap(true); 0503 layout2->addWidget(label); 0504 layout->addWidget(new QLabel()); 0505 layout->addLayout(layout2); 0506 0507 page->setLayout(layout); 0508 0509 return page; 0510 } 0511 0512 void MobileConnectionWizard::slotEnablePlanEditBox(int index) 0513 { 0514 const QString text = mPlanComboBox->itemText(index); 0515 if (type() != NetworkManager::ConnectionSettings::Gsm) { 0516 return; 0517 } 0518 if (text == i18nc("Mobile Connection Wizard", "My plan is not listed…")) { 0519 userApn->clear(); 0520 userApn->setEnabled(true); 0521 } else { 0522 if (mProvidersList->currentItem() != nullptr) { 0523 int i = mPlanComboBox->currentIndex(); 0524 if (i > 0) 0525 i = i - 1; // Skipping the separator (i==1) 0526 QStringList mApns = mProviders->getApns(mProvidersList->currentItem()->text()); 0527 userApn->setText(mApns.at(i)); 0528 } 0529 userApn->setEnabled(false); 0530 } 0531 } 0532 0533 /**********************************************************/ 0534 /* Confirm page */ 0535 /**********************************************************/ 0536 0537 QWizardPage *MobileConnectionWizard::createConfirmPage() 0538 { 0539 auto page = new QWizardPage(); 0540 page->setTitle(i18nc("Mobile Connection Wizard", "Confirm Mobile Broadband Settings")); 0541 auto layout = new QVBoxLayout; 0542 0543 auto label = new QLabel(i18nc("Mobile Connection Wizard", "Your mobile broadband connection is configured with the following settings:")); 0544 label->setWordWrap(true); 0545 layout->addWidget(label); 0546 0547 label = new QLabel('\n' + i18nc("Mobile Connection Wizard", "Your Provider:")); 0548 layout->addWidget(label); 0549 labelProvider = new QLabel(); 0550 layout->addWidget(labelProvider); 0551 0552 labelPlanLabel = new QLabel(QLatin1Char('\n') + i18nc("Mobile Connection Wizard", "Your Plan:")); 0553 layout->addWidget(labelPlanLabel); 0554 labelPlan = new QLabel(); 0555 layout->addWidget(labelPlan); 0556 labelApn = new QLabel(); 0557 labelApn->setEnabled(false); 0558 layout->addWidget(labelApn); 0559 0560 page->setLayout(layout); 0561 0562 return page; 0563 }