Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
cf1ffdbc
Commit
cf1ffdbc
authored
Sep 22, 2010
by
hjk
Browse files
debugger: start implementing a debugger console
parent
d9f4cb41
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/plugins/debugger/consolewindow.cpp
0 → 100644
View file @
cf1ffdbc
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include
"consolewindow.h"
#include
"debuggeractions.h"
#include
"debuggerconstants.h"
#include
<QtCore/QDebug>
#include
<QtCore/QFile>
#include
<QtCore/QTime>
#include
<QtGui/QAction>
#include
<QtGui/QHBoxLayout>
#include
<QtGui/QVBoxLayout>
#include
<QtGui/QKeyEvent>
#include
<QtGui/QLabel>
#include
<QtGui/QLineEdit>
#include
<QtGui/QMenu>
#include
<QtGui/QSpacerItem>
#include
<QtGui/QSplitter>
#include
<QtGui/QSyntaxHighlighter>
#include
<QtGui/QTextBlock>
#include
<QtGui/QPlainTextEdit>
#include
<QtGui/QFileDialog>
#include
<QtGui/QMessageBox>
#include
<aggregation/aggregate.h>
#include
<coreplugin/findplaceholder.h>
#include
<coreplugin/minisplitter.h>
#include
<find/basetextfind.h>
#include
<utils/savedaction.h>
using
namespace
Find
;
namespace
Debugger
{
namespace
Internal
{
static
QChar
charForChannel
(
int
channel
)
{
switch
(
channel
)
{
case
LogDebug
:
return
'd'
;
case
LogWarning
:
return
'w'
;
case
LogError
:
return
'e'
;
case
LogInput
:
return
'<'
;
case
LogOutput
:
return
'>'
;
case
LogStatus
:
return
's'
;
case
LogTime
:
return
't'
;
case
LogMisc
:
default:
return
' '
;
}
}
static
LogChannel
channelForChar
(
QChar
c
)
{
switch
(
c
.
unicode
())
{
case
'd'
:
return
LogDebug
;
case
'w'
:
return
LogWarning
;
case
'e'
:
return
LogError
;
case
'<'
:
return
LogInput
;
case
'>'
:
return
LogOutput
;
case
's'
:
return
LogStatus
;
case
't'
:
return
LogTime
;
default:
return
LogMisc
;
}
}
/////////////////////////////////////////////////////////////////////
//
// ConsoleHighlighter
//
/////////////////////////////////////////////////////////////////////
class
ConsoleHighlighter
:
public
QSyntaxHighlighter
{
public:
ConsoleHighlighter
(
QPlainTextEdit
*
parent
)
:
QSyntaxHighlighter
(
parent
->
document
()),
m_parent
(
parent
)
{}
private:
void
highlightBlock
(
const
QString
&
text
)
{
QTextCharFormat
format
;
switch
(
channelForChar
(
text
.
isEmpty
()
?
QChar
()
:
text
.
at
(
0
)))
{
case
LogInput
:
format
.
setForeground
(
Qt
::
blue
);
setFormat
(
1
,
text
.
size
(),
format
);
break
;
case
LogStatus
:
format
.
setForeground
(
Qt
::
darkGreen
);
setFormat
(
1
,
text
.
size
(),
format
);
break
;
case
LogWarning
:
format
.
setForeground
(
Qt
::
darkYellow
);
setFormat
(
1
,
text
.
size
(),
format
);
break
;
case
LogError
:
format
.
setForeground
(
Qt
::
red
);
setFormat
(
1
,
text
.
size
(),
format
);
break
;
case
LogTime
:
format
.
setForeground
(
Qt
::
darkRed
);
setFormat
(
1
,
text
.
size
(),
format
);
break
;
default:
break
;
}
QColor
base
=
m_parent
->
palette
().
color
(
QPalette
::
Base
);
format
.
setForeground
(
base
);
format
.
setFontPointSize
(
1
);
setFormat
(
0
,
1
,
format
);
/*
if (text.size() > 3 && text.at(2) == QLatin1Char(':')) {
QTextCharFormat format;
format.setForeground(Qt::darkRed);
setFormat(1, text.size(), format);
}
*/
}
QPlainTextEdit
*
m_parent
;
};
/////////////////////////////////////////////////////////////////////
//
// DebbuggerPane base class
//
/////////////////////////////////////////////////////////////////////
// FIXME: Code duplication with FakeVim
class
History
{
public:
History
()
:
m_index
(
0
)
{}
void
append
(
const
QString
&
item
)
{
m_items
.
removeAll
(
item
);
m_items
.
append
(
item
);
m_index
=
m_items
.
size
()
-
1
;
}
void
down
()
{
m_index
=
qMin
(
m_index
+
1
,
m_items
.
size
());
}
void
up
()
{
m_index
=
qMax
(
m_index
-
1
,
0
);
}
//void clear() { m_items.clear(); m_index = 0; }
void
restart
()
{
m_index
=
m_items
.
size
();
}
QString
current
()
const
{
return
m_items
.
value
(
m_index
,
QString
());
}
QStringList
items
()
const
{
return
m_items
;
}
private:
QStringList
m_items
;
int
m_index
;
};
class
Console
:
public
QPlainTextEdit
{
Q_OBJECT
public:
Console
(
QWidget
*
parent
)
:
QPlainTextEdit
(
parent
)
{
setMaximumBlockCount
(
100000
);
setFrameStyle
(
QFrame
::
NoFrame
);
m_clearContentsAction
=
new
QAction
(
this
);
m_clearContentsAction
->
setText
(
tr
(
"Clear Contents"
));
m_clearContentsAction
->
setEnabled
(
true
);
connect
(
m_clearContentsAction
,
SIGNAL
(
triggered
(
bool
)),
parent
,
SLOT
(
clearContents
()));
m_saveContentsAction
=
new
QAction
(
this
);
m_saveContentsAction
->
setText
(
tr
(
"Save Contents"
));
m_saveContentsAction
->
setEnabled
(
true
);
connect
(
m_saveContentsAction
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
saveContents
()));
}
void
contextMenuEvent
(
QContextMenuEvent
*
ev
)
{
theDebuggerAction
(
ExecuteCommand
)
->
setData
(
textCursor
().
block
().
text
());
QMenu
*
menu
=
createStandardContextMenu
();
menu
->
addAction
(
m_clearContentsAction
);
menu
->
addAction
(
m_saveContentsAction
);
// X11 clipboard is unreliable for long texts
menu
->
addAction
(
theDebuggerAction
(
ExecuteCommand
));
menu
->
addAction
(
theDebuggerAction
(
LogTimeStamps
));
menu
->
addAction
(
theDebuggerAction
(
VerboseLog
));
menu
->
addSeparator
();
menu
->
addAction
(
theDebuggerAction
(
SettingsDialog
));
menu
->
exec
(
ev
->
globalPos
());
delete
menu
;
}
void
keyPressEvent
(
QKeyEvent
*
ev
)
{
if
(
ev
->
key
()
==
Qt
::
Key_Return
)
{
if
(
ev
->
modifiers
()
==
0
)
{
QString
cmd
=
textCursor
().
block
().
text
();
if
(
cmd
.
isEmpty
())
cmd
=
m_history
.
current
();
QString
cleanCmd
;
foreach
(
QChar
c
,
cmd
)
if
(
c
.
unicode
()
>=
32
&&
c
.
unicode
()
<
128
)
cleanCmd
.
append
(
c
);
if
(
!
cleanCmd
.
isEmpty
())
{
theDebuggerAction
(
ExecuteCommand
)
->
trigger
(
cleanCmd
);
m_history
.
append
(
cleanCmd
);
}
}
QPlainTextEdit
::
keyPressEvent
(
ev
);
}
else
if
(
ev
->
key
()
==
Qt
::
Key_Up
)
{
m_history
.
up
();
}
else
if
(
ev
->
key
()
==
Qt
::
Key_Down
)
{
m_history
.
down
();
}
else
{
QPlainTextEdit
::
keyPressEvent
(
ev
);
}
}
void
mouseDoubleClickEvent
(
QMouseEvent
*
ev
)
{
QString
line
=
cursorForPosition
(
ev
->
pos
()).
block
().
text
();
int
n
=
0
;
// cut time string
if
(
line
.
size
()
>
18
&&
line
.
at
(
0
)
==
'['
)
line
=
line
.
mid
(
18
);
//qDebug() << line;
for
(
int
i
=
0
;
i
!=
line
.
size
();
++
i
)
{
QChar
c
=
line
.
at
(
i
);
if
(
!
c
.
isDigit
())
break
;
n
=
10
*
n
+
c
.
unicode
()
-
'0'
;
}
//emit commandSelected(n);
}
private
slots
:
void
saveContents
();
private:
QAction
*
m_clearContentsAction
;
QAction
*
m_saveContentsAction
;
History
m_history
;
};
void
Console
::
saveContents
()
{
while
(
true
)
{
const
QString
fileName
=
QFileDialog
::
getSaveFileName
(
this
,
tr
(
"Log File"
));
if
(
fileName
.
isEmpty
())
break
;
QFile
file
(
fileName
);
if
(
file
.
open
(
QIODevice
::
WriteOnly
|
QIODevice
::
Text
|
QIODevice
::
Truncate
))
{
file
.
write
(
toPlainText
().
toUtf8
());
file
.
close
();
break
;
}
else
{
QMessageBox
::
warning
(
this
,
tr
(
"Write Failure"
),
tr
(
"Unable to write log contents to '%1': %2"
).
arg
(
fileName
,
file
.
errorString
()));
}
}
}
/////////////////////////////////////////////////////////////////////
//
// ConsoleWindow
//
/////////////////////////////////////////////////////////////////////
ConsoleWindow
::
ConsoleWindow
(
QWidget
*
parent
)
:
QWidget
(
parent
)
{
setWindowTitle
(
tr
(
"Console"
));
m_console
=
new
Console
(
this
);
m_console
->
setSizePolicy
(
QSizePolicy
::
MinimumExpanding
,
QSizePolicy
::
MinimumExpanding
);
QVBoxLayout
*
layout
=
new
QVBoxLayout
(
this
);
layout
->
setMargin
(
0
);
layout
->
setSpacing
(
0
);
layout
->
addWidget
(
m_console
);
layout
->
addWidget
(
new
Core
::
FindToolBarPlaceHolder
(
this
));
setLayout
(
layout
);
Aggregation
::
Aggregate
*
aggregate
=
new
Aggregation
::
Aggregate
;
aggregate
->
add
(
m_console
);
aggregate
->
add
(
new
BaseTextFind
(
m_console
));
//connect(m_console, SIGNAL(statusMessageRequested(QString,int)),
// this, SIGNAL(statusMessageRequested(QString,int)));
};
void
ConsoleWindow
::
showOutput
(
int
channel
,
const
QString
&
output
)
{
if
(
output
.
isEmpty
())
return
;
//QTextCursor oldCursor = m_console->textCursor();
//QTextCursor cursor = oldCursor;
//cursor.movePosition(QTextCursor::End);
//bool atEnd = oldCursor.position() == cursor.position();
foreach
(
QString
line
,
output
.
split
(
'\n'
))
{
// FIXME: QTextEdit asserts on really long lines...
const
int
n
=
30000
;
if
(
line
.
size
()
>
n
)
{
line
.
truncate
(
n
);
line
+=
QLatin1String
(
" [...] <cut off>"
);
}
m_console
->
appendPlainText
(
charForChannel
(
channel
)
+
line
+
"
\n
"
);
}
QTextCursor
cursor
=
m_console
->
textCursor
();
cursor
.
movePosition
(
QTextCursor
::
End
);
//if (atEnd) {
m_console
->
setTextCursor
(
cursor
);
m_console
->
ensureCursorVisible
();
//}
}
void
ConsoleWindow
::
showInput
(
int
channel
,
const
QString
&
input
)
{
Q_UNUSED
(
channel
)
m_console
->
appendPlainText
(
input
);
QTextCursor
cursor
=
m_console
->
textCursor
();
cursor
.
movePosition
(
QTextCursor
::
End
);
m_console
->
setTextCursor
(
cursor
);
m_console
->
ensureCursorVisible
();
}
void
ConsoleWindow
::
clearContents
()
{
m_console
->
clear
();
}
void
ConsoleWindow
::
setCursor
(
const
QCursor
&
cursor
)
{
m_console
->
viewport
()
->
setCursor
(
cursor
);
QWidget
::
setCursor
(
cursor
);
}
QString
ConsoleWindow
::
combinedContents
()
const
{
return
m_console
->
toPlainText
();
}
QString
ConsoleWindow
::
inputContents
()
const
{
return
m_console
->
toPlainText
();
}
}
// namespace Internal
}
// namespace Debugger
#include
"consolewindow.moc"
src/plugins/debugger/consolewindow.h
0 → 100644
View file @
cf1ffdbc
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef DEBUGGER_CONSOLEWINDOW_H
#define DEBUGGER_CONSOLEWINDOW_H
#include
<QtGui/QWidget>
QT_BEGIN_NAMESPACE
class
QCursor
;
QT_END_NAMESPACE
namespace
Debugger
{
namespace
Internal
{
class
Console
;
class
ConsoleWindow
:
public
QWidget
{
Q_OBJECT
public:
explicit
ConsoleWindow
(
QWidget
*
parent
=
0
);
void
setCursor
(
const
QCursor
&
cursor
);
QString
combinedContents
()
const
;
QString
inputContents
()
const
;
static
QString
logTimeStamp
();
public
slots
:
void
clearContents
();
void
showOutput
(
int
channel
,
const
QString
&
output
);
void
showInput
(
int
channel
,
const
QString
&
input
);
signals:
void
showPage
();
void
statusMessageRequested
(
const
QString
&
msg
,
int
);
private:
Console
*
m_console
;
// combined input/output
};
}
// namespace Internal
}
// namespace Debugger
#endif // DEBUGGER_CONSOLEWINDOW_H
src/plugins/debugger/debugger.pro
View file @
cf1ffdbc
...
...
@@ -19,6 +19,7 @@ QT += gui \
HEADERS
+=
breakhandler
.
h
\
breakwindow
.
h
\
breakpoint
.
h
\
consolewindow
.
h
\
debuggeragents
.
h
\
debuggeractions
.
h
\
debuggerconstants
.
h
\
...
...
@@ -56,6 +57,7 @@ HEADERS += breakhandler.h \
SOURCES
+=
breakhandler
.
cpp
\
breakwindow
.
cpp
\
breakpoint
.
cpp
\
consolewindow
.
cpp
\
debuggeragents
.
cpp
\
debuggeractions
.
cpp
\
debuggerdialogs
.
cpp
\
...
...
src/plugins/debugger/debuggerconstants.h
View file @
cf1ffdbc
...
...
@@ -65,6 +65,7 @@ const char * const DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON =
// dock widget names
const
char
*
const
DOCKWIDGET_BREAK
=
"Debugger.Docks.Break"
;
const
char
*
const
DOCKWIDGET_CONSOLE
=
"Debugger.Docks.Console"
;
const
char
*
const
DOCKWIDGET_MODULES
=
"Debugger.Docks.Modules"
;
const
char
*
const
DOCKWIDGET_REGISTER
=
"Debugger.Docks.Register"
;
const
char
*
const
DOCKWIDGET_OUTPUT
=
"Debugger.Docks.Output"
;
...
...
src/plugins/debugger/debuggerplugin.cpp
View file @
cf1ffdbc
...
...
@@ -43,6 +43,7 @@
#include
"debuggeruiswitcher.h"
#include
"breakwindow.h"
#include
"consolewindow.h"
#include
"moduleswindow.h"
#include
"registerwindow.h"
#include
"snapshotwindow.h"
...
...
@@ -993,6 +994,7 @@ public:
QComboBox
*
m_threadBox
;
QDockWidget
*
m_breakDock
;
QDockWidget
*
m_consoleDock
;
QDockWidget
*
m_modulesDock
;
QDockWidget
*
m_outputDock
;
QDockWidget
*
m_registerDock
;
...
...
@@ -1006,6 +1008,7 @@ public:
DebuggerActions
m_actions
;
BreakWindow
*
m_breakWindow
;
ConsoleWindow
*
m_consoleWindow
;
QTreeView
*
m_returnWindow
;
QTreeView
*
m_localsWindow
;
QTreeView
*
m_watchersWindow
;
...
...
@@ -1039,6 +1042,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin)
m_threadBox
=
0
;
m_breakDock
=
0
;
m_consoleDock
=
0
;
m_modulesDock
=
0
;
m_outputDock
=
0
;
m_registerDock
=
0
;
...
...
@@ -1104,6 +1108,8 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er
m_breakWindow
=
new
BreakWindow
;
m_breakWindow
->
setObjectName
(
QLatin1String
(
"CppDebugBreakpoints"
));
m_consoleWindow
=
new
ConsoleWindow
;
m_consoleWindow
->
setObjectName
(
QLatin1String
(
"CppDebugConsole"
));
m_modulesWindow
=
new
ModulesWindow
;
m_modulesWindow
->
setObjectName
(
QLatin1String
(
"CppDebugModules"
));
m_outputWindow
=
new
DebuggerOutputWindow
;
...
...
@@ -1266,6 +1272,11 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er
// Dock widgets
m_breakDock
=
m_uiSwitcher
->
createDockWidget
(
CppLanguage
,
m_breakWindow
);
m_breakDock
->
setObjectName
(
QString
(
DOCKWIDGET_BREAK
));
m_consoleDock
=
m_uiSwitcher
->
createDockWidget
(
CppLanguage
,
m_consoleWindow
,
Qt
::
TopDockWidgetArea
);
m_consoleDock
->
setObjectName
(
QString
(
DOCKWIDGET_OUTPUT
));
m_modulesDock
=
m_uiSwitcher
->
createDockWidget
(
CppLanguage
,
m_modulesWindow
,
Qt
::
TopDockWidgetArea
);
m_modulesDock
->
setObjectName
(
QString
(
DOCKWIDGET_MODULES
));
...
...
@@ -1281,6 +1292,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er
m_outputDock
=
m_uiSwitcher
->
createDockWidget
(
AnyLanguage
,
m_outputWindow
,
Qt
::
TopDockWidgetArea
);
m_outputDock
->
setObjectName
(
QString
(
DOCKWIDGET_OUTPUT
));
m_snapshotDock
=
m_uiSwitcher
->
createDockWidget
(
CppLanguage
,
m_snapshotWindow
);
m_snapshotDock
->
setObjectName
(
QString
(
DOCKWIDGET_SNAPSHOTS
));
...
...
@@ -2065,9 +2077,10 @@ void DebuggerPluginPrivate::fontSettingsChanged
{
int
size
=
settings
.
fontZoom
()
*
settings
.
fontSize
()
/
100
;
changeFontSize
(
m_breakWindow
,
size
);
changeFontSize
(
m_outputWindow
,
size
);
changeFontSize
(
m_localsWindow
,
size
);
changeFontSize
(
m_modulesWindow
,
size
);
changeFontSize
(
m_
output
Window
,
size
);
changeFontSize
(
m_
console
Window
,
size
);
changeFontSize
(
m_registerWindow
,
size
);
changeFontSize
(
m_returnWindow
,
size
);
changeFontSize
(
m_sourceFilesWindow
,
size
);
...
...
@@ -2104,6 +2117,7 @@ void DebuggerPluginPrivate::setBusyCursor(bool busy)
m_busy
=
busy
;
QCursor
cursor
(
busy
?
Qt
::
BusyCursor
:
Qt
::
ArrowCursor
);
m_breakWindow
->
setCursor
(
cursor
);
m_consoleWindow
->
setCursor
(
cursor
);
m_localsWindow
->
setCursor
(
cursor
);
m_modulesWindow
->
setCursor
(
cursor
);
m_outputWindow
->
setCursor
(
cursor
);
...
...
@@ -2131,7 +2145,7 @@ void DebuggerPluginPrivate::setSimpleDockWidgetArrangement
}
foreach
(
QDockWidget
*
dockWidget
,
dockWidgets
)
{
if
(
dockWidget
==
m_outputDock
)
{
if
(
dockWidget
==
m_outputDock
||
dockWidget
==
m_consoleDock
)
{
mw
->
addDockWidget
(
Qt
::
TopDockWidgetArea
,
dockWidget
);
}
else
{
mw
->
addDockWidget
(
Qt
::
BottomDockWidgetArea
,
dockWidget
);
...
...
@@ -2660,6 +2674,7 @@ void DebuggerPlugin::showMessage(const QString &msg, int channel, int timeout)
{
//qDebug() << "PLUGIN OUTPUT: " << channel << msg;
DebuggerOutputWindow
*
ow
=
d
->
m_outputWindow
;
ConsoleWindow
*
cw
=
d
->
m_consoleWindow
;
QTC_ASSERT
(
ow
,
return
);
switch
(
channel
)
{
case
StatusBar
:
...
...
@@ -2679,6 +2694,7 @@ void DebuggerPlugin::showMessage(const QString &msg, int channel, int timeout)
break
;
default:
ow
->
showOutput
(
channel
,
msg
);
cw
->
showOutput
(
channel
,
msg
);
break
;
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment