Be prepared that the animated button is destroyed behind our back.
[kdbg.git] / kdbg / memwindow.cpp
blob2721ae54e121fbed98e85dfbe2a045b32d906884
1 /*
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.
5 */
7 #include "memwindow.h"
8 #include <QHeaderView>
9 #include <QMouseEvent>
10 #include <QList>
11 #include <klocale.h>
12 #include <kconfigbase.h>
13 #include <kconfiggroup.h>
14 #include "debugger.h"
17 MemoryWindow::MemoryWindow(QWidget* parent) :
18 QWidget(parent),
19 m_debugger(0),
20 m_expression(this),
21 m_memory(this),
22 m_layout(QBoxLayout::TopToBottom, this),
23 m_format(MDTword | MDThex)
25 m_expression.setEditable(true);
26 QSize minSize = m_expression.sizeHint();
27 m_expression.setMinimumSize(minSize);
28 m_expression.setInsertPolicy(QComboBox::NoInsert);
29 m_expression.setMaxCount(15);
31 m_memory.setColumnCount(9);
32 m_memory.setHeaderLabel(i18n("Address"));
33 for (int i = 1; i < 9; i++) {
34 m_memory.hideColumn(i);
35 m_memory.header()->setResizeMode(QHeaderView::ResizeToContents);
36 m_memory.headerItem()->setText(i, QString());
38 m_memory.header()->setStretchLastSection(false);
40 m_memory.setSortingEnabled(false); /* don't sort */
41 m_memory.setAllColumnsShowFocus(true);
42 m_memory.setRootIsDecorated(false);
43 m_memory.header()->setClickable(false);
44 m_memory.setContextMenuPolicy(Qt::NoContextMenu); // defer to parent
46 // create layout
47 m_layout.setSpacing(2);
48 m_layout.addWidget(&m_expression, 0);
49 m_layout.addWidget(&m_memory, 10);
50 m_layout.activate();
52 connect(&m_expression, SIGNAL(activated(const QString&)),
53 this, SLOT(slotNewExpression(const QString&)));
54 connect(m_expression.lineEdit(), SIGNAL(returnPressed()),
55 this, SLOT(slotNewExpression()));
57 // the popup menu
58 QAction* pAction;
59 pAction = m_popup.addAction(i18n("B&ytes"));
60 pAction->setData(MDTbyte);
61 pAction = m_popup.addAction(i18n("Halfwords (&2 Bytes)"));
62 pAction->setData(MDThalfword);
63 pAction = m_popup.addAction(i18n("Words (&4 Bytes)"));
64 pAction->setData(MDTword);
65 pAction = m_popup.addAction(i18n("Giantwords (&8 Bytes)"));
66 pAction->setData(MDTgiantword);
67 m_popup.addSeparator();
68 pAction = m_popup.addAction(i18n("He&xadecimal"));
69 pAction->setData(MDThex);
70 pAction = m_popup.addAction(i18n("Signed &decimal"));
71 pAction->setData(MDTsigned);
72 pAction = m_popup.addAction(i18n("&Unsigned decimal"));
73 pAction->setData(MDTunsigned);
74 pAction = m_popup.addAction(i18n("&Octal"));
75 pAction->setData(MDToctal);
76 pAction = m_popup.addAction(i18n("&Binary"));
77 pAction->setData(MDTbinary);
78 pAction = m_popup.addAction(i18n("&Addresses"));
79 pAction->setData(MDTaddress);
80 pAction = m_popup.addAction(i18n("&Character"));
81 pAction->setData(MDTchar);
82 pAction = m_popup.addAction(i18n("&Floatingpoint"));
83 pAction->setData(MDTfloat);
84 pAction = m_popup.addAction(i18n("&Strings"));
85 pAction->setData(MDTstring);
86 pAction = m_popup.addAction(i18n("&Instructions"));
87 pAction->setData(MDTinsn);
88 connect(&m_popup, SIGNAL(triggered(QAction*)), this, SLOT(slotTypeChange(QAction*)));
91 MemoryWindow::~MemoryWindow()
95 void MemoryWindow::contextMenuEvent(QContextMenuEvent* ev)
97 m_popup.popup(ev->globalPos());
98 ev->accept();
101 void MemoryWindow::slotNewExpression()
103 slotNewExpression(m_expression.lineEdit()->text());
106 void MemoryWindow::slotNewExpression(const QString& newText)
108 QString text = newText.simplified();
110 // see if the string is in the list
111 // (note: must count downwards because of removeItem!)
112 for (int i = m_expression.count()-1; i >= 0; i--)
114 if (m_expression.itemText(i) == text) {
115 // yes it is!
116 // look up the format that was used last time for this expr
117 QMap<QString,unsigned>::iterator pFormat = m_formatCache.find(text);
118 if (pFormat != m_formatCache.end()) {
119 m_format = *pFormat;
120 m_debugger->setMemoryFormat(m_format);
122 // remove this text, will be inserted at the top
123 m_expression.removeItem(i);
126 m_expression.insertItem(0, text);
128 if (!text.isEmpty()) {
129 m_formatCache[text] = m_format;
132 displayNewExpression(text);
135 void MemoryWindow::displayNewExpression(const QString& expr)
137 m_debugger->setMemoryExpression(expr);
138 m_expression.setEditText(expr);
140 // clear memory dump if no dump wanted
141 if (expr.isEmpty()) {
142 m_memory.clear();
143 m_old_memory.clear();
147 void MemoryWindow::slotTypeChange(QAction* action)
149 int id = action->data().toInt();
151 m_old_memory.clear();
153 // compute new type
154 if (id & MDTsizemask)
155 m_format = (m_format & ~MDTsizemask) | id;
156 if (id & MDTformatmask)
157 m_format = (m_format & ~MDTformatmask) | id;
158 m_debugger->setMemoryFormat(m_format);
160 // change the format in the cache
161 QString expr = m_expression.currentText();
162 m_formatCache[expr.simplified()] = m_format;
164 // force redisplay
165 displayNewExpression(expr);
168 void MemoryWindow::slotNewMemoryDump(const QString& msg, const std::list<MemoryDump>& memdump)
170 m_memory.clear();
171 if (!msg.isEmpty()) {
172 new QTreeWidgetItem(&m_memory, QStringList() << QString() << msg);
173 return;
176 std::list<MemoryDump>::const_iterator md = memdump.begin();
178 // show only needed columns
179 QStringList sl = md->dump.split( "\t" );
180 for (int i = m_memory.columnCount()-1; i > 0; i--)
181 m_memory.setColumnHidden(i, i > sl.count());
183 QMap<QString,QString> tmpMap;
185 for (; md != memdump.end(); ++md)
187 QString addr = md->address.asString() + " " + md->address.fnoffs;
188 QStringList sl = md->dump.split( "\t" );
190 // save memory
191 tmpMap[addr] = md->dump;
193 QTreeWidgetItem* line =
194 new QTreeWidgetItem(&m_memory, QStringList(addr) << sl);
196 QStringList tmplist;
197 QMap<QString,QString>::Iterator pos = m_old_memory.find( addr );
199 if( pos != m_old_memory.end() )
200 tmplist = pos.value().split( "\t" );
202 for (int i = 0; i < sl.count(); i++)
204 bool changed =
205 i < tmplist.count() &&
206 sl[i] != tmplist[i];
207 line->setForeground(i+1, changed ? QBrush(QColor(Qt::red)) : palette().text());
211 m_old_memory.clear();
212 m_old_memory = tmpMap;
215 static const char MemoryGroup[] = "Memory";
216 static const char NumExprs[] = "NumExprs";
217 static const char ExpressionFmt[] = "Expression%d";
218 static const char FormatFmt[] = "Format%d";
219 static const char ColumnWidths[] = "ColumnWidths";
221 void MemoryWindow::saveProgramSpecific(KConfigBase* config)
223 KConfigGroup g = config->group(MemoryGroup);
225 int numEntries = m_expression.count();
226 g.writeEntry(NumExprs, numEntries);
227 QString exprEntry;
228 QString fmtEntry;
229 for (int i = 0; i < numEntries;) {
230 QString text = m_expression.itemText(i);
231 i++; /* entries are counted 1-based */
232 exprEntry.sprintf(ExpressionFmt, i);
233 fmtEntry.sprintf(FormatFmt, i);
234 g.writeEntry(exprEntry, text);
235 QMap<QString,unsigned>::iterator pFormat = m_formatCache.find(text);
236 unsigned fmt = pFormat != m_formatCache.end() ? *pFormat : MDTword | MDThex;
237 g.writeEntry(fmtEntry, fmt);
240 // column widths
241 QList<int> widths;
242 for (int i = 0; i < 2; i++) {
243 int w = m_memory.columnWidth(i);
244 widths.append(w);
246 g.writeEntry(ColumnWidths, widths);
249 void MemoryWindow::restoreProgramSpecific(KConfigBase* config)
251 KConfigGroup g = config->group(MemoryGroup);
253 int numEntries = g.readEntry(NumExprs, 0);
254 m_expression.clear();
256 QString exprEntry;
257 QString fmtEntry;
258 // entries are counted 1-based
259 for (int i = 1; i <= numEntries; i++) {
260 exprEntry.sprintf(ExpressionFmt, i);
261 fmtEntry.sprintf(FormatFmt, i);
262 QString expr = g.readEntry(exprEntry, QString());
263 unsigned fmt = g.readEntry(fmtEntry, MDTword | MDThex);
264 m_expression.addItem(expr);
265 m_formatCache[expr] = fmt & (MDTsizemask | MDTformatmask);
268 // initialize with top expression
269 if (numEntries > 0) {
270 m_expression.setCurrentIndex(0);
271 QString expr = m_expression.itemText(0);
272 m_format = m_formatCache[expr];
273 m_debugger->setMemoryFormat(m_format);
274 displayNewExpression(expr);
277 // column widths
278 QList<int> widths = g.readEntry(ColumnWidths, QList<int>());
279 QList<int>::iterator w = widths.begin();
280 for (int i = 0; i < 2 && w != widths.end(); ++i, ++w) {
281 m_memory.setColumnWidth(i, *w);
286 #include "memwindow.moc"