diff --git a/analyzers/heaptrack/plugin.cpp b/analyzers/heaptrack/plugin.cpp index 0cc8620c1f..79507ea227 100644 --- a/analyzers/heaptrack/plugin.cpp +++ b/analyzers/heaptrack/plugin.cpp @@ -1,159 +1,162 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "plugin.h" #include "config/globalconfigpage.h" #include "debug.h" #include "job.h" #include "utils.h" #include "visualizer.h" #include "config.h" #if KF5SysGuard_FOUND #include "debuggers/common/dialogs/processselection.h" +#include #endif #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(HeaptrackFactory, "kdevheaptrack.json", registerPlugin();) namespace Heaptrack { Plugin::Plugin(QObject* parent, const QVariantList&) : IPlugin(QStringLiteral("kdevheaptrack"), parent) { setXMLFile(QStringLiteral("kdevheaptrack.rc")); m_launchAction = new QAction( QIcon::fromTheme(QStringLiteral("office-chart-area")), i18n("Run Heaptrack Analysis"), this); connect(m_launchAction, &QAction::triggered, this, &Plugin::launchHeaptrack); actionCollection()->addAction(QStringLiteral("heaptrack_launch"), m_launchAction); #if KF5SysGuard_FOUND m_attachAction = new QAction( QIcon::fromTheme(QStringLiteral("office-chart-area")), i18n("Attach to Process with Heaptrack"), this); connect(m_attachAction, &QAction::triggered, this, &Plugin::attachHeaptrack); actionCollection()->addAction(QStringLiteral("heaptrack_attach"), m_attachAction); #endif } Plugin::~Plugin() { } void Plugin::launchHeaptrack() { auto runController = KDevelop::Core::self()->runControllerInternal(); if (runController->launchConfigurations().isEmpty()) { runController->showConfigurationDialog(); } auto defaultLaunch = runController->defaultLaunch(); if (!defaultLaunch) { return; } auto pluginController = core()->self()->pluginController(); auto iface = pluginController->pluginForExtension(QStringLiteral("org.kdevelop.IExecutePlugin"))->extension(); Q_ASSERT(iface); auto heaptrackJob = new Job(defaultLaunch); connect(heaptrackJob, &Job::finished, this, &Plugin::jobFinished); QList jobList; if (KJob* depJob = iface->dependencyJob(defaultLaunch)) { jobList += depJob; } jobList += heaptrackJob; auto ecJob = new KDevelop::ExecuteCompositeJob(runController, jobList); ecJob->setObjectName(heaptrackJob->statusName()); runController->registerJob(ecJob); m_launchAction->setEnabled(false); } void Plugin::attachHeaptrack() { #if KF5SysGuard_FOUND - KDevMI::ProcessSelectionDialog dlg(activeMainWindow()); - if (!dlg.exec() || !dlg.pidSelected()) { + QPointer dlg = new KDevMI::ProcessSelectionDialog(activeMainWindow()); + if (!dlg->exec() || !dlg->pidSelected()) { + delete dlg; return; } - auto heaptrackJob = new Job(dlg.pidSelected()); + auto heaptrackJob = new Job(dlg->pidSelected()); + delete dlg; connect(heaptrackJob, &Job::finished, this, &Plugin::jobFinished); heaptrackJob->setObjectName(heaptrackJob->statusName()); core()->runController()->registerJob(heaptrackJob); m_launchAction->setEnabled(false); #endif } void Plugin::jobFinished(KJob* kjob) { auto job = static_cast(kjob); Q_ASSERT(job); if (job->status() == KDevelop::OutputExecuteJob::JobStatus::JobSucceeded) { auto visualizer = new Visualizer(job->resultsFile(), this); visualizer->start(); } else { QFile::remove(job->resultsFile()); } m_launchAction->setEnabled(true); } int Plugin::configPages() const { return 1; } KDevelop::ConfigPage* Plugin::configPage(int number, QWidget* parent) { if (number) { return nullptr; } return new GlobalConfigPage(this, parent); } } #include "plugin.moc" diff --git a/debuggers/common/midebuggerplugin.cpp b/debuggers/common/midebuggerplugin.cpp index ccee8215cc..11bee27d51 100644 --- a/debuggers/common/midebuggerplugin.cpp +++ b/debuggers/common/midebuggerplugin.cpp @@ -1,270 +1,274 @@ /* * Common code for MI debugger support * * Copyright 1999-2001 John Birch * Copyright 2001 by Bernd Gehrmann * Copyright 2006 Vladimir Prus * Copyright 2007 Hamish Rodda * Copyright 2016 Aetf * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "midebuggerplugin.h" #include "midebugjobs.h" #include "dialogs/processselection.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include using namespace KDevelop; using namespace KDevMI; MIDebuggerPlugin::MIDebuggerPlugin(const QString &componentName, const QString& displayName, QObject *parent) : KDevelop::IPlugin(componentName, parent) { core()->debugController()->initializeUi(); setupActions(displayName); setupDBus(); } void MIDebuggerPlugin::setupActions(const QString& displayName) { KActionCollection* ac = actionCollection(); QAction * action = new QAction(this); action->setIcon(QIcon::fromTheme(QStringLiteral("core"))); action->setText(i18n("Examine Core File with %1", displayName)); action->setWhatsThis(i18n("Examine core file" "

This loads a core file, which is typically created " "after the application has crashed, e.g. with a " "segmentation fault. The core file contains an " "image of the program memory at the time it crashed, " "allowing you to do a post-mortem analysis.

")); connect(action, &QAction::triggered, this, &MIDebuggerPlugin::slotExamineCore); ac->addAction(QStringLiteral("debug_core"), action); #if KF5SysGuard_FOUND action = new QAction(this); action->setIcon(QIcon::fromTheme(QStringLiteral("connect_creating"))); action->setText(i18n("Attach to Process with %1", displayName)); action->setWhatsThis(i18n("Attach to process" "

Attaches the debugger to a running process.

