Fixed that the debugger window really moves itself to the foreground.
[kdbg.git] / kdbg / memwindow.cpp
blobd0ce2b3cf753f27600fe73355dd7440bbefbaf3a
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include "memwindow.h"
7 #include <qheader.h>
8 #include <klocale.h>
9 #include <kconfigbase.h>
10 #include "debugger.h"
11 #include "dbgdriver.h" /* memory dump formats */
14 class MemoryViewItem : public QListViewItem
16 public:
17 MemoryViewItem(QListView* parent, QListViewItem* insertAfter, QString raw, QString cooked)
18 : QListViewItem(parent, insertAfter, raw, cooked), m_changed(8) {}
20 void setChanged(uint pos, bool b) { m_changed[pos] = b; }
22 protected:
23 virtual void paintCell(QPainter* p, const QColorGroup& cg,
24 int column, int width, int alignment);
26 QArray<bool> m_changed;
29 void MemoryViewItem::paintCell(QPainter* p, const QColorGroup& cg,
30 int column, int width, int alignment)
32 if( column > 0 && m_changed[column - 1] ) {
33 QColorGroup newcg = cg;
34 newcg.setColor(QColorGroup::Text, red);
35 QListViewItem::paintCell(p, newcg, column, width, alignment);
36 } else {
37 QListViewItem::paintCell(p, cg, column, width, alignment);
42 MemoryWindow::MemoryWindow(QWidget* parent, const char* name) :
43 QWidget(parent, name),
44 m_debugger(0),
45 m_expression(true, this, "expression"),
46 m_memory(this, "memory"),
47 m_layout(this, 0, 2),
48 m_format(MDTword | MDThex)
50 QSize minSize = m_expression.sizeHint();
51 m_expression.setMinimumSize(minSize);
52 m_expression.setInsertionPolicy(QComboBox::NoInsertion);
53 m_expression.setMaxCount(15);
55 m_memory.addColumn(i18n("Address"), 80);
57 m_memory.setSorting(-1); /* don't sort */
58 m_memory.setAllColumnsShowFocus(true);
59 m_memory.header()->setClickEnabled(false);
61 // create layout
62 m_layout.addWidget(&m_expression, 0);
63 m_layout.addWidget(&m_memory, 10);
64 m_layout.activate();
66 connect(&m_expression, SIGNAL(activated(const QString&)),
67 this, SLOT(slotNewExpression(const QString&)));
69 // the popup menu
70 m_popup.insertItem(i18n("B&ytes"), MDTbyte);
71 m_popup.insertItem(i18n("Halfwords (&2 Bytes)"), MDThalfword);
72 m_popup.insertItem(i18n("Words (&4 Bytes)"), MDTword);
73 m_popup.insertItem(i18n("Giantwords (&8 Bytes)"), MDTgiantword);
74 m_popup.insertSeparator();
75 m_popup.insertItem(i18n("He&xadecimal"), MDThex);
76 m_popup.insertItem(i18n("Signed &decimal"), MDTsigned);
77 m_popup.insertItem(i18n("&Unsigned decimal"), MDTunsigned);
78 m_popup.insertItem(i18n("&Octal"), MDToctal);
79 m_popup.insertItem(i18n("&Binary"), MDTbinary);
80 m_popup.insertItem(i18n("&Addresses"), MDTaddress);
81 m_popup.insertItem(i18n("&Character"), MDTchar);
82 m_popup.insertItem(i18n("&Floatingpoint"), MDTfloat);
83 m_popup.insertItem(i18n("&Strings"), MDTstring);
84 m_popup.insertItem(i18n("&Instructions"), MDTinsn);
85 connect(&m_popup, SIGNAL(activated(int)), this, SLOT(slotTypeChange(int)));
88 * Handle right mouse button. Signal righteButtonClicked cannot be
89 * used, because it works only over items, not over the blank window.
91 m_memory.viewport()->installEventFilter(this);
93 m_formatCache.setAutoDelete(true);
96 MemoryWindow::~MemoryWindow()
100 bool MemoryWindow::eventFilter(QObject*, QEvent* ev)
102 if (ev->type() == QEvent::MouseButtonRelease) {
103 handlePopup(static_cast<QMouseEvent*>(ev));
104 return true;
106 return false;
109 void MemoryWindow::handlePopup(QMouseEvent* ev)
111 if (ev->button() == RightButton)
113 // show popup menu
114 if (m_popup.isVisible())
116 m_popup.hide();
118 else
120 m_popup.popup(mapToGlobal(ev->pos()));
122 return;
126 void MemoryWindow::slotNewExpression(const QString& newText)
128 QString text = newText.simplifyWhiteSpace();
130 // see if the string is in the list
131 // (note: must count downwards because of removeItem!)
132 for (int i = m_expression.count()-1; i >= 0; i--)
134 if (m_expression.text(i) == text) {
135 // yes it is!
136 // look up the format that was used last time for this expr
137 unsigned* pFormat = m_formatCache[text];
138 if (pFormat != 0) {
139 m_format = *pFormat;
140 m_debugger->setMemoryFormat(m_format);
142 // remove this text, will be inserted at the top
143 m_expression.removeItem(i);
146 m_expression.insertItem(text, 0);
148 if (text.isEmpty()) {
149 // if format was not in the cache, insert it
150 if (m_formatCache[text] == 0) {
151 m_formatCache.insert(text, new unsigned(m_format));
156 displayNewExpression(text);
159 void MemoryWindow::displayNewExpression(const QString& expr)
161 m_debugger->setMemoryExpression(expr);
162 m_expression.setEditText(expr);
164 // clear memory dump if no dump wanted
165 if (expr.isEmpty()) {
166 m_memory.clear();
167 m_old_memory.clear();
171 void MemoryWindow::slotTypeChange(int id)
173 m_old_memory.clear();
175 // compute new type
176 if (id & MDTsizemask)
177 m_format = (m_format & ~MDTsizemask) | id;
178 if (id & MDTformatmask)
179 m_format = (m_format & ~MDTformatmask) | id;
180 m_debugger->setMemoryFormat(m_format);
182 // change the format in the cache
183 QString expr = m_expression.currentText();
184 expr = expr.simplifyWhiteSpace();
185 unsigned* pFormat = m_formatCache[expr];
186 if (pFormat != 0)
187 *pFormat = m_format;
189 // force redisplay
190 displayNewExpression(expr);
193 void MemoryWindow::slotNewMemoryDump(const QString& msg, QList<MemoryDump>& memdump)
195 m_memory.clear();
196 if (!msg.isEmpty()) {
197 new QListViewItem(&m_memory, QString(), msg);
198 return;
201 MemoryViewItem* after = 0;
202 MemoryDump* md = memdump.first();
204 // remove all columns, except the address column
205 for(int k = m_memory.columns() - 1; k > 0; k--)
206 m_memory.removeColumn(k);
208 //add the needed columns
209 QStringList sl = QStringList::split( "\t", md->dump );
210 for (uint i = 0; i < sl.count(); i++)
211 m_memory.addColumn("", -1);
213 QMap<QString,QString> tmpMap;
215 for (; md != 0; md = memdump.next())
217 QString addr = md->address.asString() + " " + md->address.fnoffs;
218 QStringList sl = QStringList::split( "\t", md->dump );
220 // save memory
221 tmpMap[addr] = md->dump;
223 after = new MemoryViewItem(&m_memory, after, addr, "");
225 QStringList tmplist;
226 QMap<QString,QString>::Iterator pos = m_old_memory.find( addr );
228 if( pos != m_old_memory.end() )
229 tmplist = QStringList::split( "\t", pos.data() );
231 for (uint i = 0; i < sl.count(); i++)
233 after->setText( i+1, *sl.at(i) );
235 bool changed =
236 tmplist.count() > 0 &&
237 *sl.at(i) != *tmplist.at(i);
238 after->setChanged(i, changed);
242 m_old_memory.clear();
243 m_old_memory = tmpMap;
246 static const char MemoryGroup[] = "Memory";
247 static const char NumExprs[] = "NumExprs";
248 static const char ExpressionFmt[] = "Expression%d";
249 static const char FormatFmt[] = "Format%d";
250 static const char ColumnWidths[] = "ColumnWidths";
252 void MemoryWindow::saveProgramSpecific(KConfigBase* config)
254 KConfigGroupSaver s(config, MemoryGroup);
256 int numEntries = m_expression.count();
257 config->writeEntry(NumExprs, numEntries);
258 QString exprEntry;
259 QString fmtEntry;
260 for (int i = 0; i < numEntries;) {
261 QString text = m_expression.text(i);
262 i++; /* entries are counted 1-based */
263 exprEntry.sprintf(ExpressionFmt, i);
264 fmtEntry.sprintf(FormatFmt, i);
265 config->writeEntry(exprEntry, text);
266 unsigned* pFormat = m_formatCache[text];
267 unsigned fmt = pFormat != 0 ? *pFormat : MDTword | MDThex;
268 config->writeEntry(fmtEntry, fmt);
271 // column widths
272 QStrList widths;
273 QString wStr;
274 for (int i = 0; i < 2; i++) {
275 int w = m_memory.columnWidth(i);
276 wStr.setNum(w);
277 widths.append(wStr);
279 config->writeEntry(ColumnWidths, widths);
282 void MemoryWindow::restoreProgramSpecific(KConfigBase* config)
284 KConfigGroupSaver s(config, MemoryGroup);
286 int numEntries = config->readNumEntry(NumExprs, 0);
287 m_expression.clear();
289 QString exprEntry;
290 QString fmtEntry;
291 // entries are counted 1-based
292 for (int i = 1; i <= numEntries; i++) {
293 exprEntry.sprintf(ExpressionFmt, i);
294 fmtEntry.sprintf(FormatFmt, i);
295 QString expr = config->readEntry(exprEntry);
296 unsigned fmt = config->readNumEntry(fmtEntry, MDTword | MDThex);
297 m_expression.insertItem(expr);
298 m_formatCache.replace(expr, new unsigned(fmt & (MDTsizemask | MDTformatmask)));
301 // initialize with top expression
302 if (numEntries > 0) {
303 m_expression.setCurrentItem(0);
304 QString expr = m_expression.text(0);
305 m_format = *m_formatCache[expr];
306 m_debugger->setMemoryFormat(m_format);
307 displayNewExpression(expr);
310 // column widths
311 QStrList widths;
312 int n = config->readListEntry(ColumnWidths, widths);
313 if (n > 2)
314 n = 2;
315 for (int i = 0; i < n; i++) {
316 QString wStr = widths.at(i);
317 bool ok;
318 int w = wStr.toInt(&ok);
319 if (ok)
320 m_memory.setColumnWidth(i, w);
325 #include "memwindow.moc"