~ubuntu-branches/ubuntu/utopic/openmsx-debugger/utopic

« back to all changes in this revision

Viewing changes to src/SymbolManager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Joost Yervante Damad
  • Date: 2009-12-06 07:40:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20091206074002-kssfkg1d6xbp6w9e
Tags: 0.0.0.svn20091206-1
New svn snapshot (Closes: #559612)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// $Id: SymbolManager.cpp 9347 2009-03-06 22:47:13Z m9710797 $
 
2
 
1
3
#include "SymbolManager.h"
2
4
#include "SymbolTable.h"
3
5
#include "Settings.h"
4
6
#include "Convert.h"
5
7
#include <QFileDialog>
6
8
#include <QMessageBox>
7
 
#include <QFile>
8
 
#include <QTextStream>
 
9
#include <QHeaderView>
9
10
 
10
 
SymbolManager::SymbolManager(SymbolTable& symtable, QWidget *parent)
 
11
SymbolManager::SymbolManager(SymbolTable& symtable, QWidget* parent)
11
12
        : QDialog(parent), symTable(symtable)
12
13
{
13
14
        setupUi(this);
14
15
 
 
16
        // restore layout
 
17
        Settings& s = Settings::get();
 
18
        restoreGeometry(s.value("SymbolManager/WindowGeometry", saveGeometry()).toByteArray());
 
19
        treeFiles->header()->restoreState(s.value("SymbolManager/HeaderFiles",
 
20
                                          treeFiles->header()->saveState()).toByteArray());
 
21
        treeLabels->header()->restoreState(s.value("SymbolManager/HeaderSymbols",
 
22
                                           treeLabels->header()->saveState()).toByteArray());
 
23
 
15
24
        treeLabelsUpdateCount = 0;
16
 
 
17
 
        connect( treeFiles, SIGNAL( itemSelectionChanged() ), this, SLOT( fileSelectionChange() ) );
18
 
        connect( btnAddFile, SIGNAL( clicked() ), this, SLOT( addFile() ) );
19
 
        connect( btnRemoveFile, SIGNAL( clicked() ), this, SLOT( removeFile() ) );
20
 
        connect( treeLabels, SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ),
21
 
                 this, SLOT( labelEdit( QTreeWidgetItem*, int ) ) );
22
 
        connect( treeLabels, SIGNAL( itemChanged( QTreeWidgetItem *, int ) ),
23
 
                 this, SLOT( labelChanged( QTreeWidgetItem*, int ) ) );
24
 
        connect( btnAddSymbol, SIGNAL( clicked() ), this, SLOT( addLabel() ) );
 
25
        editColumn = -1;
 
26
 
 
27
        // put slot checkboxes in a convenience array
 
28
        chkSlots[ 0] = chk00; chkSlots[ 1] = chk01; chkSlots[ 2] = chk02; chkSlots[ 3] = chk03;
 
29
        chkSlots[ 4] = chk10; chkSlots[ 5] = chk11; chkSlots[ 6] = chk12; chkSlots[ 7] = chk13;
 
30
        chkSlots[ 8] = chk20; chkSlots[ 9] = chk21; chkSlots[10] = chk22; chkSlots[11] = chk23;
 
31
        chkSlots[12] = chk30; chkSlots[13] = chk31; chkSlots[14] = chk32; chkSlots[15] = chk33;
 
32
        chkRegs[ 0] = chkRegA;  chkRegs[ 1] = chkRegB;  chkRegs[ 2] = chkRegC;  chkRegs[ 3] = chkRegD;
 
33
        chkRegs[ 4] = chkRegE;  chkRegs[ 5] = chkRegH;  chkRegs[ 6] = chkRegL;  chkRegs[ 7] = chkRegBC;
 
34
        chkRegs[ 8] = chkRegDE; chkRegs[ 9] = chkRegHL; chkRegs[10] = chkRegIX; chkRegs[11] = chkRegIY;
 
35
        chkRegs[12] = chkRegIXL;chkRegs[13] = chkRegIXH;chkRegs[14] = chkRegIYL;chkRegs[15] = chkRegIYH;
 
36
        chkRegs[16] = chkRegOffset; chkRegs[17] = chkRegI;
 
37
 
 
38
        connect(treeFiles, SIGNAL(itemSelectionChanged()), this, SLOT(fileSelectionChange()));
 
39
        connect(btnAddFile, SIGNAL(clicked()), this, SLOT(addFile()));
 
40
        connect(btnRemoveFile, SIGNAL(clicked()), this, SLOT(removeFile()));
 
41
        connect(btnReloadFiles, SIGNAL(clicked()), this, SLOT(reloadFiles()));
 
42
        connect(treeLabels, SIGNAL(itemSelectionChanged()), this, SLOT(labelSelectionChanged()));
 
43
        connect(treeLabels, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
 
44
                this, SLOT(labelEdit(QTreeWidgetItem*, int)));
 
45
        connect(treeLabels, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
 
46
                this, SLOT(labelChanged(QTreeWidgetItem*, int)));
 
47
        connect(btnAddSymbol, SIGNAL(clicked()), this, SLOT(addLabel()));
 
48
        connect(btnRemoveSymbol, SIGNAL(clicked()), this, SLOT(removeLabel()));
 
49
        connect(radJump, SIGNAL(toggled(bool)), this, SLOT(changeType(bool)));
 
50
        connect(radVar, SIGNAL(toggled(bool)), this, SLOT(changeType(bool)));
 
51
        connect(radValue, SIGNAL(toggled(bool)), this, SLOT(changeType(bool)));
 
52
        connect(chk00, SIGNAL(stateChanged(int)), this, SLOT(changeSlot00(int)));
 
53
        connect(chk01, SIGNAL(stateChanged(int)), this, SLOT(changeSlot01(int)));
 
54
        connect(chk02, SIGNAL(stateChanged(int)), this, SLOT(changeSlot02(int)));
 
55
        connect(chk03, SIGNAL(stateChanged(int)), this, SLOT(changeSlot03(int)));
 
56
        connect(chk10, SIGNAL(stateChanged(int)), this, SLOT(changeSlot10(int)));
 
57
        connect(chk11, SIGNAL(stateChanged(int)), this, SLOT(changeSlot11(int)));
 
58
        connect(chk12, SIGNAL(stateChanged(int)), this, SLOT(changeSlot12(int)));
 
59
        connect(chk13, SIGNAL(stateChanged(int)), this, SLOT(changeSlot13(int)));
 
60
        connect(chk20, SIGNAL(stateChanged(int)), this, SLOT(changeSlot20(int)));
 
61
        connect(chk21, SIGNAL(stateChanged(int)), this, SLOT(changeSlot21(int)));
 
62
        connect(chk22, SIGNAL(stateChanged(int)), this, SLOT(changeSlot22(int)));
 
63
        connect(chk23, SIGNAL(stateChanged(int)), this, SLOT(changeSlot23(int)));
 
64
        connect(chk30, SIGNAL(stateChanged(int)), this, SLOT(changeSlot30(int)));
 
65
        connect(chk31, SIGNAL(stateChanged(int)), this, SLOT(changeSlot31(int)));
 
66
        connect(chk32, SIGNAL(stateChanged(int)), this, SLOT(changeSlot32(int)));
 
67
        connect(chk33, SIGNAL(stateChanged(int)), this, SLOT(changeSlot33(int)));
 
68
        connect(chkRegA, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterA(int)));
 