")); connect(action, &QAction::triggered, this, &MIDebuggerPlugin::slotAttachProcess); ac->addAction(QStringLiteral("debug_attach"), action); #endif } void MIDebuggerPlugin::setupDBus() { m_drkonqiMap = new QSignalMapper(this); connect(m_drkonqiMap, static_cast(&QSignalMapper::mapped), this, &MIDebuggerPlugin::slotDebugExternalProcess); QDBusConnectionInterface* dbusInterface = QDBusConnection::sessionBus().interface(); for (const auto &service : dbusInterface->registeredServiceNames().value()) { slotDBusServiceRegistered(service); } QDBusServiceWatcher* watcher = new QDBusServiceWatcher(this); connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &MIDebuggerPlugin::slotDBusServiceRegistered); connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &MIDebuggerPlugin::slotDBusServiceUnregistered); } void MIDebuggerPlugin::unload() { unloadToolviews(); } MIDebuggerPlugin::~MIDebuggerPlugin() { } void MIDebuggerPlugin::slotDBusServiceRegistered(const QString& service) { if (service.startsWith(QLatin1String("org.kde.drkonqi"))) { // New registration QDBusInterface* drkonqiInterface = new QDBusInterface(service, QStringLiteral("/krashinfo"), QString(), QDBusConnection::sessionBus(), this); m_drkonqis.insert(service, drkonqiInterface); connect(drkonqiInterface, SIGNAL(acceptDebuggingApplication()), m_drkonqiMap, SLOT(map())); m_drkonqiMap->setMapping(drkonqiInterface, drkonqiInterface); drkonqiInterface->call(QStringLiteral("registerDebuggingApplication"), i18n("KDevelop")); } } void MIDebuggerPlugin::slotDBusServiceUnregistered(const QString& service) { if (service.startsWith(QLatin1String("org.kde.drkonqi"))) { // Deregistration if (m_drkonqis.contains(service)) delete m_drkonqis.take(service); } } void MIDebuggerPlugin::slotDebugExternalProcess(QObject* interface) { auto dbusInterface = static_cast(interface); QDBusReply reply = dbusInterface->call(QStringLiteral("pid")); if (reply.isValid()) { attachProcess(reply.value()); QTimer::singleShot(500, this, &MIDebuggerPlugin::slotCloseDrKonqi); m_drkonqi = m_drkonqis.key(dbusInterface); } core()->uiController()->activeMainWindow()->raise(); } void MIDebuggerPlugin::slotCloseDrKonqi() { if (!m_drkonqi.isEmpty()) { QDBusInterface drkonqiInterface(m_drkonqi, QStringLiteral("/MainApplication"), QStringLiteral("org.kde.KApplication")); drkonqiInterface.call(QStringLiteral("quit")); m_drkonqi.clear(); } } ContextMenuExtension MIDebuggerPlugin::contextMenuExtension(Context* context) { ContextMenuExtension menuExt = IPlugin::contextMenuExtension(context); if (context->type() != KDevelop::Context::EditorContext) return menuExt; EditorContext *econtext = dynamic_cast(context); if (!econtext) return menuExt; QString contextIdent = econtext->currentWord(); if (!contextIdent.isEmpty()) { QString squeezed = KStringHandler::csqueeze(contextIdent, 30); QAction* action = new QAction(this); action->setText(i18n("Evaluate: %1", squeezed)); action->setWhatsThis(i18n("Evaluate expression" "

Shows the value of the expression under the cursor.

")); connect(action, &QAction::triggered, this, [this, contextIdent](){ emit addWatchVariable(contextIdent); }); menuExt.addAction(ContextMenuExtension::DebugGroup, action); action = new QAction(this); action->setText(i18n("Watch: %1", squeezed)); action->setWhatsThis(i18n("Watch expression" "

Adds the expression under the cursor to the Variables/Watch list.

