1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "debuggerdialogs.h"
36 #include "debuggerconstants.h"
37 #include "cdb/cdbengine.h"
39 #include "ui_attachcoredialog.h"
40 #include "ui_attachexternaldialog.h"
41 #include "ui_attachtcfdialog.h"
42 #include "ui_startexternaldialog.h"
43 #include "ui_startremotedialog.h"
44 #include "ui_startremoteenginedialog.h"
47 # include "shared/dbgwinutils.h"
50 #include <coreplugin/icore.h>
51 #include <utils/synchronousprocess.h>
52 #include <utils/historycompleter.h>
53 #include <utils/qtcassert.h>
55 #include <QtCore/QDebug>
56 #include <QtCore/QProcess>
57 #include <QtCore/QRegExp>
58 #include <QtCore/QDir>
59 #include <QtCore/QFile>
60 #include <QtCore/QCoreApplication>
61 #include <QtGui/QStandardItemModel>
62 #include <QtGui/QHeaderView>
63 #include <QtGui/QFileDialog>
64 #include <QtGui/QPushButton>
65 #include <QtGui/QProxyModel>
66 #include <QtGui/QSortFilterProxyModel>
67 #include <QtGui/QMessageBox>
68 #include <QtGui/QGroupBox>
70 using namespace Utils;
75 bool operator<(const ProcData &p1, const ProcData &p2)
77 return p1.name < p2.name;
80 // A filterable process list model
81 class ProcessListFilterModel : public QSortFilterProxyModel
84 explicit ProcessListFilterModel(QObject *parent);
85 QString processIdAt(const QModelIndex &index) const;
86 QString executableForPid(const QString& pid) const;
88 void populate(QList<ProcData> processes, const QString &excludePid);
91 enum { ProcessImageRole = Qt::UserRole, ProcessNameRole };
93 bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
95 QStandardItemModel *m_model;
98 ProcessListFilterModel::ProcessListFilterModel(QObject *parent)
99 : QSortFilterProxyModel(parent),
100 m_model(new QStandardItemModel(this))
103 columns << AttachExternalDialog::tr("Process ID")
104 << AttachExternalDialog::tr("Name")
105 << AttachExternalDialog::tr("State");
106 m_model->setHorizontalHeaderLabels(columns);
107 setSourceModel(m_model);
108 setFilterCaseSensitivity(Qt::CaseInsensitive);
109 setFilterKeyColumn(1);
112 bool ProcessListFilterModel::lessThan(const QModelIndex &left,
113 const QModelIndex &right) const
115 const QString l = sourceModel()->data(left).toString();
116 const QString r = sourceModel()->data(right).toString();
117 if (left.column() == 0)
118 return l.toInt() < r.toInt();
122 QString ProcessListFilterModel::processIdAt(const QModelIndex &index) const
124 if (index.isValid()) {
125 const QModelIndex index0 = mapToSource(index);
126 QModelIndex siblingIndex = index0.sibling(index0.row(), 0);
127 if (const QStandardItem *item = m_model->itemFromIndex(siblingIndex))
133 QString ProcessListFilterModel::executableForPid(const QString &pid) const
135 const int rowCount = m_model->rowCount();
136 for (int r = 0; r < rowCount; r++) {
137 const QStandardItem *item = m_model->item(r, 0);
138 if (item->text() == pid) {
139 QString name = item->data(ProcessImageRole).toString();
141 name = item->data(ProcessNameRole).toString();
148 void ProcessListFilterModel::populate
149 (QList<ProcData> processes, const QString &excludePid)
151 qStableSort(processes);
153 if (const int rowCount = m_model->rowCount())
154 m_model->removeRows(0, rowCount);
156 QStandardItem *root = m_model->invisibleRootItem();
157 foreach (const ProcData &proc, processes) {
158 QList<QStandardItem *> row;
159 row.append(new QStandardItem(proc.ppid));
160 QString name = proc.image.isEmpty() ? proc.name : proc.image;
161 row.back()->setData(name, ProcessImageRole);
162 row.append(new QStandardItem(proc.name));
163 row.back()->setToolTip(proc.image);
164 row.append(new QStandardItem(proc.state));
166 if (proc.ppid == excludePid)
167 foreach (QStandardItem *item, row)
168 item->setEnabled(false);
169 root->appendRow(row);
174 ///////////////////////////////////////////////////////////////////////
178 ///////////////////////////////////////////////////////////////////////
180 AttachCoreDialog::AttachCoreDialog(QWidget *parent)
181 : QDialog(parent), m_ui(new Ui::AttachCoreDialog)
185 m_ui->execFileName->setExpectedKind(PathChooser::File);
186 m_ui->execFileName->setPromptDialogTitle(tr("Select Executable"));
188 m_ui->coreFileName->setExpectedKind(PathChooser::File);
189 m_ui->coreFileName->setPromptDialogTitle(tr("Select Core File"));
191 m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
193 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
194 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
197 AttachCoreDialog::~AttachCoreDialog()
202 QString AttachCoreDialog::executableFile() const
204 return m_ui->execFileName->path();
207 void AttachCoreDialog::setExecutableFile(const QString &fileName)
209 m_ui->execFileName->setPath(fileName);
212 QString AttachCoreDialog::coreFile() const
214 return m_ui->coreFileName->path();
217 void AttachCoreDialog::setCoreFile(const QString &fileName)
219 m_ui->coreFileName->setPath(fileName);
223 ///////////////////////////////////////////////////////////////////////
225 // Process model helpers
227 ///////////////////////////////////////////////////////////////////////
231 static bool isUnixProcessId(const QString &procname)
233 for (int i = 0; i != procname.size(); ++i)
234 if (!procname.at(i).isDigit())
240 // Determine UNIX processes by running ps
241 static QList<ProcData> unixProcessListPS()
244 static const char formatC[] = "pid state command";
246 static const char formatC[] = "pid,state,cmd";
251 args << QLatin1String("-e") << QLatin1String("-o") << QLatin1String(formatC);
252 psProcess.start(QLatin1String("ps"), args);
253 if (!psProcess.waitForStarted())
256 if (!SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, 0, false))
258 // Split "457 S+ /Users/foo.app"
259 const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
260 const int lineCount = lines.size();
261 const QChar blank = QLatin1Char(' ');
262 for (int l = 1; l < lineCount; l++) { // Skip header
263 const QString line = lines.at(l).simplified();
264 const int pidSep = line.indexOf(blank);
265 const int cmdSep = pidSep != -1 ? line.indexOf(blank, pidSep + 1) : -1;
268 procData.ppid = line.left(pidSep);
269 procData.state = line.mid(pidSep + 1, cmdSep - pidSep - 1);
270 procData.name = line.mid(cmdSep + 1);
271 rc.push_back(procData);
277 // Determine UNIX processes by reading "/proc". Default to ps if
279 static QList<ProcData> unixProcessList()
281 const QDir procDir(QLatin1String("/proc/"));
282 if (!procDir.exists())
283 return unixProcessListPS();
285 const QStringList procIds = procDir.entryList();
286 if (procIds.isEmpty())
288 foreach (const QString &procId, procIds) {
289 if (!isUnixProcessId(procId))
291 QString filename = QLatin1String("/proc/");
293 filename += QLatin1String("/stat");
294 QFile file(filename);
295 if (!file.open(QIODevice::ReadOnly))
296 continue; // process may have exited
298 const QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
301 proc.name = data.at(1);
302 if (proc.name.startsWith(QLatin1Char('(')) && proc.name.endsWith(QLatin1Char(')'))) {
303 proc.name.truncate(proc.name.size() - 1);
304 proc.name.remove(0, 1);
306 proc.state = data.at(2);
314 static QList<ProcData> processList()
317 return winProcessList();
319 return unixProcessList();
324 ///////////////////////////////////////////////////////////////////////
326 // AttachExternalDialog
328 ///////////////////////////////////////////////////////////////////////
330 AttachExternalDialog::AttachExternalDialog(QWidget *parent)
332 m_selfPid(QString::number(QCoreApplication::applicationPid())),
333 m_ui(new Ui::AttachExternalDialog),
334 m_model(new ProcessListFilterModel(this))
337 okButton()->setDefault(true);
338 okButton()->setEnabled(false);
340 m_ui->procView->setModel(m_model);
341 m_ui->procView->setSortingEnabled(true);
342 m_ui->procView->sortByColumn(1, Qt::AscendingOrder);
344 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
345 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
346 QPushButton *refreshButton = new QPushButton(tr("Refresh"));
347 connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
348 m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
349 m_ui->filterWidget->setFocus(Qt::TabFocusReason);
351 m_ui->procView->setAlternatingRowColors(true);
352 m_ui->procView->setRootIsDecorated(false);
353 m_ui->procView->setUniformRowHeights(true);
355 // Do not use activated, will be single click in Oxygen
356 connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
357 this, SLOT(procSelected(QModelIndex)));
358 connect(m_ui->procView, SIGNAL(clicked(QModelIndex)),
359 this, SLOT(procClicked(QModelIndex)));
360 connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)),
361 this, SLOT(pidChanged(QString)));
362 connect(m_ui->filterWidget, SIGNAL(filterChanged(QString)),
363 this, SLOT(setFilterString(QString)));
366 setMinimumHeight(500);
367 rebuildProcessList();
370 AttachExternalDialog::~AttachExternalDialog()
375 void AttachExternalDialog::setFilterString(const QString &filter)
377 m_model->setFilterFixedString(filter);
378 // Activate the line edit if there's a unique filtered process.
380 if (m_model->rowCount(QModelIndex()) == 1)
381 processId = m_model->processIdAt(m_model->index(0, 0, QModelIndex()));
382 m_ui->pidLineEdit->setText(processId);
383 pidChanged(processId);
386 QPushButton *AttachExternalDialog::okButton() const
388 return m_ui->buttonBox->button(QDialogButtonBox::Ok);
391 void AttachExternalDialog::rebuildProcessList()
393 m_model->populate(processList(), m_selfPid);
394 m_ui->procView->expandAll();
395 m_ui->procView->resizeColumnToContents(0);
396 m_ui->procView->resizeColumnToContents(1);
399 void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex)
401 const QString processId = m_model->processIdAt(proxyIndex);
402 if (!processId.isEmpty()) {
403 m_ui->pidLineEdit->setText(processId);
404 if (okButton()->isEnabled())
405 okButton()->animateClick();
409 void AttachExternalDialog::procClicked(const QModelIndex &proxyIndex)
411 const QString processId = m_model->processIdAt(proxyIndex);
412 if (!processId.isEmpty())
413 m_ui->pidLineEdit->setText(processId);
416 QString AttachExternalDialog::attachPIDText() const
418 return m_ui->pidLineEdit->text().trimmed();
421 qint64 AttachExternalDialog::attachPID() const
423 return attachPIDText().toLongLong();
426 QString AttachExternalDialog::executable() const
428 // Search pid in model in case the user typed in the PID.
429 return m_model->executableForPid(attachPIDText());
432 void AttachExternalDialog::pidChanged(const QString &pid)
434 bool enabled = !pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid;
435 okButton()->setEnabled(enabled);
438 void AttachExternalDialog::accept()
441 const qint64 pid = attachPID();
442 if (pid && isWinProcessBeingDebugged(pid)) {
443 QMessageBox::warning(this, tr("Process Already Under Debugger Control"),
444 tr("The process %1 is already under the control of a debugger.\n"
445 "Qt Creator cannot attach to it.").arg(pid));
453 ///////////////////////////////////////////////////////////////////////
457 ///////////////////////////////////////////////////////////////////////
459 AttachTcfDialog::AttachTcfDialog(QWidget *parent)
461 m_ui(new Ui::AttachTcfDialog)
464 m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
465 m_ui->serverStartScript->setExpectedKind(PathChooser::File);
466 m_ui->serverStartScript->setPromptDialogTitle(tr("Select Executable"));
468 connect(m_ui->useServerStartScriptCheckBox, SIGNAL(toggled(bool)),
469 this, SLOT(updateState()));
471 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
472 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
477 AttachTcfDialog::~AttachTcfDialog()
482 void AttachTcfDialog::setRemoteChannel(const QString &channel)
484 m_ui->channelLineEdit->setText(channel);
487 QString AttachTcfDialog::remoteChannel() const
489 return m_ui->channelLineEdit->text();
492 void AttachTcfDialog::setRemoteArchitectures(const QStringList &list)
494 m_ui->architectureComboBox->clear();
495 if (!list.isEmpty()) {
496 m_ui->architectureComboBox->insertItems(0, list);
497 m_ui->architectureComboBox->setCurrentIndex(0);
501 void AttachTcfDialog::setRemoteArchitecture(const QString &arch)
503 int index = m_ui->architectureComboBox->findText(arch);
505 m_ui->architectureComboBox->setCurrentIndex(index);
508 QString AttachTcfDialog::remoteArchitecture() const
510 int index = m_ui->architectureComboBox->currentIndex();
511 return m_ui->architectureComboBox->itemText(index);
514 void AttachTcfDialog::setServerStartScript(const QString &scriptName)
516 m_ui->serverStartScript->setPath(scriptName);
519 QString AttachTcfDialog::serverStartScript() const
521 return m_ui->serverStartScript->path();
524 void AttachTcfDialog::setUseServerStartScript(bool on)
526 m_ui->useServerStartScriptCheckBox->setChecked(on);
529 bool AttachTcfDialog::useServerStartScript() const
531 return m_ui->useServerStartScriptCheckBox->isChecked();
534 void AttachTcfDialog::updateState()
536 bool enabled = m_ui->useServerStartScriptCheckBox->isChecked();
537 m_ui->serverStartScriptLabel->setEnabled(enabled);
538 m_ui->serverStartScript->setEnabled(enabled);
542 ///////////////////////////////////////////////////////////////////////
544 // StartExternalDialog
546 ///////////////////////////////////////////////////////////////////////
548 StartExternalDialog::StartExternalDialog(QWidget *parent)
549 : QDialog(parent), m_ui(new Ui::StartExternalDialog)
552 m_ui->execFile->setExpectedKind(PathChooser::File);
553 m_ui->execFile->setPromptDialogTitle(tr("Select Executable"));
554 m_ui->execFile->lineEdit()->setCompleter(
555 new HistoryCompleter(m_ui->execFile->lineEdit()));
556 m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
557 m_ui->workingDirectory->setExpectedKind(PathChooser::Directory);
558 m_ui->workingDirectory->setPromptDialogTitle(tr("Select Working Directory"));
559 m_ui->workingDirectory->lineEdit()->setCompleter(
560 new HistoryCompleter(m_ui->workingDirectory->lineEdit()));
562 //execLabel->setHidden(false);
563 //execEdit->setHidden(false);
564 //browseButton->setHidden(false);
566 m_ui->execLabel->setText(tr("Executable:"));
567 m_ui->argsLabel->setText(tr("Arguments:"));
568 m_ui->argsEdit->setCompleter(new HistoryCompleter(m_ui->argsEdit));
570 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
571 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
574 StartExternalDialog::~StartExternalDialog()
579 void StartExternalDialog::setExecutableFile(const QString &str)
581 m_ui->execFile->setPath(str);
584 QString StartExternalDialog::executableFile() const
586 return m_ui->execFile->path();
589 void StartExternalDialog::setWorkingDirectory(const QString &str)
591 m_ui->workingDirectory->setPath(str);
594 QString StartExternalDialog::workingDirectory() const
596 return m_ui->workingDirectory->path();
599 void StartExternalDialog::setExecutableArguments(const QString &str)
601 m_ui->argsEdit->setText(str);
604 QString StartExternalDialog::executableArguments() const
606 return m_ui->argsEdit->text();
609 bool StartExternalDialog::breakAtMain() const
611 return m_ui->checkBoxBreakAtMain->isChecked();
614 ///////////////////////////////////////////////////////////////////////
618 ///////////////////////////////////////////////////////////////////////
620 StartRemoteDialog::StartRemoteDialog(QWidget *parent)
622 m_ui(new Ui::StartRemoteDialog)
625 m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
626 m_ui->debuggerPathChooser->setExpectedKind(PathChooser::File);
627 m_ui->debuggerPathChooser->setPromptDialogTitle(tr("Select Debugger"));
628 m_ui->executablePathChooser->setExpectedKind(PathChooser::File);
629 m_ui->executablePathChooser->setPromptDialogTitle(tr("Select Executable"));
630 m_ui->sysrootPathChooser->setPromptDialogTitle(tr("Select Sysroot"));
631 m_ui->serverStartScript->setExpectedKind(PathChooser::File);
632 m_ui->serverStartScript->setPromptDialogTitle(tr("Select Start Script"));
634 connect(m_ui->useServerStartScriptCheckBox, SIGNAL(toggled(bool)),
635 this, SLOT(updateState()));
637 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
638 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
643 StartRemoteDialog::~StartRemoteDialog()
648 void StartRemoteDialog::setRemoteChannel(const QString &channel)
650 m_ui->channelLineEdit->setText(channel);
653 QString StartRemoteDialog::remoteChannel() const
655 return m_ui->channelLineEdit->text();
658 void StartRemoteDialog::setLocalExecutable(const QString &executable)
660 m_ui->executablePathChooser->setPath(executable);
663 QString StartRemoteDialog::localExecutable() const
665 return m_ui->executablePathChooser->path();
668 void StartRemoteDialog::setDebugger(const QString &debugger)
670 m_ui->debuggerPathChooser->setPath(debugger);
673 QString StartRemoteDialog::debugger() const
675 return m_ui->debuggerPathChooser->path();
678 void StartRemoteDialog::setRemoteArchitectures(const QStringList &list)
680 m_ui->architectureComboBox->clear();
681 if (!list.isEmpty()) {
682 m_ui->architectureComboBox->insertItems(0, list);
683 m_ui->architectureComboBox->setCurrentIndex(0);
687 void StartRemoteDialog::setRemoteArchitecture(const QString &arch)
689 int index = m_ui->architectureComboBox->findText(arch);
691 m_ui->architectureComboBox->setCurrentIndex(index);
694 QString StartRemoteDialog::remoteArchitecture() const
696 return m_ui->architectureComboBox->currentText();
699 QString StartRemoteDialog::gnuTarget() const
701 return m_ui->gnuTargetComboBox->currentText();
704 void StartRemoteDialog::setGnuTargets(const QStringList &gnuTargets)
706 m_ui->gnuTargetComboBox->clear();
707 if (!gnuTargets.isEmpty()) {
708 m_ui->gnuTargetComboBox->insertItems(0, gnuTargets);
709 m_ui->gnuTargetComboBox->setCurrentIndex(0);
713 void StartRemoteDialog::setGnuTarget(const QString &gnuTarget)
715 const int index = m_ui->gnuTargetComboBox->findText(gnuTarget);
717 m_ui->gnuTargetComboBox->setCurrentIndex(index);
720 void StartRemoteDialog::setServerStartScript(const QString &scriptName)
722 m_ui->serverStartScript->setPath(scriptName);
725 QString StartRemoteDialog::serverStartScript() const
727 return m_ui->serverStartScript->path();
730 void StartRemoteDialog::setUseServerStartScript(bool on)
732 m_ui->useServerStartScriptCheckBox->setChecked(on);
735 bool StartRemoteDialog::useServerStartScript() const
737 return m_ui->useServerStartScriptCheckBox->isChecked();
740 void StartRemoteDialog::setSysRoot(const QString &sysroot)
742 m_ui->sysrootPathChooser->setPath(sysroot);
745 QString StartRemoteDialog::sysRoot() const
747 return m_ui->sysrootPathChooser->path();
750 void StartRemoteDialog::updateState()
752 bool enabled = m_ui->useServerStartScriptCheckBox->isChecked();
753 m_ui->serverStartScriptLabel->setEnabled(enabled);
754 m_ui->serverStartScript->setEnabled(enabled);
757 // --------- StartRemoteCdbDialog
758 static inline QString cdbRemoteHelp()
760 const char *cdbConnectionSyntax =
762 "tcp:server=Server,port=Port[,password=Password][,ipversion=6]\n"
763 "tcp:clicon=Server,port=Port[,password=Password][,ipversion=6]\n"
764 "npipe:server=Server,pipe=PipeName[,password=Password]\n"
765 "com:port=COMPort,baud=BaudRate,channel=COMChannel[,password=Password]\n"
766 "spipe:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,pipe=PipeName[,password=Password]\n"
767 "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,port=Socket[,password=Password]\n"
768 "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},clicon=Server,port=Socket[,password=Password]";
770 const QString ext32 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(false));
771 const QString ext64 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(true));
772 return StartRemoteCdbDialog::tr(
773 "<html><body><p>The remote CDB needs to load the matching Qt Creator CDB extension "
774 "(<code>%1</code> or <code>%2</code>, respectively).</p><p>Copy it onto the remote machine and set the "
775 "environment variable <code>%3</code> to point to its folder.</p><p>"
776 "Launch the remote CDB as <code>%4 <executable></code> "
777 " to use TCP/IP as communication protocol.</p><p>Enter the connection parameters as:</p>"
778 "<pre>%5</pre></body></html>").
779 arg(ext32, ext64, QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"),
780 QLatin1String("cdb.exe -server tcp:port=1234"),
781 QLatin1String(cdbConnectionSyntax));
784 StartRemoteCdbDialog::StartRemoteCdbDialog(QWidget *parent) :
785 QDialog(parent), m_okButton(0), m_lineEdit(new QLineEdit)
787 setWindowTitle(tr("Start a CDB Remote Session"));
788 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
790 QGroupBox *groupBox = new QGroupBox;
791 QFormLayout *formLayout = new QFormLayout;
792 QLabel *helpLabel = new QLabel(cdbRemoteHelp());
793 helpLabel->setWordWrap(true);
794 helpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
795 formLayout->addRow(helpLabel);
796 QLabel *label = new QLabel(tr("&Connection:"));
797 label->setBuddy(m_lineEdit);
798 m_lineEdit->setMinimumWidth(400);
799 connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
800 formLayout->addRow(label, m_lineEdit);
801 groupBox->setLayout(formLayout);
803 QVBoxLayout *vLayout = new QVBoxLayout;
804 vLayout->addWidget(groupBox);
805 QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
806 vLayout->addWidget(box);
807 m_okButton = box->button(QDialogButtonBox::Ok);
808 connect(m_lineEdit, SIGNAL(returnPressed()), m_okButton, SLOT(animateClick()));
809 m_okButton->setEnabled(false);
810 connect(box, SIGNAL(accepted()), this, SLOT(accept()));
811 connect(box, SIGNAL(rejected()), this, SLOT(reject()));
816 void StartRemoteCdbDialog::accept()
818 if (!m_lineEdit->text().isEmpty())
822 StartRemoteCdbDialog::~StartRemoteCdbDialog()
826 void StartRemoteCdbDialog::textChanged(const QString &t)
828 m_okButton->setEnabled(!t.isEmpty());
831 QString StartRemoteCdbDialog::connection() const
833 const QString rc = m_lineEdit->text();
834 // Transform an IP:POrt ('localhost:1234') specification into full spec
835 QRegExp ipRegexp(QLatin1String("([\\w\\.\\-_]+):([0-9]{1,4})"));
836 QTC_ASSERT(ipRegexp.isValid(), return QString());
837 if (ipRegexp.exactMatch(rc))
838 return QString::fromAscii("tcp:server=%1,port=%2").arg(ipRegexp.cap(1), ipRegexp.cap(2));
842 void StartRemoteCdbDialog::setConnection(const QString &c)
844 m_lineEdit->setText(c);
845 m_okButton->setEnabled(!c.isEmpty());
848 AddressDialog::AddressDialog(QWidget *parent) :
850 m_lineEdit(new QLineEdit),
851 m_box(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel))
853 setWindowTitle(tr("Select Start Address"));
854 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
855 QHBoxLayout *hLayout = new QHBoxLayout;
856 hLayout->addWidget(new QLabel(tr("Enter an address: ")));
857 hLayout->addWidget(m_lineEdit);
858 QVBoxLayout *vLayout = new QVBoxLayout;
859 vLayout->addLayout(hLayout);
860 vLayout->addWidget(m_box);
863 connect(m_box, SIGNAL(accepted()), this, SLOT(accept()));
864 connect(m_box, SIGNAL(rejected()), this, SLOT(reject()));
865 connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(accept()));
866 connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
868 setOkButtonEnabled(false);
871 void AddressDialog::setOkButtonEnabled(bool v)
873 m_box->button(QDialogButtonBox::Ok)->setEnabled(v);
876 bool AddressDialog::isOkButtonEnabled() const
878 return m_box->button(QDialogButtonBox::Ok)->isEnabled();
881 quint64 AddressDialog::address() const
883 return m_lineEdit->text().toULongLong(0, 16);
886 void AddressDialog::accept()
888 if (isOkButtonEnabled())
892 void AddressDialog::textChanged()
894 setOkButtonEnabled(isValid());
897 bool AddressDialog::isValid() const
899 const QString text = m_lineEdit->text();
901 text.toULongLong(&ok, 16);
905 ///////////////////////////////////////////////////////////////////////
907 // StartRemoteEngineDialog
909 ///////////////////////////////////////////////////////////////////////
911 StartRemoteEngineDialog::StartRemoteEngineDialog(QWidget *parent) :
913 m_ui(new Ui::StartRemoteEngineDialog)
916 m_ui->host->setCompleter(new HistoryCompleter(m_ui->host));
917 m_ui->username->setCompleter(new HistoryCompleter(m_ui->username));
918 m_ui->enginepath->setCompleter(new HistoryCompleter(m_ui->enginepath));
919 m_ui->inferiorpath->setCompleter(new HistoryCompleter(m_ui->inferiorpath));
920 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
921 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
924 StartRemoteEngineDialog::~StartRemoteEngineDialog()
928 QString StartRemoteEngineDialog::host() const
930 return m_ui->host->text();
933 QString StartRemoteEngineDialog::username() const
935 return m_ui->username->text();
938 QString StartRemoteEngineDialog::password() const
940 return m_ui->password->text();
943 QString StartRemoteEngineDialog::inferiorPath() const
945 return m_ui->inferiorpath->text();
948 QString StartRemoteEngineDialog::enginePath() const
950 return m_ui->enginepath->text();
954 } // namespace Internal
955 } // namespace Debugger