2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
8 #include <QFontDatabase>
10 #include <QMouseEvent>
13 #include <kconfigbase.h>
14 #include <kconfiggroup.h>
17 const int COL_DUMP_ASCII
= 9;
19 MemoryWindow::MemoryWindow(QWidget
* parent
) :
24 m_layout(QBoxLayout::TopToBottom
, this),
25 m_format(MDTword
| MDThex
)
27 setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont
));
29 m_expression
.setEditable(true);
30 QSize minSize
= m_expression
.sizeHint();
31 m_expression
.setMinimumSize(minSize
);
32 m_expression
.setInsertPolicy(QComboBox::NoInsert
);
33 m_expression
.setMaxCount(15);
35 m_memory
.setColumnCount(10);
36 m_memory
.setHeaderLabel(i18n("Address"));
37 for (int i
= 1; i
< 10; i
++) {
38 m_memory
.hideColumn(i
);
39 m_memory
.headerItem()->setText(i
, QString());
41 m_memory
.header()->setStretchLastSection(false);
43 m_memory
.setSortingEnabled(false); /* don't sort */
44 m_memory
.setAllColumnsShowFocus(true);
45 m_memory
.setRootIsDecorated(false);
46 m_memory
.header()->setSectionResizeMode(QHeaderView::ResizeToContents
);
47 m_memory
.header()->setSectionsClickable(false);
48 m_memory
.header()->setSectionsMovable(false); // don't move columns
49 m_memory
.setContextMenuPolicy(Qt::NoContextMenu
); // defer to parent
52 m_layout
.setSpacing(2);
53 m_layout
.addWidget(&m_expression
, 0);
54 m_layout
.addWidget(&m_memory
, 10);
57 connect(&m_expression
, SIGNAL(activated(const QString
&)),
58 this, SLOT(slotNewExpression(const QString
&)));
59 connect(m_expression
.lineEdit(), SIGNAL(returnPressed()),
60 this, SLOT(slotNewExpression()));
64 pAction
= m_popup
.addAction(i18n("B&ytes"));
65 pAction
->setData(MDTbyte
);
66 pAction
= m_popup
.addAction(i18n("Halfwords (&2 Bytes)"));
67 pAction
->setData(MDThalfword
);
68 pAction
= m_popup
.addAction(i18n("Words (&4 Bytes)"));
69 pAction
->setData(MDTword
);
70 pAction
= m_popup
.addAction(i18n("Giantwords (&8 Bytes)"));
71 pAction
->setData(MDTgiantword
);
72 m_popup
.addSeparator();
73 pAction
= m_popup
.addAction(i18n("He&xadecimal"));
74 pAction
->setData(MDThex
);
75 pAction
= m_popup
.addAction(i18n("Signed &decimal"));
76 pAction
->setData(MDTsigned
);
77 pAction
= m_popup
.addAction(i18n("&Unsigned decimal"));
78 pAction
->setData(MDTunsigned
);
79 pAction
= m_popup
.addAction(i18n("&Octal"));
80 pAction
->setData(MDToctal
);
81 pAction
= m_popup
.addAction(i18n("&Binary"));
82 pAction
->setData(MDTbinary
);
83 pAction
= m_popup
.addAction(i18n("&Addresses"));
84 pAction
->setData(MDTaddress
);
85 pAction
= m_popup
.addAction(i18n("&Character"));
86 pAction
->setData(MDTchar
);
87 pAction
= m_popup
.addAction(i18n("&Floatingpoint"));
88 pAction
->setData(MDTfloat
);
89 pAction
= m_popup
.addAction(i18n("&Strings"));
90 pAction
->setData(MDTstring
);
91 pAction
= m_popup
.addAction(i18n("&Instructions"));
92 pAction
->setData(MDTinsn
);
93 connect(&m_popup
, SIGNAL(triggered(QAction
*)), this, SLOT(slotTypeChange(QAction
*)));
96 MemoryWindow::~MemoryWindow()
100 void MemoryWindow::contextMenuEvent(QContextMenuEvent
* ev
)
102 m_popup
.popup(ev
->globalPos());
106 void MemoryWindow::slotNewExpression()
108 slotNewExpression(m_expression
.lineEdit()->text());
111 void MemoryWindow::slotNewExpression(const QString
& newText
)
113 QString text
= newText
.simplified();
115 // see if the string is in the list
116 // (note: must count downwards because of removeItem!)
117 for (int i
= m_expression
.count()-1; i
>= 0; i
--)
119 if (m_expression
.itemText(i
) == text
) {
121 // look up the format that was used last time for this expr
122 QMap
<QString
,unsigned>::iterator pFormat
= m_formatCache
.find(text
);
123 if (pFormat
!= m_formatCache
.end()) {
125 m_debugger
->setMemoryFormat(m_format
);
127 // remove this text, will be inserted at the top
128 m_expression
.removeItem(i
);
131 m_expression
.insertItem(0, text
);
133 if (!text
.isEmpty()) {
134 m_formatCache
[text
] = m_format
;
137 displayNewExpression(text
);
140 void MemoryWindow::displayNewExpression(const QString
& expr
)
142 m_debugger
->setMemoryExpression(expr
);
143 m_expression
.setEditText(expr
);
145 // clear memory dump if no dump wanted
146 if (expr
.isEmpty()) {
148 m_old_memory
.clear();
152 void MemoryWindow::slotTypeChange(QAction
* action
)
154 int id
= action
->data().toInt();
156 m_old_memory
.clear();
159 if (id
& MDTsizemask
)
160 m_format
= (m_format
& ~MDTsizemask
) | id
;
161 if (id
& MDTformatmask
)
162 m_format
= (m_format
& ~MDTformatmask
) | id
;
163 m_debugger
->setMemoryFormat(m_format
);
165 // change the format in the cache
166 QString expr
= m_expression
.currentText();
167 m_formatCache
[expr
.simplified()] = m_format
;
170 displayNewExpression(expr
);
173 QString
MemoryWindow::parseMemoryDumpLineToAscii(const QString
& line
)
175 QStringList hexdata
= line
.split("\t");
177 // Get the size of value from hex str representation length
178 // 0x00 = (4 - 2) / 2 -> 1 byte
179 // 0x0000 = (6 - 2) / 2 -> 2 half-word
180 // 0x00000000 = (10 - 2) / 2 -> 4 word
181 // 0x0000000000000000 = (18 - 2) / 2 -> 8 giant word
183 int len
= (hexdata
[0].length()-2) / 2;
185 for (const auto& hex
: hexdata
)
188 unsigned long long parsedValue
= hex
.toULongLong(&ok
, 16);
190 for (int s
= 0; s
< len
; s
++)
192 unsigned char b
= parsedValue
& 0xFF;
205 void MemoryWindow::slotNewMemoryDump(const QString
& msg
, const std::list
<MemoryDump
>& memdump
)
208 if (!msg
.isEmpty()) {
209 new QTreeWidgetItem(&m_memory
, QStringList() << QString() << msg
);
212 bool showDumpAscii
= (m_format
& MDTformatmask
) == MDThex
;
214 std::list
<MemoryDump
>::const_iterator md
= memdump
.begin();
216 // show only needed columns
217 QStringList sl
= md
->dump
.split( "\t" );
218 for (int i
= COL_DUMP_ASCII
-1; i
> 0; i
--)
219 m_memory
.setColumnHidden(i
, i
> sl
.count());
221 m_memory
.setColumnHidden(COL_DUMP_ASCII
, !showDumpAscii
);
223 QMap
<QString
,QString
> tmpMap
;
225 for (; md
!= memdump
.end(); ++md
)
227 QString addr
= md
->address
.asString() + " " + md
->address
.fnoffs
;
228 QStringList sl
= md
->dump
.split( "\t" );
231 tmpMap
[addr
] = md
->dump
;
233 QTreeWidgetItem
* line
=
234 new QTreeWidgetItem(&m_memory
, QStringList(addr
) << sl
);
237 QString dumpAscii
= parseMemoryDumpLineToAscii(md
->dump
);
238 line
->setText(COL_DUMP_ASCII
, dumpAscii
);
242 QMap
<QString
,QString
>::Iterator pos
= m_old_memory
.find( addr
);
244 if( pos
!= m_old_memory
.end() )
245 tmplist
= pos
.value().split( "\t" );
247 for (int i
= 0; i
< sl
.count(); i
++)
250 i
< tmplist
.count() &&
252 line
->setForeground(i
+1, changed
? QBrush(QColor(Qt::red
)) : palette().text());
256 m_old_memory
.clear();
257 m_old_memory
= tmpMap
;
260 static const char MemoryGroup
[] = "Memory";
261 static const char NumExprs
[] = "NumExprs";
262 static const char ExpressionFmt
[] = "Expression%d";
263 static const char FormatFmt
[] = "Format%d";
264 static const char ColumnWidths
[] = "ColumnWidths";
266 void MemoryWindow::saveProgramSpecific(KConfigBase
* config
)
268 KConfigGroup g
= config
->group(MemoryGroup
);
270 int numEntries
= m_expression
.count();
271 g
.writeEntry(NumExprs
, numEntries
);
274 for (int i
= 0; i
< numEntries
;) {
275 QString text
= m_expression
.itemText(i
);
276 i
++; /* entries are counted 1-based */
277 exprEntry
.sprintf(ExpressionFmt
, i
);
278 fmtEntry
.sprintf(FormatFmt
, i
);
279 g
.writeEntry(exprEntry
, text
);
280 QMap
<QString
,unsigned>::iterator pFormat
= m_formatCache
.find(text
);
281 unsigned fmt
= pFormat
!= m_formatCache
.end() ? *pFormat
: MDTword
| MDThex
;
282 g
.writeEntry(fmtEntry
, fmt
);
287 for (int i
= 0; i
< 2; i
++) {
288 int w
= m_memory
.columnWidth(i
);
291 g
.writeEntry(ColumnWidths
, widths
);
294 void MemoryWindow::restoreProgramSpecific(KConfigBase
* config
)
296 KConfigGroup g
= config
->group(MemoryGroup
);
298 int numEntries
= g
.readEntry(NumExprs
, 0);
299 m_expression
.clear();
303 // entries are counted 1-based
304 for (int i
= 1; i
<= numEntries
; i
++) {
305 exprEntry
.sprintf(ExpressionFmt
, i
);
306 fmtEntry
.sprintf(FormatFmt
, i
);
307 QString expr
= g
.readEntry(exprEntry
, QString());
308 unsigned fmt
= g
.readEntry(fmtEntry
, MDTword
| MDThex
);
309 m_expression
.addItem(expr
);
310 m_formatCache
[expr
] = fmt
& (MDTsizemask
| MDTformatmask
);
313 // initialize with top expression
314 if (numEntries
> 0) {
315 m_expression
.setCurrentIndex(0);
316 QString expr
= m_expression
.itemText(0);
317 m_format
= m_formatCache
[expr
];
318 m_debugger
->setMemoryFormat(m_format
);
319 displayNewExpression(expr
);
323 QList
<int> widths
= g
.readEntry(ColumnWidths
, QList
<int>());
324 QList
<int>::iterator w
= widths
.begin();
325 for (int i
= 0; i
< 2 && w
!= widths
.end(); ++i
, ++w
) {
326 m_memory
.setColumnWidth(i
, *w
);
331 #include "memwindow.moc"