")); connect(action, &QAction::triggered, this, [this, contextIdent](){ emit evaluateExpression(contextIdent); }); menuExt.addAction(ContextMenuExtension::DebugGroup, action); } return menuExt; } void MIDebuggerPlugin::slotExamineCore() { showStatusMessage(i18n("Choose a core file to examine..."), 1000); if (core()->debugController()->currentSession() != nullptr) { KMessageBox::ButtonCode answer = KMessageBox::warningYesNo( core()->uiController()->activeMainWindow(), i18n("A program is already being debugged. Do you want to abort the " "currently running debug session and continue?")); if (answer == KMessageBox::No) return; } MIExamineCoreJob *job = new MIExamineCoreJob(this, core()->runController()); core()->runController()->registerJob(job); // job->start() is called in registerJob } #if KF5SysGuard_FOUND void MIDebuggerPlugin::slotAttachProcess() { showStatusMessage(i18n("Choose a process to attach to..."), 1000); if (core()->debugController()->currentSession() != nullptr) { KMessageBox::ButtonCode answer = KMessageBox::warningYesNo( core()->uiController()->activeMainWindow(), i18n("A program is already being debugged. Do you want to abort the " "currently running debug session and continue?")); if (answer == KMessageBox::No) return; } - ProcessSelectionDialog dlg(core()->uiController()->activeMainWindow()); - if (!dlg.exec() || !dlg.pidSelected()) + QPointer dlg = new ProcessSelectionDialog(core()->uiController()->activeMainWindow()); + if (!dlg->exec() || !dlg->pidSelected()) { + delete dlg; return; + } // TODO: move check into process selection dialog - int pid = dlg.pidSelected(); + int pid = dlg->pidSelected(); + delete dlg; if (QApplication::applicationPid() == pid) KMessageBox::error(core()->uiController()->activeMainWindow(), i18n("Not attaching to process %1: cannot attach the debugger to itself.", pid)); else attachProcess(pid); } #endif void MIDebuggerPlugin::attachProcess(int pid) { MIAttachProcessJob *job = new MIAttachProcessJob(this, pid, core()->runController()); core()->runController()->registerJob(job); // job->start() is called in registerJob } QString MIDebuggerPlugin::statusName() const { return i18n("Debugger"); } void MIDebuggerPlugin::showStatusMessage(const QString& msg, int timeout) { emit showMessage(this, msg, timeout); } diff --git a/debuggers/common/midebugjobs.cpp b/debuggers/common/midebugjobs.cpp index 070787d2d0..e7c50215dc 100644 --- a/debuggers/common/midebugjobs.cpp +++ b/debuggers/common/midebugjobs.cpp @@ -1,216 +1,219 @@ /* * Common Code for Debugger Support * * Copyright 2006 Vladimir Prus * Copyright 2007 Hamish Rodda * Copyright 2009 Andreas Pakulat * Copyright 2016 Aetf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "midebugjobs.h" #include "debuglog.h" #include "dialogs/selectcoredialog.h" #include "midebugsession.h" #include "midebuggerplugin.h" #include #include #include #include #include #include #include #include #include #include +#include using namespace KDevMI; using namespace KDevelop; MIDebugJob::MIDebugJob(MIDebuggerPlugin* p, ILaunchConfiguration* launchcfg, IExecutePlugin* execute, QObject* parent) : KDevelop::OutputJob(parent) , m_launchcfg(launchcfg) , m_execute(execute) { setCapabilities(Killable); m_session = p->createSession(); connect(m_session, &MIDebugSession::inferiorStdoutLines, this, &MIDebugJob::stdoutReceived); connect(m_session, &MIDebugSession::inferiorStderrLines, this, &MIDebugJob::stderrReceived); connect(m_session, &MIDebugSession::finished, this, &MIDebugJob::done); if (launchcfg->project()) { setObjectName(i18nc("ProjectName: run configuration name", "%1: %2", launchcfg->project()->name(), launchcfg->name())); } else { setObjectName(launchcfg->name()); } } void MIDebugJob::start() { Q_ASSERT(m_execute); QString err; // check if the config is valid QString executable = m_execute->executable(m_launchcfg, err).toLocalFile(); if (!err.isEmpty()) { setError(-1); setErrorText(err); emitResult(); return; } if (!QFileInfo(executable).isExecutable()) { setError(-1); setErrorText(i18n("'%1' is not an executable", executable)); emitResult(); return; } QStringList arguments = m_execute->arguments(m_launchcfg, err); if (!err.isEmpty()) { setError(-1); setErrorText(err); emitResult(); return; } setStandardToolView(IOutputView::DebugView); setBehaviours(IOutputView::Behaviours(IOutputView::AllowUserClose) | KDevelop::IOutputView::AutoScroll); auto model = new KDevelop::OutputModel; model->setFilteringStrategy(OutputModel::NativeAppErrorFilter); setModel(model); setTitle(m_launchcfg->name()); KConfigGroup grp = m_launchcfg->config(); QString startWith = grp.readEntry(Config::StartWithEntry, QStringLiteral("ApplicationOutput")); if (startWith == QLatin1String("ApplicationOutput")) { setVerbosity(Verbose); } else { setVerbosity(Silent); } startOutput(); if (!m_session->startDebugging(m_launchcfg, m_execute)) { done(); } } bool MIDebugJob::doKill() { m_session->stopDebugger(); return true; } void MIDebugJob::stderrReceived(const QStringList& l) { if (OutputModel* m = model()) { m->appendLines(l); } } void MIDebugJob::stdoutReceived(const QStringList& l) { if (OutputModel* m = model()) { m->appendLines(l); } } OutputModel* MIDebugJob::model() { return qobject_cast(OutputJob::model()); } void MIDebugJob::done() { emitResult(); } MIExamineCoreJob::MIExamineCoreJob(MIDebuggerPlugin *plugin, QObject *parent) : KJob(parent) { setCapabilities(Killable); m_session = plugin->createSession(); connect(m_session, &MIDebugSession::finished, this, &MIExamineCoreJob::done); setObjectName(i18n("Debug core file")); } void MIExamineCoreJob::start() { - SelectCoreDialog dlg(ICore::self()->uiController()->activeMainWindow()); - if (dlg.exec() == QDialog::Rejected) { + QPointer dlg = new SelectCoreDialog(ICore::self()->uiController()->activeMainWindow()); + if (dlg->exec() == QDialog::Rejected) { done(); + delete dlg; return; } - if (!m_session->examineCoreFile(dlg.executableFile(), dlg.core())) { + if (!m_session->examineCoreFile(dlg->executableFile(), dlg->core())) { done(); } + delete dlg; } bool MIExamineCoreJob::doKill() { m_session->stopDebugger(); return true; } void MIExamineCoreJob::done() { emitResult(); } MIAttachProcessJob::MIAttachProcessJob(MIDebuggerPlugin *plugin, int pid, QObject *parent) : KJob(parent) , m_pid(pid) { setCapabilities(Killable); m_session = plugin->createSession(); connect(m_session, &MIDebugSession::finished, this, &MIAttachProcessJob::done); setObjectName(i18n("Debug process %1", pid)); } void MIAttachProcessJob::start() { if (!m_session->attachToProcess(m_pid)) { done(); } } bool MIAttachProcessJob::doKill() { m_session->stopDebugger(); return true; } void MIAttachProcessJob::done() { emitResult(); } diff --git a/documentation/qthelp/qthelpconfig.cpp b/documentation/qthelp/qthelpconfig.cpp index 3c58570975..10bc17df5c 100644 --- a/documentation/qthelp/qthelpconfig.cpp +++ b/documentation/qthelp/qthelpconfig.cpp @@ -1,354 +1,355 @@ /* This file is part of KDevelop Copyright 2010 Benjamin Port Copyright 2014 Kevin Funk Copyright 2016 Andreas Cord-Landwehr This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "qthelpconfig.h" #include #include #include +#include #include #include #include #include "ui_qthelpconfig.h" #include "ui_qthelpconfigeditdialog.h" #include "qthelp_config_shared.h" #include "debug.h" #include "qthelpplugin.h" enum Column { NameColumn, PathColumn, IconColumn, GhnsColumn, ConfigColumn }; class QtHelpConfigEditDialog : public QDialog, public Ui_QtHelpConfigEditDialog { public: explicit QtHelpConfigEditDialog(QTreeWidgetItem* modifiedItem, QtHelpConfig* parent = nullptr) : QDialog(parent) , m_modifiedItem(modifiedItem) , m_config(parent) { setupUi(this); if (modifiedItem) { setWindowTitle(i18n("Modify Entry")); } else { setWindowTitle(i18n("Add New Entry")); } qchIcon->setIcon(QStringLiteral("qtlogo")); } bool checkQtHelpFile(); void accept() override; private: QTreeWidgetItem* m_modifiedItem; QtHelpConfig* m_config; }; bool QtHelpConfigEditDialog::checkQtHelpFile() { //verify if the file is valid and if there is a name if(qchName->text().isEmpty()){ KMessageBox::error(this, i18n("Name cannot be empty.")); return false; } return m_config->checkNamespace(qchRequester->text(), m_modifiedItem); } void QtHelpConfigEditDialog::accept() { if (!checkQtHelpFile()) return; QDialog::accept(); } QtHelpConfig::QtHelpConfig(QtHelpPlugin* plugin, QWidget *parent) : KDevelop::ConfigPage(plugin, nullptr, parent) { m_configWidget = new Ui::QtHelpConfigUI; m_configWidget->setupUi(this); m_configWidget->addButton->setIcon(QIcon::fromTheme(QStringLiteral("list-add"))); connect(m_configWidget->addButton, &QPushButton::clicked, this, &QtHelpConfig::add); // Table m_configWidget->qchTable->setColumnHidden(IconColumn, true); m_configWidget->qchTable->setColumnHidden(GhnsColumn, true); m_configWidget->qchTable->model()->setHeaderData(ConfigColumn, Qt::Horizontal, QVariant()); m_configWidget->qchTable->header()->setSectionsMovable(false); m_configWidget->qchTable->header()->setStretchLastSection(false); m_configWidget->qchTable->header()->setSectionResizeMode(NameColumn, QHeaderView::Stretch); m_configWidget->qchTable->header()->setSectionResizeMode(PathColumn, QHeaderView::Stretch); m_configWidget->qchTable->header()->setSectionResizeMode(ConfigColumn, QHeaderView::Fixed); // Add GHNS button KNS3::Button *knsButton = new KNS3::Button(i18nc("Allow user to get some API documentation with GHNS", "Get New Documentation"), QStringLiteral("kdevelop-qthelp.knsrc"), m_configWidget->boxQchManage); m_configWidget->tableCtrlLayout->insertWidget(1, knsButton); connect(knsButton, &KNS3::Button::dialogFinished, this, &QtHelpConfig::knsUpdate); connect(m_configWidget->loadQtDocsCheckBox, &QCheckBox::toggled, this, static_cast(&QtHelpConfig::changed)); m_configWidget->qchSearchDir->setMode(KFile::Directory); connect(m_configWidget->qchSearchDir, &KUrlRequester::textChanged, this, &QtHelpConfig::changed); // Set availability information for QtHelp m_configWidget->messageAvailabilityQtDocs->setCloseButtonVisible(false); if(plugin->isQtHelpAvailable()) { m_configWidget->messageAvailabilityQtDocs->setVisible(false); } else { m_configWidget->messageAvailabilityQtDocs->setText( i18n("The command \"qmake -query\" could not provide a path to a QtHelp file (QCH).")); m_configWidget->loadQtDocsCheckBox->setVisible(false); } reset(); } QtHelpConfig::~QtHelpConfig() { delete m_configWidget; } KDevelop::ConfigPage::ConfigPageType QtHelpConfig::configPageType() const { return KDevelop::ConfigPage::DocumentationConfigPage; } void QtHelpConfig::apply() { QStringList iconList, nameList, pathList, ghnsList; for (int i = 0; i < m_configWidget->qchTable->topLevelItemCount(); i++) { const QTreeWidgetItem* item = m_configWidget->qchTable->topLevelItem(i); nameList << item->text(0); pathList << item->text(1); iconList << item->text(2); ghnsList << item->text(3); } QString searchDir = m_configWidget->qchSearchDir->text(); bool loadQtDoc = m_configWidget->loadQtDocsCheckBox->isChecked(); qtHelpWriteConfig(iconList, nameList, pathList, ghnsList, searchDir, loadQtDoc); static_cast(plugin())->readConfig(); } void QtHelpConfig::reset() { m_configWidget->qchTable->clear(); QStringList iconList, nameList, pathList, ghnsList; QString searchDir; bool loadQtDoc; qtHelpReadConfig(iconList, nameList, pathList, ghnsList, searchDir, loadQtDoc); const int size = qMin(qMin(iconList.size(), nameList.size()), pathList.size()); for(int i = 0; i < size; ++i) { QString ghnsStatus = ghnsList.size()>i ? ghnsList.at(i) : QStringLiteral("0"); addTableItem(iconList.at(i), nameList.at(i), pathList.at(i), ghnsStatus); } m_configWidget->qchSearchDir->setText(searchDir); m_configWidget->loadQtDocsCheckBox->setChecked(loadQtDoc); emit changed(); } void QtHelpConfig::defaults() { bool change = false; if(m_configWidget->qchTable->topLevelItemCount() > 0) { m_configWidget->qchTable->clear(); change = true; } if(!m_configWidget->loadQtDocsCheckBox->isChecked()){ m_configWidget->loadQtDocsCheckBox->setChecked(true); change = true; } if (change) { emit changed(); } } void QtHelpConfig::add() { - QtHelpConfigEditDialog dialog(nullptr, this); - if (!dialog.exec()) - return; - - QTreeWidgetItem* item = addTableItem(dialog.qchIcon->icon(), dialog.qchName->text(), dialog.qchRequester->text(), QStringLiteral("0")); - m_configWidget->qchTable->setCurrentItem(item); - emit changed(); + QPointer dialog = new QtHelpConfigEditDialog(nullptr, this); + if (dialog->exec()) { + QTreeWidgetItem* item = addTableItem(dialog->qchIcon->icon(), dialog->qchName->text(), dialog->qchRequester->text(), QStringLiteral("0")); + m_configWidget->qchTable->setCurrentItem(item); + emit changed(); + } + delete dialog; } void QtHelpConfig::modify(QTreeWidgetItem* item) { if (!item) return; - QtHelpConfigEditDialog dialog(item, this); + QPointer dialog = new QtHelpConfigEditDialog(item, this); if (item->text(GhnsColumn) != QLatin1String("0")) { - dialog.qchRequester->setText(i18n("Documentation provided by GHNS")); - dialog.qchRequester->setEnabled(false); + dialog->qchRequester->setText(i18n("Documentation provided by GHNS")); + dialog->qchRequester->setEnabled(false); } else { - dialog.qchRequester->setText(item->text(PathColumn)); - dialog.qchRequester->setEnabled(true); - } - dialog.qchName->setText(item->text(NameColumn)); - dialog.qchIcon->setIcon(item->text(IconColumn)); - if (!dialog.exec()) { - return; + dialog->qchRequester->setText(item->text(PathColumn)); + dialog->qchRequester->setEnabled(true); } + dialog->qchName->setText(item->text(NameColumn)); + dialog->qchIcon->setIcon(item->text(IconColumn)); + if (dialog->exec()) { + item->setIcon(NameColumn, QIcon(dialog->qchIcon->icon())); + item->setText(NameColumn, dialog->qchName->text()); + item->setText(IconColumn, dialog->qchIcon->icon()); + if(item->text(GhnsColumn) == QLatin1String("0")) { + item->setText(PathColumn, dialog->qchRequester->text()); + } - item->setIcon(NameColumn, QIcon(dialog.qchIcon->icon())); - item->setText(NameColumn, dialog.qchName->text()); - item->setText(IconColumn, dialog.qchIcon->icon()); - if(item->text(GhnsColumn) == QLatin1String("0")) { - item->setText(PathColumn, dialog.qchRequester->text()); + emit changed(); } - emit changed(); + delete dialog; } bool QtHelpConfig::checkNamespace(const QString& filename, QTreeWidgetItem* modifiedItem) { QString qtHelpNamespace = QHelpEngineCore::namespaceName(filename); if (qtHelpNamespace.isEmpty()) { // Open error message (not valid Qt Compressed Help file) KMessageBox::error(this, i18n("Qt Compressed Help file is not valid.")); return false; } // verify if it's the namespace it's not already in the list for(int i=0; i < m_configWidget->qchTable->topLevelItemCount(); i++) { const QTreeWidgetItem* item = m_configWidget->qchTable->topLevelItem(i); if (item != modifiedItem){ if (qtHelpNamespace == QHelpEngineCore::namespaceName(item->text(PathColumn))) { // Open error message, documentation already imported KMessageBox::error(this, i18n("Documentation already imported")); return false; } } } return true; } void QtHelpConfig::remove(QTreeWidgetItem* item) { if (!item) return; delete item; emit changed(); } void QtHelpConfig::knsUpdate(KNS3::Entry::List list) { if (list.isEmpty()) return; foreach (const KNS3::Entry& e, list) { if(e.status() == KNS3::Entry::Installed) { if(e.installedFiles().size() == 1) { QString filename = e.installedFiles().at(0); if(checkNamespace(filename, nullptr)){ QTreeWidgetItem* item = addTableItem(QStringLiteral("documentation"), e.name(), filename, QStringLiteral("1")); m_configWidget->qchTable->setCurrentItem(item); } else { qCDebug(QTHELP) << "namespace error"; } } } else if(e.status() == KNS3::Entry::Deleted) { if(e.uninstalledFiles().size() == 1) { for(int i=0; i < m_configWidget->qchTable->topLevelItemCount(); i++) { QTreeWidgetItem* item = m_configWidget->qchTable->topLevelItem(i); if (e.uninstalledFiles().at(0) == item->text(PathColumn)) { delete item; break; } } } } } emit changed(); } QString QtHelpConfig::name() const { return i18n("Qt Help"); } QString QtHelpConfig::fullName() const { return i18n("Configure Qt Help Settings"); } QIcon QtHelpConfig::icon() const { return QIcon::fromTheme(QStringLiteral("qtlogo")); } QTreeWidgetItem * QtHelpConfig::addTableItem(const QString &icon, const QString &name, const QString &path, const QString &ghnsStatus) { QTreeWidgetItem *item = new QTreeWidgetItem(m_configWidget->qchTable); item->setIcon(NameColumn, QIcon::fromTheme(icon)); item->setText(NameColumn, name); item->setToolTip(NameColumn, name); item->setText(PathColumn, path); item->setToolTip(PathColumn, path); item->setText(IconColumn, icon); item->setText(GhnsColumn, ghnsStatus); QWidget *ctrlWidget = new QWidget(item->treeWidget()); ctrlWidget->setLayout(new QHBoxLayout(ctrlWidget)); QToolButton *modifyBtn = new QToolButton(item->treeWidget()); modifyBtn->setIcon(QIcon::fromTheme(QStringLiteral("document-edit"))); modifyBtn->setToolTip(i18n("Modify")); connect(modifyBtn, &QPushButton::clicked, this, [=](){ modify(item); }); QToolButton *removeBtn = new QToolButton(item->treeWidget()); removeBtn->setIcon(QIcon::fromTheme(QStringLiteral("entry-delete"))); removeBtn->setToolTip(i18n("Delete")); if (item->text(GhnsColumn) != QLatin1String("0")) { // KNS3 currently does not provide API to uninstall entries // just removing the files results in wrong installed states in the KNS3 dialog // TODO: add API to KNS to remove files without UI interaction removeBtn->setEnabled(false); removeBtn->setToolTip(i18n("Please uninstall this via GHNS")); } else { connect(removeBtn, &QPushButton::clicked, this, [=](){ remove(item); }); } ctrlWidget->layout()->addWidget(modifyBtn); ctrlWidget->layout()->addWidget(removeBtn); m_configWidget->qchTable->setItemWidget(item, ConfigColumn, ctrlWidget); return item; } diff --git a/languages/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp b/languages/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp index d76d75b8cc..13091de1f2 100644 --- a/languages/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp +++ b/languages/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp @@ -1,305 +1,310 @@ /************************************************************************ * * * Copyright 2010 Andreas Pakulat * * Copyright 2014 Sergey Kalinichev * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see . * ************************************************************************/ #include "projectpathswidget.h" #include #include +#include #include #include #include #include "../compilerprovider/compilerprovider.h" #include "../compilerprovider/settingsmanager.h" #include "ui_projectpathswidget.h" #include "ui_batchedit.h" #include "projectpathsmodel.h" #include using namespace KDevelop; namespace { enum PageType { IncludesPage, DefinesPage, ParserArgumentsPage }; } ProjectPathsWidget::ProjectPathsWidget( QWidget* parent ) : QWidget(parent), ui(new Ui::ProjectPathsWidget), pathsModel(new ProjectPathsModel(this)) { ui->setupUi( this ); ui->addPath->setIcon(QIcon::fromTheme(QStringLiteral("list-add"))); ui->removePath->setIcon(QIcon::fromTheme(QStringLiteral("list-remove"))); ui->batchEdit->setIcon(QIcon::fromTheme(QStringLiteral("format-list-unordered"))); // hack taken from kurlrequester, make the buttons a bit less in height so they better match the url-requester ui->addPath->setFixedHeight( ui->projectPaths->sizeHint().height() ); ui->removePath->setFixedHeight( ui->projectPaths->sizeHint().height() ); connect( ui->addPath, &QPushButton::clicked, this, &ProjectPathsWidget::addProjectPath ); connect( ui->removePath, &QPushButton::clicked, this, &ProjectPathsWidget::deleteProjectPath ); connect( ui->batchEdit, &QPushButton::clicked, this, &ProjectPathsWidget::batchEdit ); ui->projectPaths->setModel( pathsModel ); connect( ui->projectPaths, static_cast(&KComboBox::currentIndexChanged), this, &ProjectPathsWidget::projectPathSelected ); connect( pathsModel, &ProjectPathsModel::dataChanged, this, &ProjectPathsWidget::changed ); connect( pathsModel, &ProjectPathsModel::rowsInserted, this, &ProjectPathsWidget::changed ); connect( pathsModel, &ProjectPathsModel::rowsRemoved, this, &ProjectPathsWidget::changed ); connect( ui->compiler, static_cast(&QComboBox::activated), this, &ProjectPathsWidget::changed ); connect( ui->compiler, static_cast(&QComboBox::activated), this, &ProjectPathsWidget::changeCompilerForPath ); connect( ui->includesWidget, static_cast(&IncludesWidget::includesChanged), this, &ProjectPathsWidget::includesChanged ); connect( ui->definesWidget, static_cast(&DefinesWidget::definesChanged), this, &ProjectPathsWidget::definesChanged ); connect(ui->languageParameters, &QTabWidget::currentChanged, this, &ProjectPathsWidget::tabChanged); connect(ui->parserWidget, &ParserWidget::changed, this, &ProjectPathsWidget::parserArgumentsChanged); tabChanged(IncludesPage); } QVector ProjectPathsWidget::paths() const { return pathsModel->paths(); } void ProjectPathsWidget::setPaths( const QVector& paths ) { bool b = blockSignals( true ); clear(); pathsModel->setPaths( paths ); blockSignals( b ); ui->projectPaths->setCurrentIndex(0); // at least a project root item is present ui->languageParameters->setCurrentIndex(0); // Set compilers ui->compiler->clear(); auto settings = SettingsManager::globalInstance(); auto compilers = settings->provider()->compilers(); for (int i = 0 ; i < compilers.count(); ++i) { Q_ASSERT(compilers[i]); if (!compilers[i]) { continue; } ui->compiler->addItem(compilers[i]->name()); QVariant val; val.setValue(compilers[i]); ui->compiler->setItemData(i, val); } projectPathSelected(0); updateEnablements(); } void ProjectPathsWidget::definesChanged( const Defines& defines ) { qCDebug(DEFINESANDINCLUDES) << "defines changed"; updatePathsModel( QVariant::fromValue(defines), ProjectPathsModel::DefinesDataRole ); } void ProjectPathsWidget::includesChanged( const QStringList& includes ) { qCDebug(DEFINESANDINCLUDES) << "includes changed"; updatePathsModel( includes, ProjectPathsModel::IncludesDataRole ); } void ProjectPathsWidget::parserArgumentsChanged() { updatePathsModel(QVariant::fromValue(ui->parserWidget->parserArguments()), ProjectPathsModel::ParserArgumentsRole); } void ProjectPathsWidget::updatePathsModel(const QVariant& newData, int role) { QModelIndex idx = pathsModel->index( ui->projectPaths->currentIndex(), 0, QModelIndex() ); if( idx.isValid() ) { bool b = pathsModel->setData( idx, newData, role ); if( b ) { emit changed(); } } } void ProjectPathsWidget::projectPathSelected( int index ) { if( index < 0 && pathsModel->rowCount() > 0 ) { index = 0; } Q_ASSERT(index >= 0); const QModelIndex midx = pathsModel->index( index, 0 ); ui->includesWidget->setIncludes( pathsModel->data( midx, ProjectPathsModel::IncludesDataRole ).toStringList() ); ui->definesWidget->setDefines( pathsModel->data( midx, ProjectPathsModel::DefinesDataRole ).value() ); Q_ASSERT(pathsModel->data(midx, ProjectPathsModel::CompilerDataRole).value()); ui->compiler->setCurrentText(pathsModel->data(midx, ProjectPathsModel::CompilerDataRole).value()->name()); ui->parserWidget->setParserArguments(pathsModel->data(midx, ProjectPathsModel::ParserArgumentsRole).value()); updateEnablements(); } void ProjectPathsWidget::clear() { bool sigDisabled = ui->projectPaths->blockSignals( true ); pathsModel->setPaths({}); ui->includesWidget->clear(); ui->definesWidget->clear(); updateEnablements(); ui->projectPaths->blockSignals( sigDisabled ); } void ProjectPathsWidget::addProjectPath() { const QUrl directory = pathsModel->data(pathsModel->index(0, 0), ProjectPathsModel::FullUrlDataRole).value(); - QFileDialog dlg(this, i18n("Select Project Path"), directory.toLocalFile()); - dlg.setFileMode(QFileDialog::Directory); - dlg.setOption(QFileDialog::ShowDirsOnly); - dlg.exec(); - pathsModel->addPath(dlg.selectedUrls().value(0)); - ui->projectPaths->setCurrentIndex(pathsModel->rowCount() - 1); - updateEnablements(); + QPointer dlg = new QFileDialog(this, i18n("Select Project Path"), directory.toLocalFile()); + dlg->setFileMode(QFileDialog::Directory); + dlg->setOption(QFileDialog::ShowDirsOnly); + if (dlg->exec()) { + pathsModel->addPath(dlg->selectedUrls().value(0)); + ui->projectPaths->setCurrentIndex(pathsModel->rowCount() - 1); + updateEnablements(); + } + delete dlg; } void ProjectPathsWidget::deleteProjectPath() { const QModelIndex idx = pathsModel->index( ui->projectPaths->currentIndex(), 0 ); if( KMessageBox::questionYesNo( this, i18n("Are you sure you want to remove the configuration for the path '%1'?", pathsModel->data( idx, Qt::DisplayRole ).toString() ), QStringLiteral("Remove Path Configuration") ) == KMessageBox::Yes ) { pathsModel->removeRows( ui->projectPaths->currentIndex(), 1 ); } updateEnablements(); } void ProjectPathsWidget::setProject(KDevelop::IProject* w_project) { pathsModel->setProject( w_project ); ui->includesWidget->setProject( w_project ); } void ProjectPathsWidget::updateEnablements() { // Disable removal of the project root entry which is always first in the list ui->removePath->setEnabled( ui->projectPaths->currentIndex() > 0 ); } void ProjectPathsWidget::batchEdit() { Ui::BatchEdit be; - QDialog dialog(this); - be.setupUi(&dialog); + QPointer dialog = new QDialog(this); + be.setupUi(dialog); const int index = qMax(ui->projectPaths->currentIndex(), 0); const QModelIndex midx = pathsModel->index(index, 0); if (!midx.isValid()) { return; } bool includesTab = ui->languageParameters->currentIndex() == 0; if (includesTab) { auto includes = pathsModel->data(midx, ProjectPathsModel::IncludesDataRole).toStringList(); be.textEdit->setPlainText(includes.join(QStringLiteral("\n"))); - dialog.setWindowTitle(i18n("Edit include directories/files")); + dialog->setWindowTitle(i18n("Edit include directories/files")); } else { auto defines = pathsModel->data(midx, ProjectPathsModel::DefinesDataRole).value(); for (auto it = defines.constBegin(); it != defines.constEnd(); it++) { be.textEdit->appendPlainText(it.key() + "=" + it.value()); } - dialog.setWindowTitle(i18n("Edit defined macros")); + dialog->setWindowTitle(i18n("Edit defined macros")); } - if (dialog.exec() != QDialog::Accepted) { + if (dialog->exec() != QDialog::Accepted) { + delete dialog; return; } + delete dialog; if (includesTab) { auto includes = be.textEdit->toPlainText().split('\n', QString::SkipEmptyParts); for (auto& s : includes) { s = s.trimmed(); } pathsModel->setData(midx, includes, ProjectPathsModel::IncludesDataRole); } else { auto list = be.textEdit->toPlainText().split('\n', QString::SkipEmptyParts); Defines defines; for (auto& d : list) { //This matches: a=b, a=, a QRegExp r("^([^=]+)(=(.*))?$"); if (!r.exactMatch(d)) { continue; } defines[r.cap(1).trimmed()] = r.cap(3).trimmed(); } pathsModel->setData(midx, QVariant::fromValue(defines), ProjectPathsModel::DefinesDataRole); } projectPathSelected(index); } void ProjectPathsWidget::setCurrentCompiler(const QString& name) { for (int i = 0 ; i < ui->compiler->count(); ++i) { if(ui->compiler->itemText(i) == name) { ui->compiler->setCurrentIndex(i); } } } CompilerPointer ProjectPathsWidget::currentCompiler() const { return ui->compiler->itemData(ui->compiler->currentIndex()).value(); } void ProjectPathsWidget::tabChanged(int idx) { if (idx == ParserArgumentsPage) { ui->batchEdit->setVisible(false); ui->compilerBox->setVisible(true); ui->configureLabel->setText(i18n("Configure C/C++ parser")); } else { ui->batchEdit->setVisible(true); ui->compilerBox->setVisible(false); ui->configureLabel->setText(i18n("Configure which macros and include directories/files will be added to the parser during project parsing:")); } } void ProjectPathsWidget::changeCompilerForPath() { for (int idx = 0; idx < pathsModel->rowCount(); idx++) { const QModelIndex midx = pathsModel->index(idx, 0); if (pathsModel->data(midx, Qt::DisplayRole) == ui->projectPaths->currentText()) { pathsModel->setData(midx, QVariant::fromValue(currentCompiler()), ProjectPathsModel::CompilerDataRole); break; } } } diff --git a/projectmanagers/qmake/qmakeutils.cpp b/projectmanagers/qmake/qmakeutils.cpp index 8316fef98e..bf2ed0e866 100644 --- a/projectmanagers/qmake/qmakeutils.cpp +++ b/projectmanagers/qmake/qmakeutils.cpp @@ -1,82 +1,85 @@ /* * Copyright 2015 Kevin Funk * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "qmakeutils.h" #include #include "qmakebuilddirchooserdialog.h" #include "qmakeconfig.h" #include #include #include +#include #include using namespace KDevelop; bool QMakeUtils::checkForNeedingConfigure(IProject* project) { Q_ASSERT(project); qCDebug(KDEV_QMAKE) << "Checking whether" << project->name() << "needs a configure run"; const auto buildDir = QMakeConfig::buildDirFromSrc(project, project->path()); if (!buildDir.isValid()) { - QMakeBuildDirChooserDialog chooser(project); - if (chooser.exec() == QDialog::Rejected) { + QPointer chooser = new QMakeBuildDirChooserDialog(project); + if (chooser->exec() == QDialog::Rejected) { + delete chooser; return false; // cancelled, can't configure => false } + delete chooser; } qCDebug(KDEV_QMAKE) << "Build directory for" << project->name() << "is" << buildDir; if (!QMakeConfig::isConfigured(project)) { return true; } const QString qmakeExecutable = QMakeConfig::qmakeExecutable(project); if (qmakeExecutable.isEmpty()) { return true; } const QHash vars = queryQMake(project); if (vars.isEmpty()) { return true; } if (QMakeConfig::findBasicMkSpec(vars).isEmpty()) { return true; } if (!QFile::exists(buildDir.toLocalFile())) { qCDebug(KDEV_QMAKE) << "build dir" << buildDir << "configured, but does not exist yet"; return true; } qCDebug(KDEV_QMAKE) << "No configure needed for project" << project->name(); return false; } QHash QMakeUtils::queryQMake(IProject* project) { if (!project->path().toUrl().isLocalFile()) return QHash(); return QMakeConfig::queryQMake(QMakeConfig::qmakeExecutable(project)); } diff --git a/providers/ghprovider/ghdialog.cpp b/providers/ghprovider/ghdialog.cpp index 39ccad1967..9c273d6132 100644 --- a/providers/ghprovider/ghdialog.cpp +++ b/providers/ghprovider/ghdialog.cpp @@ -1,183 +1,185 @@ /* This file is part of KDevelop * * Copyright (C) 2012-2013 Miquel Sabaté * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include +#include #include #include #include #include #include #include static QString invalidAccountText() { return i18n("You have not authorized KDevelop to use your GitHub account. " "If you authorize KDevelop, you will be able to fetch your " "public/private repositories and the repositories from your " "organizations."); } static QString tokenLinkStatementText() { return i18nc("%1 is the URL with the GitHub token settings", "You can check the authorization for this application and " "others at %1", QStringLiteral("https://github.com/settings/tokens.")); } namespace gh { Dialog::Dialog(QWidget *parent, Account *account) : QDialog(parent) , m_account(account) { auto mainWidget = new QWidget(this); auto mainLayout = new QVBoxLayout; setLayout(mainLayout); mainLayout->addWidget(mainWidget); auto buttonBox = new QDialogButtonBox(); if (m_account->validAccount()) { m_text = new QLabel(i18n("You are logged in as %1.
%2", m_account->name(), tokenLinkStatementText()), this); auto logOutButton = new QPushButton; logOutButton->setText(i18n("Log Out")); logOutButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel"))); buttonBox->addButton(logOutButton, QDialogButtonBox::ActionRole); connect(logOutButton, &QPushButton::clicked, this, &Dialog::revokeAccess); auto forceSyncButton = new QPushButton; forceSyncButton->setText(i18n("Force Sync")); forceSyncButton->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); buttonBox->addButton(forceSyncButton, QDialogButtonBox::ActionRole); connect(forceSyncButton, &QPushButton::clicked, this, &Dialog::syncUser); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); } else { m_text = new QLabel(invalidAccountText(), this); buttonBox->addButton(QDialogButtonBox::Cancel); auto authorizeButton = new QPushButton; buttonBox->addButton(authorizeButton, QDialogButtonBox::ActionRole); authorizeButton->setText(i18n("Authorize")); authorizeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok"))); connect(authorizeButton, &QPushButton::clicked, this, &Dialog::authorizeClicked); } m_text->setWordWrap(true); m_text->setOpenExternalLinks(true); setMinimumWidth(350); mainLayout->addWidget(m_text); mainLayout->addWidget(buttonBox); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); setWindowTitle(i18n("GitHub Account")); } void Dialog::authorizeClicked() { - KPasswordDialog dlg(this, KPasswordDialog::ShowUsernameLine); - dlg.setPrompt(i18n("Enter a login and a password")); - if(!dlg.exec()) - return; - - m_text->setAlignment(Qt::AlignCenter); - m_text->setText(i18n("Waiting for response")); - m_account->setName(dlg.username()); - - Resource *rs = m_account->resource(); - rs->authenticate(dlg.username(), dlg.password()); - connect(rs, &Resource::authenticated, - this, &Dialog::authorizeResponse); + QPointer dlg = new KPasswordDialog(this, KPasswordDialog::ShowUsernameLine); + dlg->setPrompt(i18n("Enter a login and a password")); + if(dlg->exec()) { + m_text->setAlignment(Qt::AlignCenter); + m_text->setText(i18n("Waiting for response")); + m_account->setName(dlg->username()); + + Resource *rs = m_account->resource(); + rs->authenticate(dlg->username(), dlg->password()); + connect(rs, &Resource::authenticated, + this, &Dialog::authorizeResponse); + } + delete dlg; } void Dialog::authorizeResponse(const QByteArray &id, const QByteArray &token, const QString &tokenName) { Q_UNUSED(tokenName); Resource *rs = m_account->resource(); disconnect(rs, &Resource::authenticated, this, &Dialog::authorizeResponse); if (id.isEmpty()) { m_text->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); m_text->setText(invalidAccountText()); m_account->setName(QString()); KMessageBox::sorry(this, i18n("Authentication failed. Please try again.\n\n" "Could not create token: \"%1\"\n%2", tokenName, tokenLinkStatementText()), i18n("GitHub Authorization Failed")); return; } else{ KMessageBox::information(this, i18n("Authentication succeeded.\n\n" "Created token: \"%1\"\n%2", tokenName, tokenLinkStatementText()), i18n("GitHub Account Authorized")); } m_account->saveToken(id, token); syncUser(); } void Dialog::syncUser() { Resource *rs = m_account->resource(); connect(rs, &Resource::orgsUpdated, this, &Dialog::updateOrgs); m_text->setAlignment(Qt::AlignCenter); m_text->setText(i18n("Waiting for response")); rs->getOrgs(m_account->token()); } void Dialog::updateOrgs(const QStringList& orgs) { Resource *rs = m_account->resource(); disconnect(rs, &Resource::orgsUpdated, this, &Dialog::updateOrgs); if (!orgs.isEmpty()) m_account->setOrgs(orgs); emit shouldUpdate(); close(); } void Dialog::revokeAccess() { - KPasswordDialog dlg(this); - dlg.setPrompt(i18n("Please, write your password here.")); - if(!dlg.exec()) - return; - m_account->invalidate(dlg.password()); - emit shouldUpdate(); - close(); + QPointer dlg = new KPasswordDialog(this); + dlg->setPrompt(i18n("Please, write your password here.")); + if(dlg->exec()) { + m_account->invalidate(dlg->password()); + emit shouldUpdate(); + close(); + } + delete dlg; } } // End of namespace gh