Repository navigation
Expand file tree
/
Copy pathEditDialog.cpp
More file actions
357 lines (300 loc) · 10.4 KB
/
Copy pathEditDialog.cpp
File metadata and controls
357 lines (300 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#include "EditDialog.h"
#include "ui_EditDialog.h"
#include "sqlitedb.h"
#include "PreferencesDialog.h"
#include "src/qhexedit.h"
#include "FileDialog.h"
#include <QMainWindow>
#include <QKeySequence>
#include <QShortcut>
#include <QImageReader>
#include <QBuffer>
EditDialog::EditDialog(QWidget* parent)
: QDialog(parent),
ui(new Ui::EditDialog)
{
ui->setupUi(this);
// Add Ctrl-Enter (Cmd-Enter on OSX) as a shortcut for the Apply button
ui->buttonApply->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return));
QHBoxLayout* hexLayout = new QHBoxLayout(ui->editorBinary);
hexEdit = new QHexEdit(this);
hexLayout->addWidget(hexEdit);
hexEdit->setOverwriteMode(false);
connect(hexEdit, SIGNAL(dataChanged()), this, SLOT(hexDataChanged()));
QShortcut* ins = new QShortcut(QKeySequence(Qt::Key_Insert), this);
connect(ins, SIGNAL(activated()), this, SLOT(toggleOverwriteMode()));
reset();
}
EditDialog::~EditDialog()
{
delete ui;
}
void EditDialog::reset()
{
// Set the font for the text and hex editors
QFont editorFont(PreferencesDialog::getSettingsValue("databrowser", "font").toString());
editorFont.setPointSize(PreferencesDialog::getSettingsValue("databrowser", "fontsize").toInt());
ui->editorText->setFont(editorFont);
hexEdit->setFont(editorFont);
curRow = -1;
curCol = -1;
ui->editorText->clear();
ui->editorText->setFocus();
ui->editorImage->clear();
hexEdit->setData(QByteArray());
oldData = "";
// Hide the warning about editing non-text data in text mode
ui->labelBinaryWarning->setVisible(false);
// Update the cell data info in the bottom left of the Edit Cell
int dataType = checkDataType();
updateCellInfo(dataType);
}
void EditDialog::closeEvent(QCloseEvent*)
{
emit goingAway();
}
void EditDialog::showEvent(QShowEvent*)
{
// Whenever the dialog is shown, position it at the center of the parent dialog
QMainWindow* parentDialog = qobject_cast<QMainWindow*>(parent());
if(parentDialog)
{
move(parentDialog->x() + parentDialog->width() / 2 - width() / 2,
parentDialog->y() + parentDialog->height() / 2 - height() / 2);
}
}
void EditDialog::reject()
{
// We override this, to ensure the Escape key doesn't make the Edit Cell
// dock go away
return;
}
void EditDialog::loadText(const QByteArray& data, int row, int col)
{
curRow = row;
curCol = col;
oldData = data;
// Load data
QString textData = QString::fromUtf8(data.constData(), data.size());
ui->editorText->setPlainText(textData);
hexEdit->setData(data);
// Determine the data type in the cell
int dataType = checkDataType();
// Do some data type specific handling
QImage img;
switch (dataType) {
case Text:
// For text, ensure it's all selected in the Edit Cell
ui->editorText->selectAll();
// Clear any image from the image viewing widget
ui->editorImage->setPixmap(QPixmap(0,0));
break;
case Image:
// For images, load the image into the image viewing widget
if (img.loadFromData(hexEdit->data())) {
ui->editorImage->setPixmap(QPixmap::fromImage(img));
}
break;
default:
// Clear the image viewing widget for everything else too
ui->editorImage->setPixmap(QPixmap(0,0));
break;
}
// Get the current editor mode (eg text, hex, or image mode)
int editMode = ui->editorStack->currentIndex();
// Show or hide the warning about editing binary data in text mode
updateBinaryEditWarning(editMode, dataType);
// Update the cell data info in the bottom left of the Edit Cell
updateCellInfo(dataType);
}
void EditDialog::importData()
{
// Get list of supported image file formats to include them in the file dialog filter
QString image_formats;
QList<QByteArray> image_formats_list = QImageReader::supportedImageFormats();
for(int i=0;i<image_formats_list.size();++i)
image_formats.append(QString("*.%1 ").arg(QString::fromUtf8(image_formats_list.at(i))));
QString fileName = FileDialog::getOpenFileName(
this,
tr("Choose a file")
#ifndef Q_OS_MAC // Filters on OS X are buggy
, tr("Text files(*.txt);;Image files(%1);;All files(*)").arg(image_formats)
#endif
);
if(QFile::exists(fileName))
{
QFile file(fileName);
if(file.open(QIODevice::ReadOnly))
{
QByteArray d = file.readAll();
hexEdit->setData(d);
ui->editorText->setPlainText(d);
file.close();
// Update the cell data info in the bottom left of the Edit Cell
int dataType = checkDataType();
updateCellInfo(dataType);
}
}
}
void EditDialog::exportData()
{
QString fileName = FileDialog::getSaveFileName(
this,
tr("Choose a filename to export data"),
tr("Text files(*.txt);;All files(*)"));
if(fileName.size() > 0)
{
QFile file(fileName);
if(file.open(QIODevice::WriteOnly))
{
file.write(hexEdit->data());
file.close();
}
}
}
void EditDialog::setNull()
{
ui->editorText->clear();
ui->editorImage->clear();
hexEdit->setData(QByteArray());
// Update the cell data info in the bottom left of the Edit Cell
int dataType = checkDataType();
updateCellInfo(dataType);
ui->editorText->setFocus();
}
void EditDialog::accept()
{
// Don't update if the data hasn't changed
// To differentiate NULL and empty byte arrays, we also compare the NULL flag
if(hexEdit->data() != oldData || hexEdit->data().isNull() != oldData.isNull())
{
const QString dataType = ui->comboMode->currentText();
bool isBlob = dataType == tr("Binary");
emit updateRecordText(curRow, curCol, isBlob, hexEdit->data());
}
}
// Called when the user manually changes the "Mode" drop down combobox
void EditDialog::editModeChanged(int editMode)
{
// Switch to the selected editor
ui->editorStack->setCurrentIndex(editMode);
// Show or hide the warning about editing binary data in text mode
int dataType = checkDataType();
updateBinaryEditWarning(editMode, dataType);
}
void EditDialog::editTextChanged()
{
if(ui->editorText->hasFocus())
{
hexEdit->blockSignals(true);
hexEdit->setData(ui->editorText->toPlainText().toUtf8());
hexEdit->blockSignals(false);
// Update the cell data info in the bottom left of the Edit Cell
int dataType = checkDataType();
updateCellInfo(dataType);
}
}
void EditDialog::hexDataChanged()
{
// Update the text editor accordingly
ui->editorText->blockSignals(true);
ui->editorText->setPlainText(QString::fromUtf8(hexEdit->data().constData(), hexEdit->data().size()));
ui->editorText->blockSignals(false);
}
// Determine the type of data in the cell
int EditDialog::checkDataType()
{
QByteArray cellData = hexEdit->data();
// Check for NULL data type
if (cellData.isNull()) {
return Null;
}
// Check if it's an image
QBuffer imageBuffer(&cellData);
QImageReader readerBuffer(&imageBuffer);
bool someCheck = readerBuffer.canRead();
if (someCheck == true) {
return Image;
}
// Check if it's text only
if (QString(cellData).toUtf8() == cellData) { // Is there a better way to check this?
return Text;
}
// It's none of the above, so treat it as general binary data
return Binary;
}
void EditDialog::toggleOverwriteMode()
{
static bool currentMode = false;
currentMode = !currentMode;
hexEdit->setOverwriteMode(currentMode);
ui->editorText->setOverwriteMode(currentMode);
}
void EditDialog::setFocus()
{
QDialog::setFocus();
// Set the focus to the editor widget. The idea here is that setting focus
// to the dock itself doesn't make much sense as it's just a frame; you'd
// have to tab to the editor which is what you most likely want to use. So
// in order to save the user from doing this we explicitly set the focus
// to the editor.
ui->editorText->setFocus();
ui->editorText->selectAll();
}
// Enables or disables the Apply, Null, & Import buttons in the Edit Cell dock
void EditDialog::allowEditing(bool on)
{
ui->buttonApply->setEnabled(on);
ui->buttonNull->setEnabled(on);
ui->buttonImport->setEnabled(on);
}
// Shows or hides the warning about editing binary data in text mode
void EditDialog::updateBinaryEditWarning(int editMode, int dataType)
{
// If we're in the text editor, and the data type is not plain text
// display a warning about editing it
if ((editMode == 0) && ((dataType != Text) && (dataType != Null))) {
// Display the warning
ui->labelBinaryWarning->setVisible(true);
} else {
// Hide the warning
ui->labelBinaryWarning->setVisible(false);
}
}
// Update the information labels in the bottom left corner of the dialog
void EditDialog::updateCellInfo(int cellType)
{
QByteArray cellData = hexEdit->data();
// Image data needs special treatment
if (cellType == Image) {
QBuffer imageBuffer(&cellData);
QImageReader image(&imageBuffer);
// Display the image format
QString imageFormat = image.format();
ui->labelType->setText(tr("Type of data currently in cell: %1 Image").arg(imageFormat.toUpper()));
// Display the image dimensions
QSize imageSize = image.size();
ui->labelSize->setText(tr("%1x%2 pixel(s)").arg(imageSize.width()).arg(imageSize.height()));
return;
}
// Determine the legth of the cell data
int dataLength = cellData.length();
// Use a switch statement for the other data types to keep things neat :)
switch (cellType) {
case Null:
// NULL data type
ui->labelType->setText(tr("Type of data currently in cell: NULL"));
ui->labelSize->setText(tr("%n byte(s)", "", dataLength));
break;
case Text:
// Text only
ui->labelType->setText(tr("Type of data currently in cell: Text / Numeric"));
ui->labelSize->setText(tr("%n char(s)", "", dataLength));
break;
default:
// If none of the above data types, consider it general binary data
ui->labelType->setText(tr("Type of data currently in cell: Binary"));
ui->labelSize->setText(tr("%n byte(s)", "", dataLength));
break;
}
}