69
        connect(chkRegB, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterB(int)));
 
70
        connect(chkRegC, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterC(int)));
 
71
        connect(chkRegD, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterD(int)));
 
72
        connect(chkRegE, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterE(int)));
 
73
        connect(chkRegH, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterH(int)));
 
74
        connect(chkRegL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterL(int)));
 
75
        connect(chkRegBC, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterBC(int)));
 
76
        connect(chkRegDE, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterDE(int)));
 
77
        connect(chkRegHL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterHL(int)));
 
78
        connect(chkRegIX, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIX(int)));
 
79
        connect(chkRegIY, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIY(int)));
 
80
        connect(chkRegIXL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIXL(int)));
 
81
        connect(chkRegIXH, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIXH(int)));
 
82
        connect(chkRegIYL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIYL(int)));
 
83
        connect(chkRegIYH, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIYH(int)));
 
84
        connect(chkRegOffset, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterOffset(int)));
 
85
        connect(chkRegI, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterI(int)));
25
86
 
26
87
        groupSlots->setEnabled(false);
27
88
        groupSegments->setEnabled(false);
32
93
        initSymbolList();
33
94
}
34
95
 
 
96
 
 
97
void SymbolManager::closeEvent(QCloseEvent* e)
 
98
{
 
99
        // store layout
 
100
        Settings& s = Settings::get();
 
101
        s.setValue("SymbolManager/WindowGeometry", saveGeometry());
 
102
        s.setValue("SymbolManager/HeaderFiles", treeFiles->header()->saveState());
 
103
        s.setValue("SymbolManager/HeaderSymbols", treeLabels->header()->saveState());
 
104
        QDialog::closeEvent(e);
 
105
}
 
106
 
35
107
/*
36
108
 * File list support functions
37
109
 */
