Skip to content

Commit 2d4c5ce

Browse files
committed
Support inline preview of image data in cells
This adds a new option in the Preferences dialog to enable a preview of images in BLOB cells directly in the grid view of the Browse Data tab. See issue #2000.
1 parent 4081deb commit 2d4c5ce

File tree

7 files changed

+90
-33
lines changed

7 files changed

+90
-33
lines changed

src/Data.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include "Data.h"
22

3+
#include <QBuffer>
4+
#include <QImageReader>
35
#include <QTextCodec>
6+
47
#include <algorithm>
58

69
// Note that these aren't all possible BOMs. But they are probably the most common ones.
@@ -88,6 +91,19 @@ QByteArray removeBom(QByteArray& data)
8891
}
8992
}
9093

94+
QString isImageData(const QByteArray& data)
95+
{
96+
// Check if it's an image. First do a quick test by calling canRead() which only checks the first couple of bytes or so. Only if
97+
// that returned true, do a more sophisticated test of the data. This way we get both, good performance and proper data checking.
98+
QBuffer imageBuffer(const_cast<QByteArray*>(&data));
99+
QImageReader readerBuffer(&imageBuffer);
100+
QString imageFormat = readerBuffer.format();
101+
if(readerBuffer.canRead() && !readerBuffer.read().isNull())
102+
return imageFormat;
103+
else
104+
return QString();
105+
}
106+
91107
QStringList toStringList(const QList<QByteArray>& list) {
92108
QStringList strings;
93109
for (const QByteArray &item : list) {

src/Data.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ bool startsWithBom(const QByteArray& data);
2121
// with a BOM an empty byte array is returned and the original data is not modified.
2222
QByteArray removeBom(QByteArray& data);
2323

24+
// Check if a byte array contains an image. Returns the name of the image format for images or a null string for non-image data.
25+
QString isImageData(const QByteArray& data);
26+
2427
QStringList toStringList(const QList<QByteArray>& list);
2528

2629
QByteArray encodeString(const QByteArray& str, const QString& encoding);

src/EditDialog.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <QKeySequence>
1212
#include <QShortcut>
1313
#include <QImageReader>
14-
#include <QBuffer>
1514
#include <QModelIndex>
1615
#include <QtXml/QDomDocument>
1716
#include <QMessageBox>
@@ -856,12 +855,9 @@ int EditDialog::checkDataType(const QByteArray& bArrdata)
856855
return Null;
857856
}
858857

859-
// Check if it's an image. First do a quick test by calling canRead() which only checks the first couple of bytes or so. Only if
860-
// that returned true, do a more sophisticated test of the data. This way we get both, good performance and proper data checking.
861-
QBuffer imageBuffer(&cellData);
862-
QImageReader readerBuffer(&imageBuffer);
863-
QString imageFormat = readerBuffer.format();
864-
if(readerBuffer.canRead() && !readerBuffer.read().isNull())
858+
// Check if it's an image
859+
QString imageFormat = isImageData(cellData);
860+
if(!imageFormat.isNull())
865861
return imageFormat == "svg" ? SVG : Image;
866862

867863
// Check if it's text only

src/PreferencesDialog.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ void PreferencesDialog::loadSettings()
109109

110110
ui->spinSymbolLimit->setValue(Settings::getValue("databrowser", "symbol_limit").toInt());
111111
ui->spinCompleteThreshold->setValue(Settings::getValue("databrowser", "complete_threshold").toInt());
112+
ui->checkShowImagesInline->setChecked(Settings::getValue("databrowser", "image_preview").toBool());
112113
ui->txtNull->setText(Settings::getValue("databrowser", "null_text").toString());
113114
ui->txtBlob->setText(Settings::getValue("databrowser", "blob_text").toString());
114115
ui->editFilterEscape->setText(Settings::getValue("databrowser", "filter_escape").toString());
@@ -217,6 +218,7 @@ void PreferencesDialog::saveSettings()
217218

218219
Settings::setValue("databrowser", "font", ui->comboDataBrowserFont->currentText());
219220
Settings::setValue("databrowser", "fontsize", ui->spinDataBrowserFontSize->value());
221+
Settings::setValue("databrowser", "image_preview", ui->checkShowImagesInline->isChecked());
220222
saveColorSetting(ui->fr_null_fg, "null_fg");
221223
saveColorSetting(ui->fr_null_bg, "null_bg");
222224
saveColorSetting(ui->fr_reg_fg, "reg_fg");

src/PreferencesDialog.ui

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,23 @@ Can be set to 0 for disabling completion.</string>
821821
</property>
822822
</widget>
823823
</item>
824+
<item row="2" column="0">
825+
<widget class="QLabel" name="label_22">
826+
<property name="text">
827+
<string>Show images in cell</string>
828+
</property>
829+
<property name="buddy">
830+
<cstring>checkShowImagesInline</cstring>
831+
</property>
832+
</widget>
833+
</item>
834+
<item row="2" column="1">
835+
<widget class="QCheckBox" name="checkShowImagesInline">
836+
<property name="toolTip">
837+
<string>Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however.</string>
838+
</property>
839+
</widget>
840+
</item>
824841
</layout>
825842
</widget>
826843
</item>
@@ -1866,17 +1883,20 @@ Can be set to 0 for disabling completion.</string>
18661883
</customwidget>
18671884
</customwidgets>
18681885
<tabstops>
1886+
<tabstop>tabWidget</tabstop>
18691887
<tabstop>comboDefaultLocation</tabstop>
18701888
<tabstop>locationEdit</tabstop>
18711889
<tabstop>setLocationButton</tabstop>
18721890
<tabstop>languageComboBox</tabstop>
1891+
<tabstop>appStyleCombo</tabstop>
18731892
<tabstop>toolbarStyleComboMain</tabstop>
18741893
<tabstop>toolbarStyleComboStructure</tabstop>
18751894
<tabstop>toolbarStyleComboBrowse</tabstop>
18761895
<tabstop>toolbarStyleComboSql</tabstop>
18771896
<tabstop>toolbarStyleComboEditCell</tabstop>
18781897
<tabstop>checkUseRemotes</tabstop>
18791898
<tabstop>checkUpdates</tabstop>
1899+
<tabstop>buttonManageFileExtension</tabstop>
18801900
<tabstop>encodingComboBox</tabstop>
18811901
<tabstop>foreignKeysCheckBox</tabstop>
18821902
<tabstop>checkHideSchemaLinebreaks</tabstop>
@@ -1886,6 +1906,9 @@ Can be set to 0 for disabling completion.</string>
18861906
<tabstop>editDatabaseDefaultSqlText</tabstop>
18871907
<tabstop>comboDataBrowserFont</tabstop>
18881908
<tabstop>spinDataBrowserFontSize</tabstop>
1909+
<tabstop>spinSymbolLimit</tabstop>
1910+
<tabstop>spinCompleteThreshold</tabstop>
1911+
<tabstop>checkShowImagesInline</tabstop>
18891912
<tabstop>fr_null_fg</tabstop>
18901913
<tabstop>fr_null_bg</tabstop>
18911914
<tabstop>txtNull</tabstop>
@@ -1902,20 +1925,25 @@ Can be set to 0 for disabling completion.</string>
19021925
<tabstop>spinEditorFontSize</tabstop>
19031926
<tabstop>spinLogFontSize</tabstop>
19041927
<tabstop>spinTabSize</tabstop>
1928+
<tabstop>wrapComboBox</tabstop>
1929+
<tabstop>quoteComboBox</tabstop>
19051930
<tabstop>checkAutoCompletion</tabstop>
1931+
<tabstop>checkCompleteUpper</tabstop>
19061932
<tabstop>checkErrorIndicators</tabstop>
19071933
<tabstop>checkHorizontalTiling</tabstop>
19081934
<tabstop>listExtensions</tabstop>
19091935
<tabstop>buttonAddExtension</tabstop>
19101936
<tabstop>buttonRemoveExtension</tabstop>
19111937
<tabstop>checkRegexDisabled</tabstop>
1912-
<tabstop>editRemoteCloneDirectory</tabstop>
1913-
<tabstop>buttonRemoteBrowseCloneDirectory</tabstop>
1914-
<tabstop>tableCaCerts</tabstop>
1938+
<tabstop>checkAllowLoadExtension</tabstop>
1939+
<tabstop>tabCertificates</tabstop>
19151940
<tabstop>tableClientCerts</tabstop>
19161941
<tabstop>buttonClientCertAdd</tabstop>
19171942
<tabstop>buttonClientCertRemove</tabstop>
1918-
<tabstop>tabWidget</tabstop>
1943+
<tabstop>buttonProxy</tabstop>
1944+
<tabstop>editRemoteCloneDirectory</tabstop>
1945+
<tabstop>buttonRemoteBrowseCloneDirectory</tabstop>
1946+
<tabstop>tableCaCerts</tabstop>
19191947
</tabstops>
19201948
<resources>
19211949
<include location="icons/icons.qrc"/>
@@ -1992,12 +2020,12 @@ Can be set to 0 for disabling completion.</string>
19922020
<slot>setVisible(bool)</slot>
19932021
<hints>
19942022
<hint type="sourcelabel">
1995-
<x>365</x>
1996-
<y>207</y>
2023+
<x>344</x>
2024+
<y>230</y>
19972025
</hint>
19982026
<hint type="destinationlabel">
1999-
<x>108</x>
2000-
<y>280</y>
2027+
<x>119</x>
2028+
<y>273</y>
20012029
</hint>
20022030
</hints>
20032031
</connection>
@@ -2008,8 +2036,8 @@ Can be set to 0 for disabling completion.</string>
20082036
<slot>setVisible(bool)</slot>
20092037
<hints>
20102038
<hint type="sourcelabel">
2011-
<x>365</x>
2012-
<y>207</y>
2039+
<x>344</x>
2040+
<y>230</y>
20132041
</hint>
20142042
<hint type="destinationlabel">
20152043
<x>365</x>
@@ -2024,8 +2052,8 @@ Can be set to 0 for disabling completion.</string>
20242052
<slot>activateRemoteTab(bool)</slot>
20252053
<hints>
20262054
<hint type="sourcelabel">
2027-
<x>161</x>
2028-
<y>172</y>
2055+
<x>231</x>
2056+
<y>393</y>
20292057
</hint>
20302058
<hint type="destinationlabel">
20312059
<x>382</x>
@@ -2040,8 +2068,8 @@ Can be set to 0 for disabling completion.</string>
20402068
<slot>addClientCertificate()</slot>
20412069
<hints>
20422070
<hint type="sourcelabel">
2043-
<x>578</x>
2044-
<y>315</y>
2071+
<x>722</x>
2072+
<y>110</y>
20452073
</hint>
20462074
<hint type="destinationlabel">
20472075
<x>596</x>
@@ -2056,8 +2084,8 @@ Can be set to 0 for disabling completion.</string>
20562084
<slot>removeClientCertificate()</slot>
20572085
<hints>
20582086
<hint type="sourcelabel">
2059-
<x>578</x>
2060-
<y>353</y>
2087+
<x>722</x>
2088+
<y>139</y>
20612089
</hint>
20622090
<hint type="destinationlabel">
20632091
<x>597</x>
@@ -2072,8 +2100,8 @@ Can be set to 0 for disabling completion.</string>
20722100
<slot>chooseRemoteCloneDirectory()</slot>
20732101
<hints>
20742102
<hint type="sourcelabel">
2075-
<x>567</x>
2076-
<y>54</y>
2103+
<x>732</x>
2104+
<y>538</y>
20772105
</hint>
20782106
<hint type="destinationlabel">
20792107
<x>595</x>
@@ -2088,12 +2116,12 @@ Can be set to 0 for disabling completion.</string>
20882116
<slot>setEnabled(bool)</slot>
20892117
<hints>
20902118
<hint type="sourcelabel">
2091-
<x>474</x>
2092-
<y>464</y>
2119+
<x>642</x>
2120+
<y>450</y>
20932121
</hint>
20942122
<hint type="destinationlabel">
2095-
<x>474</x>
2096-
<y>492</y>
2123+
<x>642</x>
2124+
<y>480</y>
20972125
</hint>
20982126
</hints>
20992127
</connection>
@@ -2104,8 +2132,8 @@ Can be set to 0 for disabling completion.</string>
21042132
<slot>on_buttonBox_clicked(QAbstractButton*)</slot>
21052133
<hints>
21062134
<hint type="sourcelabel">
2107-
<x>385</x>
2108-
<y>591</y>
2135+
<x>394</x>
2136+
<y>584</y>
21092137
</hint>
21102138
<hint type="destinationlabel">
21112139
<x>385</x>
@@ -2120,8 +2148,8 @@ Can be set to 0 for disabling completion.</string>
21202148
<slot>configureProxy()</slot>
21212149
<hints>
21222150
<hint type="sourcelabel">
2123-
<x>385</x>
2124-
<y>591</y>
2151+
<x>225</x>
2152+
<y>506</y>
21252153
</hint>
21262154
<hint type="destinationlabel">
21272155
<x>385</x>

src/Settings.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ QVariant Settings::getDefaultValue(const std::string& group, const std::string&
208208
return 5000;
209209
if(name == "complete_threshold")
210210
return 1000;
211+
if(name == "image_preview")
212+
return false;
211213
if(name == "indent_compact")
212214
return false;
213215
if(name == "auto_switch_mode")

src/sqlitetablemodel.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,16 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
390390
.arg(QKeySequence(Qt::CTRL).toString(QKeySequence::NativeText));
391391
else
392392
return QString();
393+
} else if(role == Qt::DecorationRole) {
394+
if(!row_available)
395+
return QVariant();
396+
397+
if(Settings::getValue("databrowser", "image_preview").toBool() && !isImageData(cached_row->at(column)).isNull())
398+
{
399+
QImage img;
400+
img.loadFromData(cached_row->at(column));
401+
return QPixmap::fromImage(img);
402+
}
393403
}
394404

395405
return QVariant();

0 commit comments

Comments
 (0)