39
111
void SymbolManager::initFileList()
40
112
{
41
113
        treeFiles->clear();
42
 
        for( int i = 0; i < symTable.symbolFilesSize(); i++ ) {
43
 
                QTreeWidgetItem *item = new QTreeWidgetItem(treeFiles);
44
 
                item->setText( 0, symTable.symbolFile(i) );
 
114
        for (int i = 0; i < symTable.symbolFilesSize(); ++i) {
 
115
                QTreeWidgetItem* item = new QTreeWidgetItem(treeFiles);
 
116
                item->setText(0, symTable.symbolFile(i));
 
117
                item->setText(1, symTable.symbolFileRefresh(i).toString(Qt::LocaleDate));
45
118
        }
46
119
}
47
120
 
48
121
void SymbolManager::addFile()
49
122
{
50
123
        // create dialog
51
 
        QFileDialog *d = new QFileDialog(this);
 
124
        QFileDialog* d = new QFileDialog(this);
52
125
        QStringList types;
53
 
        types << "Symbol files (*.sym)"
54
 
              << "TNIASM 0.x symbol files (*.sym)"
 
126
        types << "All supported files (*.sym *.map)"
 
127
              << "tniASM 0.x symbol files (*.sym)"
55
128
              << "asMSX 0.x symbol files (*.sym)"
56
129
              << "HiTech link map files (*.map)";
57
 
        d->setFilters( types );
58
 
        d->setAcceptMode( QFileDialog::AcceptOpen );
59
 
        d->setFileMode( QFileDialog::ExistingFile );
 
130
        d->setFilters(types);
 
131
        d->setAcceptMode(QFileDialog::AcceptOpen);
 
132
        d->setFileMode(QFileDialog::ExistingFile);
60
133
        // set default directory
61
 
        d->setDirectory( Settings::get().value("SymbolManager/OpenDir", QDir::currentPath() ).toString() );
 
134
        d->setDirectory(Settings::get().value("SymbolManager/OpenDir", QDir::currentPath()).toString());
62
135
        // run
63
 
        if( d->exec() ) {
 
136
        if (d->exec()) {
64
137
                QString f = d->selectedFilter();
65
138
                QString n = d->selectedFiles().at(0);
66
139
                // load file from the correct type
67
140
                bool read = false;
68
 
                if( f.startsWith( "TNIASM 0" ) ) {
69
 
                        read = symTable.readTNIASM0File( n );
70
 
                } else if( f.startsWith( "asMSX" ) ) {
71
 
                        read = symTable.readASMSXFile( n );
 
141
                if        (f.startsWith("tniASM 0")) {
 
142
                        read = symTable.readFile(n, SymbolTable::TNIASM_FILE);
 
143
                } else if (f.startsWith("asMSX")) {
 
144
                        read = symTable.readFile(n, SymbolTable::ASMSX_FILE);
 
145
                } else if (f.startsWith("HiTech")) {
 
146
                        read = symTable.readFile(n, SymbolTable::LINKMAP_FILE);
72
147
                } else {
73
 
                        if( n.endsWith(".sym") ) {
74
 
                                // auto detect which sym file
75
 
                                QFile file( n );
76
 
                                if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
77
 
                                        QTextStream in(&file);
78
 
                                        QString line = in.readLine();
79
 
                                        file.close();
80
 
                                        if( line[0] == ';' )
81
 
                                                read = symTable.readASMSXFile( n );
82
 
                                        else
83
 
                                                read = symTable.readTNIASM0File( n );
84
 
                                }
85
 
                        } else if ( n.endsWith(".map") ) {
86
 
                                // HiTech link map file
87
 
                                read = symTable.readLinkMapFile( n );
88
 
                        } 
 
148
                        read = symTable.readFile(n);
89
149
                }
90
150
                // if read succesful, add it to the list
91
 
                if( read ) {
92
 
                        QTreeWidgetItem *item = new QTreeWidgetItem(treeFiles);
93
 
                        item->setText( 0, d->selectedFiles().at(0) );
 
151
                if (read) {
 
152
                        initFileList();
94
153
                        initSymbolList();
 
154
                        emit symbolTableChanged();
95
155
                }
96
156
        }
97
 
        // story last used path
98
 
        Settings::get().setValue( "SymbolManager/OpenDir", d->directory().absolutePath() );
 
157
        // store last used path
 
158
        Settings::get().setValue("SymbolManager/OpenDir", d->directory().absolutePath());
99
159
}
100
160
 
101
161
void SymbolManager::removeFile()
102
162
{
103
 
        int r = QMessageBox::question(this, tr("Remove symbol file(s)"),
104
 
                tr("When removing the symbol file(s), do you want keep or delete the attached symbols?"),
 
163
        int r = QMessageBox::question(
 
164
                this,
 
165
                tr("Remove symbol file(s)"),
 
166
                tr("When removing the symbol file(s), do you want keep or "
 
167
                   "delete the attached symbols?"),
105
168
                "Keep symbols", "Delete symbols", "Cancel", 1, 2);
106
 
 
107
 
        if( r == 2 ) return;
108
 
 
109
 
        for( int i = 0; i < treeFiles->selectedItems().size(); i++ )
110
 
                symTable.unloadFile( treeFiles->selectedItems().at(i)->text(0), r == 0);
111
 
 
112
 
        initFileList();
113
 
        initSymbolList();
 
169
        if (r == 2) return;
 
170
 
 
171
        for (int i = 0; i < treeFiles->selectedItems().size(); ++i) {
 
172
                symTable.unloadFile(treeFiles->selectedItems().at(i)->text(0), r == 0);
 
173
        }
 
174
 
 
175
        initFileList();
 
176
        initSymbolList();
 
177
        emit symbolTableChanged();
 
178
}
 
179
 
 
180
void SymbolManager::reloadFiles()
 
181
{
 
182
        symTable.reloadFiles();
 
183
        initFileList();
 
184
        initSymbolList();
 
185
        emit symbolTableChanged();
114
186
}
115
187
 
116
188
void SymbolManager::fileSelectionChange()
117
189
{
118
 
        btnRemoveFile->setEnabled( treeFiles->selectedItems().size() );
 
190
        btnRemoveFile->setEnabled(treeFiles->selectedItems().size());
119
191
}
120
192
 
121
 
void SymbolManager::labelEdit( QTreeWidgetItem * item, int column )
 
193
void SymbolManager::labelEdit(QTreeWidgetItem* item, int column)
122
194
{
123
 
        if( column > 1 ) return;
124
 
        
125
 
        Symbol *sym = (Symbol *)(item->data(0, Qt::UserRole).value<quintptr>());
126
 
        if( sym->source() == 0 ) {
127
 
                treeLabels->openPersistentEditor( item, column );
 
195
        // only symbol name and value are editable
 
196
        if (column == 0 || column == 2) {
 
197
                // open editor if manually added symbol
 
198
                Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
 
199
                if (sym->source() == 0) {
 
200
                        // first close possible existing editor
 
201
                        closeEditor();
 
202
                        // open new editor
 
203
                        treeLabels->openPersistentEditor(item, column);
 
204
                        editItem = item;
 
205
                        editColumn = column;
 
206
                }
128
207
        }
129
208
}
130
209
 
136
215
{
137
216
        treeLabels->clear();
138
217
        beginTreeLabelsUpdate();
139
 
        Symbol *sym = symTable.findFirstAddressSymbol( 0 );
140
 
        while( sym != 0 ) {
141
 
                QTreeWidgetItem *item = new QTreeWidgetItem(treeLabels);
142
 
                item->setData(0L, Qt::UserRole, quintptr(sym) );
143
 
                item->setText( 0, sym->text() );
144
 
                item->setText( 1, QString("$%1").arg(sym->value(), 4, 16, QChar('0')) );
145
 
                switch( sym->status() ) {
146
 
                        case Symbol::HIDDEN:
147
 
                                item->setTextColor(0, QColor(128, 128, 128) );
148
 
                                break;
149
 
                        case Symbol::LOST:
150
 
                                item->setTextColor(0, QColor(128, 0, 0) );
151
 
                                break;
152
 
                        default:
153
 
                                break;
154
 
                }
155
 
                if( sym->source() )
156
 
                        item->setIcon( 0, QIcon(":/icons/symfil.png") );
157
 
                else
158
 
                        item->setIcon( 0, QIcon(":/icons/symman.png") );
159
 
                sym = symTable.findNextAddressSymbol();
 
218
        for (Symbol* sym = symTable.findFirstAddressSymbol(0);
 
219
             sym != 0;
 
220
             sym = symTable.findNextAddressSymbol()) {
 
221
                QTreeWidgetItem* item = new QTreeWidgetItem(treeLabels);
 
222
                // attach a pointer to the symbol object to the tree item
 
223
                item->setData(0L, Qt::UserRole, quintptr(sym));
 
224
                // update columns
 
225
                updateItemName(item);
 
226
                updateItemType(item);
 
227
                updateItemValue(item);
 
228
                updateItemSlots(item);
 
229
                updateItemSegments(item);
 
230
                updateItemRegisters(item);
160
231
        }
161
232
        endTreeLabelsUpdate();
162
233
}
163
234
 
164
235
void SymbolManager::beginTreeLabelsUpdate()
165
236
{
166
 
        treeLabelsUpdateCount++;
 
237
        ++treeLabelsUpdateCount;
167
238
}
168
239
 
169
240
void SymbolManager::endTreeLabelsUpdate()
170
241
{
171
 
        if( treeLabelsUpdateCount > 0 )
172
 
                treeLabelsUpdateCount--;
 
242
        if (treeLabelsUpdateCount > 0) {
 
243
                --treeLabelsUpdateCount;
 
244
        }
 
245
}
 
246
 
 
247
void SymbolManager::closeEditor()
 
248
{
 
249
        if (editColumn >= 0) {
 
250
                treeLabels->closePersistentEditor(editItem, editColumn);
 
251
                editColumn = -1;
 
252
        }
173
253
}
174
254
 
175
255
void SymbolManager::addLabel()
176
256
{
177
257
        // create an empty symbol
178
 
        Symbol *sym = new Symbol( tr("New symbol"), 0 );
179
 
        symTable.add( sym );
 
258
        Symbol* sym = new Symbol(tr("New symbol"), 0);
 
259
        symTable.add(sym);
180
260
 
181
261
        beginTreeLabelsUpdate();
182
 
        QTreeWidgetItem *item = new QTreeWidgetItem(treeLabels);
183
 
        item->setData(0, Qt::UserRole, quintptr(sym) );
184
 
        item->setText( 0, sym->text() );
185
 
        item->setText( 1, QString("$%1").arg(sym->value(), 4, 16, QChar('0')) );
186
 
        item->setIcon( 0, QIcon(":/icons/symman.png") );
 
262
        QTreeWidgetItem* item = new QTreeWidgetItem(treeLabels);
 
263
        item->setData(0, Qt::UserRole, quintptr(sym));
 
264
        updateItemName(item);
 
265
        updateItemType(item);
 
266
        updateItemValue(item);
 
267
        updateItemSlots(item);
 
268
        updateItemSegments(item);
 
269
        updateItemRegisters(item);
187
270
        endTreeLabelsUpdate();
 
271
        closeEditor();
 
272
        treeLabels->setFocus();
 
273
        treeLabels->setCurrentItem(item, 0);
188
274
        treeLabels->scrollToItem(item);
189
 
        treeLabels->openPersistentEditor( item, 0 );
190
 
}
191
 
 
192
 
void SymbolManager::labelChanged( QTreeWidgetItem *item, int column )
193
 
{
194
 
        if( !treeLabelsUpdateCount ) {
195
 
                Symbol *sym = (Symbol *)(item->data(0, Qt::UserRole).value<quintptr>());
196
 
                // Todo: add validity checks
197
 
                sym->setText( item->text(0) );
198
 
                int value = stringToValue( item->text(1) );
199
 
                if( value >= 0 ) sym->setValue( value );
200
 
                treeLabels->closePersistentEditor( item, column );
 
275
        treeLabels->openPersistentEditor(item, 0);
 
276
        editItem = item;
 
277
        editColumn = 0;
 
278
 
 
279
        // emit notification that something has changed
 
280
        emit symbolTableChanged();
 
281
}
 
282
 
 
283
void SymbolManager::removeLabel()
 
284
{
 
285
        QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
 
286
        // check for selection
 
287
        if (selection.empty()) return;
 
288
        // remove selected items
 
289
        bool deleted = false;
 
290
        for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
 
291
             selit != selection.end(); ++selit) {
 
292
                // get symbol
 
293
                Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
 
294
                // check if symbol is from symbol file
 
295
                if (!sym->source()) {
 
296
                        // remove from table
 
297
                        symTable.remove(sym);
 
298
                        deleted = true;
 
299
                }
 
300
        }
 
301
        if (deleted) {
 
302
                // refresh tree
 
303
                initSymbolList();
 
304
                emit symbolTableChanged();
 
305
        }
 
306
}
 
307
 
 
308
void SymbolManager::labelChanged(QTreeWidgetItem* item, int column)
 
309
{
 
310
        if (!treeLabelsUpdateCount) {
 
311
                Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
 
312
                // Set symbol text from tree item if any
 
313
                QString symText = item->text(0).trimmed();
 
314
                if (symText.isEmpty()) symText = "[unnamed]";
 
315
                sym->setText(symText);
 
316
                // set value TODO: proper decoding of value
 
317
                int value = stringToValue(item->text(2));
 
318
                if (value >= 0 && value < 65536) sym->setValue(value);
 
319
                treeLabels->closePersistentEditor(item, column);
 
320
                editColumn = -1;
 
321
                // update item name and value
 
322
                beginTreeLabelsUpdate();
 
323
                updateItemName(item);
 
324
                updateItemValue(item);
 
325
                endTreeLabelsUpdate();
 
326
                // notify change
 
327
                emit symbolTableChanged();
201
328
        }
202
329
}
203
330
 
204
331
void SymbolManager::labelSelectionChanged()
205
332
{
206
 
        //QList<QTreeWidgetItem *>
 
333
        // remove possible editor
 
334
        closeEditor();
 
335
 
 
336
        QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
 
337
        // check if is available at all
 
338
        if (selection.empty()) {
 
339
                // disable everything
 
340
                btnRemoveSymbol->setEnabled(false);
 
341
                groupSlots->setEnabled(false);
 
342
                groupSegments->setEnabled(false);
 
343
                groupType->setEnabled(false);
 
344
                groupRegs8->setEnabled(false);
 
345
                groupRegs16->setEnabled(false);
 
346
                return;
 
347
        }
 
348
        // check selection for "manual insertion", identical slot mask,
 
349
        // identical register mask, identical types and value size
 
350
        bool removeButActive = true;
 
351
        bool anyEight = false;
 
352
        bool sameType = true;
 
353
        Symbol::SymbolType type;
 
354
        int slotMask, slotMaskMultiple = 0;
 
355
        int regMask, regMaskMultiple = 0;
 
356
        for (QList<QTreeWidgetItem *>::iterator selit = selection.begin();
 
357
             selit != selection.end(); ++selit) {
 
358
                // get symbol
 
359
                Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
 
360
                // check if symbol is from symbol file
 
361
                if (sym->source()) removeButActive = false;
 
362
 
 
363
                if (selit == selection.begin()) {
 
364
                        // first item, reference for slotMask and regMask
 
365
                        slotMask = sym->validSlots();
 
366
                        regMask = sym->validRegisters();
 
367
                        type = sym->type();
 
368
                } else {
 
369
                        // other, set all different bits
 
370
                        slotMaskMultiple |= slotMask ^ sym->validSlots();
 
371
                        regMaskMultiple |= regMask ^ sym->validRegisters();
 
372
                        // check for different type
 
373
                        if (type != sym->type()) sameType = false;
 
374
                }
 
375
 
 
376
                // check for 8 bit values
 
377
                if ((sym->value() & 0xFF00) == 0) {
 
378
                        anyEight = true;
 
379
                }
 
380
        }
 
381
 
 
382
        btnRemoveSymbol->setEnabled(removeButActive);
 
383
        groupSlots->setEnabled(true);
 
384
        groupType->setEnabled(true);
 
385
        groupRegs8->setEnabled(anyEight);
 
386
        groupRegs16->setEnabled(true);
 
387
        beginTreeLabelsUpdate();
 
388
 
 
389
        // set slot selection
 
390
        for (int i = 0; i < 16; ++i) {
 
391
                chkSlots[i]->setTristate(false);
 
392
                if (slotMaskMultiple & 1) {
 
393
                        chkSlots[i]->setCheckState(Qt::PartiallyChecked);
 
394
                } else if (slotMask & 1) {
 
395
                        chkSlots[i]->setCheckState(Qt::Checked);
 
396
                } else {
 
397
                        chkSlots[i]->setCheckState(Qt::Unchecked);
 
398
                }
 
399
                slotMask >>= 1;
 
400
                slotMaskMultiple >>= 1;
 
401
        }
 
402
        // set register selection
 
403
        for (int i = 0; i < 18; ++i) {
 
404
                chkRegs[i]->setTristate(false);
 
405
                if (regMaskMultiple & 1) {
 
406
                        chkRegs[i]->setCheckState(Qt::PartiallyChecked);
 
407
                } else if (regMask & 1) {
 
408
                        chkRegs[i]->setCheckState(Qt::Checked);
 
409
                } else {
 
410
                        chkRegs[i]->setCheckState(Qt::Unchecked);
 
411
                }
 
412
                regMask >>= 1;
 
413
                regMaskMultiple >>= 1;
 
414
        }
 
415
 
 
416
        // temporarily disable exclusive radiobuttons to be able to
 
417
        // deselect them all.
 
418
        radJump->setAutoExclusive (false);
 
419
        radVar->setAutoExclusive  (false);
 
420
        radValue->setAutoExclusive(false);
 
421
        // set type radio buttons
 
422
        radJump->setChecked (sameType && type == Symbol::JUMPLABEL);
 
423
        radVar->setChecked  (sameType && type == Symbol::VARIABLELABEL);
 
424
        radValue->setChecked(sameType && type == Symbol::VALUE);
 
425
        // enable exclusive radiobuttons (this won't immediately activate
 
426
        // one if none are active).
 
427
        radJump->setAutoExclusive (true);
 
428
        radVar->setAutoExclusive  (true);
 
429
        radValue->setAutoExclusive(true);
 
430
        endTreeLabelsUpdate();
 
431
}
 
432
 
 
433
void SymbolManager::changeSlot(int id, int state)
 
434
{
 
435
        if (treeLabelsUpdateCount) return;
 
436
 
 
437
        // disallow another tristate selection
 
438
        chkSlots[id]->setTristate(false);
 
439
        // get selected items
 
440
        QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
 
441
 
 
442
        // update items
 
443
        beginTreeLabelsUpdate();
 
444
        int bit = 1 << id;
 
445
        for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
 
446
             selit != selection.end(); ++selit) {
 
447
                Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
 
448
                // set or clear bit
 
449
                if (state == Qt::Checked) {
 
450
                        sym->setValidSlots(sym->validSlots() |  bit);
 
451
                } else {
 
452
                        sym->setValidSlots(sym->validSlots() & ~bit);
 
453
                }
 
454
                // update item in treewidget
 
455
                updateItemSlots(*selit);
 
456
        }
 
457
        endTreeLabelsUpdate();
 
458
        // notify change
 
459
        emit symbolTableChanged();
 
460
}
 
461
 
 
462
void SymbolManager::changeRegister(int id, int state)
 
463
{
 
464
        if (treeLabelsUpdateCount) return;
 
465
 
 
466
        // disallow another tristate selection
 
467
        chkRegs[id]->setTristate(false);
 
468
        // get selected items
 
469
        QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
 
470
 
 
471
        // update items
 
472
        beginTreeLabelsUpdate();
 
473
        int bit = 1 << id;
 
474
        for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
 
475
             selit != selection.end(); ++selit) {
 
476
                Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
 
477
                // set or clear bit
 
478
                if (state == Qt::Checked) {
 
479
                        sym->setValidRegisters(sym->validRegisters() |  bit);
 
480
                } else {
 
481
                        sym->setValidRegisters(sym->validRegisters() & ~bit);
 
482
                }
 
483
                // update item in treewidget
 
484
                updateItemRegisters(*selit);
 
485
        }
 
486
        endTreeLabelsUpdate();
 
487
        // notify change
 
488
        emit symbolTableChanged();
 
489
}
 
490
 
 
491
void SymbolManager::changeType(bool /*checked*/)
 
492
{
 
493
        if (treeLabelsUpdateCount) return;
 
494
 
 
495
        // determine selected type
 
496
        Symbol::SymbolType newType = Symbol::JUMPLABEL;
 
497
        if (radVar->isChecked()) {
 
498
                newType = Symbol::VARIABLELABEL;
 
499
        } else if (radValue->isChecked()) {
 
500
                newType = Symbol::VALUE;
 
501
        }
 
502
 
 
503
        // get selected items
 
504
        QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
 
505
 
 
506
        // update items
 
507
        beginTreeLabelsUpdate();
 
508
        for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
 
509
             selit != selection.end(); ++selit) {
 
510
                Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
 
511
                sym->setType(newType);
 
512
                updateItemType(*selit);
 
513
        }
 
514
        endTreeLabelsUpdate();
 
515
        // notify change
 
516
        emit symbolTableChanged();
 
517
}
 
518
 
 
519
 
 
520
/*
 
521
 * Symbol tree layout functions
 
522
 */
 
523
 
 
524
void SymbolManager::updateItemName(QTreeWidgetItem* item)
 
525
{
 
526
        Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
 
527
        // set text and icon
 
528
        item->setText(0, sym->text());
 
529
        if (sym->source()) {
 
530
                item->setIcon(0, QIcon(":/icons/symfil.png"));
 
531
                item->setText(6, *sym->source());
 
532
        } else {
 
533
                item->setIcon(0, QIcon(":/icons/symman.png"));
 
534
        }
 
535
        // set color based on status as well as status in 2nd column
 
536
        switch (sym->status()) {
 
537
        case Symbol::HIDDEN:
 
538
                item->setTextColor(0, QColor(128, 128, 128));
 
539
                break;
 
540
        case Symbol::LOST:
 
541
                item->setTextColor(0, QColor(128, 0, 0));
 
542
                break;
 
543
        default:
 
544
                break;
 
545
        }
 
546
}
 
547
 
 
548
void SymbolManager::updateItemType(QTreeWidgetItem* item)
 
549
{
 
550
        Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
 
551
        // set symbol type in 2nd column
 
552
        switch (sym->type()) {
 
553
        case Symbol::JUMPLABEL:
 
554
                item->setText(1, tr("Jump label"));
 
555
                break;
 
556
        case Symbol::VARIABLELABEL:
 
557
                item->setText(1, tr("Variable label"));
 
558
                break;
 
559
        case Symbol::VALUE:
 
560
                item->setText(1, tr("Value"));
 
561
                break;
 
562
        }
 
563
}
 
564
 
 
565
void SymbolManager::updateItemValue(QTreeWidgetItem* item)
 
566
{
 
567
        Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
 
568
 
 
569
        // symbol value in 3rd column
 
570
        // TODO: Custom prefix/postfix
 
571
        item->setText(2, QString("$%1").arg(sym->value(), 4, 16, QChar('0')));
 
572
}
 
573
 
 
574
void SymbolManager::updateItemSlots(QTreeWidgetItem* item)
 
575
{
 
576
        Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
 
577
 
 
578
        QString slotText;
 
579
        int slotmask = sym->validSlots();
 
580
        // value represents 16 bits for 4 subslots in 4 slots
 
581
        if (slotmask == 0xFFFF) {
 
582
                slotText = tr("All");
 
583
        } else if (slotmask == 0) {
 
584
                slotText = tr("None");
 
585
        } else {
 
586
                // create a list of valid slots
 
587
                // loop over all primary slots
 
588
                for (int ps = 0; ps < 4; ++ps) {
 
589
                        QString subText;
 
590
                        int subslots = (slotmask >> (4 * ps)) & 15;
 
591
                        if (subslots == 15) {
 
592
                                // all subslots are ok
 
593
                                subText = QString("%1-*").arg(ps);
 
594
                        } else if (subslots) {
 
595
                                // some subslots are ok
 
596
                                if (subslots & 1) subText += "/0";
 
597
                                if (subslots & 2) subText += "/1";
 
598
                                if (subslots & 4) subText += "/2";
 
599
                                if (subslots & 8) subText += "/3";
 
600
                                subText = QString("%1-").arg(ps) + subText.mid(1);
 
601
                        }
 
602
                        // add to string if any subslots were ok
 
603
                        if (!subText.isEmpty()) {
 
604
                                if (!slotText.isEmpty()) slotText += ", ";
 
605
                                slotText += subText;
 
606
                        }
 
607
                }
 
608
        }
 
609
 
 
610
        // valid slots in 4th column
 
611
        item->setText(3, slotText);
 
612
}
 
613
 
 
614
void SymbolManager::updateItemSegments(QTreeWidgetItem* item)
 
615
{
 
616
        item->data(0, Qt::UserRole).value<quintptr>();
 
617
}
 
618
 
 
619
void SymbolManager::updateItemRegisters(QTreeWidgetItem* item)
 
620
{
 
621
        Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
 
622
 
 
623
        QString regText;
 
624
        int regmask = sym->validRegisters();
 
625
        // value represents 16 bits for 4 subslots in 4 slots
 
626
        if (regmask == 0x3FFFF) {
 
627
                regText = tr("All");
 
628
        } else if (regmask == 0) {
 
629
                regText = tr("None");
 
630
        } else {
 
631
                if ((regmask & Symbol::REG_ALL8) == Symbol::REG_ALL8) {
 
632
                        // all 8 bit registers selected
 
633
                        regText = "All 8 bit, ";
 
634
                        regmask ^= Symbol::REG_ALL8;
 
635
                } else if ((regmask & Symbol::REG_ALL16) == Symbol::REG_ALL16) {
 
636
                        // all 16 bit registers selected
 
637
                        regText = "All 16 bit, ";
 
638
                        regmask ^= Symbol::REG_ALL16;
 
639
                }
 
640
                // register list for remaining registers
 
641
                static const char* const registers[] = {
 
642
                        "A", "B", "C", "D", "E", "H", "L", "BC", "DE", "HL",
 
643
                        "IX", "IY", "IXL", "IXH", "IYL", "IYH", "Offset", "I"
 
644
                };
 
645
                for (int i = 0; i < 18; ++i) {
 
646
                        if (regmask & 1) {
 
647
                                regText += QString("%1, ").arg(registers[i]);
 
648
                        }
 
649
                        regmask >>= 1;
 
650
                }
 
651
                regText.chop(2);
 
652
        }
 
653
 
 
654
        // valid slots in 4th column
 
655
        item->setText(5, regText);
 
656
}
 
657
 
 
658
 
 
659
// load of functions that shouldn't really be necessary
 
660
void SymbolManager::changeSlot00(int state)
 
661
{
 
662
        changeSlot(0, state);
 
663
}
 
664
void SymbolManager::changeSlot01(int state)
 
665
{
 
666
        changeSlot(1, state);
 
667
}
 
668
void SymbolManager::changeSlot02(int state)
 
669
{
 
670
        changeSlot(2, state);
 
671
}
 
672
void SymbolManager::changeSlot03(int state)
 
673
{
 
674
        changeSlot(3, state);
 
675
}
 
676
void SymbolManager::changeSlot10(int state)
 
677
{
 
678
        changeSlot(4, state);
 
679
}
 
680
void SymbolManager::changeSlot11(int state)
 
681
{
 
682
        changeSlot(5, state);
 
683
}
 
684
void SymbolManager::changeSlot12(int state)
 
685
{
 
686
        changeSlot(6, state);
 
687
}
 
688
void SymbolManager::changeSlot13(int state)
 
689
{
 
690
        changeSlot(7, state);
 
691
}
 
692
void SymbolManager::changeSlot20(int state)
 
693
{
 
694
        changeSlot(8, state);
 
695
}
 
696
void SymbolManager::changeSlot21(int state)
 
697
{
 
698
        changeSlot(9, state);
 
699
}
 
700
void SymbolManager::changeSlot22(int state)
 
701
{
 
702
        changeSlot(10, state);
 
703
}
 
704
void SymbolManager::changeSlot23(int state)
 
705
{
 
706
        changeSlot(11, state);
 
707
}
 
708
void SymbolManager::changeSlot30(int state)
 
709
{
 
710
        changeSlot(12, state);
 
711
}
 
712
void SymbolManager::changeSlot31(int state)
 
713
{
 
714
        changeSlot(13, state);
 
715
}
 
716
void SymbolManager::changeSlot32(int state)
 
717
{
 
718
        changeSlot(14, state);
 
719
}
 
720
void SymbolManager::changeSlot33(int state)
 
721
{
 
722
        changeSlot(15, state);
 
723
}
 
724
void SymbolManager::changeRegisterA(int state)
 
725
{
 
726
        changeRegister(0, state);
 
727
}
 
728
void SymbolManager::changeRegisterB(int state)
 
729
{
 
730
        changeRegister(1, state);
 
731
}
 
732
void SymbolManager::changeRegisterC(int state)
 
733
{
 
734
        changeRegister(2, state);
 
735
}
 
736
void SymbolManager::changeRegisterD(int state)
 
737
{
 
738
        changeRegister(3, state);
 
739
}
 
740
void SymbolManager::changeRegisterE(int state)
 
741
{
 
742
        changeRegister(4, state);
 
743
}
 
744
void SymbolManager::changeRegisterH(int state)
 
745
{
 
746
        changeRegister(5, state);
 
747
}
 
748
void SymbolManager::changeRegisterL(int state)
 
749
{
 
750
        changeRegister(6, state);
 
751
}
 
752
void SymbolManager::changeRegisterBC(int state)
 
753
{
 
754
        changeRegister(7, state);
 
755
}
 
756
void SymbolManager::changeRegisterDE(int state)
 
757
{
 
758
        changeRegister(8, state);
 
759
}
 
760
void SymbolManager::changeRegisterHL(int state)
 
761
{
 
762
        changeRegister(9, state);
 
763
}
 
764
void SymbolManager::changeRegisterIX(int state)
 
765
{
 
766
        changeRegister(10, state);
 
767
}
 
768
void SymbolManager::changeRegisterIY(int state)
 
769
{
 
770
        changeRegister(11, state);
 
771
}
 
772
void SymbolManager::changeRegisterIXL(int state)
 
773
{
 
774
        changeRegister(12, state);
 
775
}
 
776
void SymbolManager::changeRegisterIXH(int state)
 
777
{
 
778
        changeRegister(13, state);
 
779
}
 
780
void SymbolManager::changeRegisterIYL(int state)
 
781
{
 
782
        changeRegister(14, state);
 
783
}
 
784
void SymbolManager::changeRegisterIYH(int state)
 
785
{
 
786
        changeRegister(15, state);
 
787
}
 
788
void SymbolManager::changeRegisterOffset(int state)
 
789
{
 
790
        changeRegister(16, state);
 
791
}
 
792
void SymbolManager::changeRegisterI(int state)
 
793
{
 
794
        changeRegister(17, state);
207
795
}