[consider merging] Reader format error with details showing dump or text

This commit is contained in:
Matthias Koefferlein 2022-08-16 21:56:07 +02:00
parent 49fe816294
commit 46364c2420
7 changed files with 508 additions and 2 deletions

View File

@ -91,7 +91,13 @@ Reader::Reader (tl::InputStream &stream)
}
if (! mp_actual_reader) {
throw db::ReaderException (tl::to_string (tr ("Stream has unknown format: ")) + stream.source ());
m_stream.reset ();
std::string head = m_stream.read_all (4000);
bool has_more (m_stream.get (1) != 0);
throw db::ReaderUnknownFormatException (tl::to_string (tr ("Stream has unknown format: ")) + stream.source (), head, has_more);
}
}

View File

@ -54,6 +54,35 @@ public:
{ }
};
/**
* @brief A class representing the "unknown format" reader error
*
* The purpose of this class is supply the header bytes of the
* data stream for analysis.
*/
class DB_PUBLIC ReaderUnknownFormatException
: public ReaderException
{
public:
ReaderUnknownFormatException (const std::string &msg, const std::string &data, bool has_more)
: ReaderException (msg), m_data (data), m_has_more (has_more)
{ }
const std::string &data () const
{
return m_data;
}
bool has_more () const
{
return m_has_more;
}
private:
std::string m_data;
bool m_has_more;
};
/**
* @brief Joins layer names into a single, combined layer
* @param s The first layer name and output

View File

@ -0,0 +1,278 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ReaderErrorForm</class>
<widget class="QDialog" name="ReaderErrorForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>496</width>
<height>297</height>
</rect>
</property>
<property name="windowTitle">
<string>Script Error</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="2" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>411</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>411</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="3">
<widget class="QLabel" name="msg_label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>71</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" rowspan="3">
<widget class="QLabel" name="icon_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>71</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="details_frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTextBrowser" name="details_text">
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Liberation Mono';&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="details_pb">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string> Details &gt;&gt; </string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>341</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="ok_button">
<property name="text">
<string>OK</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections>
<connection>
<sender>ok_button</sender>
<signal>clicked()</signal>
<receiver>ReaderErrorForm</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>457</x>
<y>330</y>
</hint>
<hint type="destinationlabel">
<x>271</x>
<y>177</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -31,6 +31,7 @@ HEADERS = \
layProgressWidget.h \
layResourceHelpProvider.h \
layRuntimeErrorForm.h \
layReaderErrorForm.h \
laySearchReplaceConfigPage.h \
laySearchReplaceDialog.h \
laySearchReplacePropertiesWidgets.h \
@ -87,6 +88,7 @@ FORMS = \
ReplacePropertiesShape.ui \
ReplacePropertiesText.ui \
RuntimeErrorForm.ui \
ReaderErrorForm.ui \
SearchPropertiesBox.ui \
SearchPropertiesInstance.ui \
SearchPropertiesPath.ui \
@ -139,6 +141,7 @@ SOURCES = \
layProgressWidget.cc \
layResourceHelpProvider.cc \
layRuntimeErrorForm.cc \
layReaderErrorForm.cc \
laySearchReplaceConfigPage.cc \
laySearchReplaceDialog.cc \
laySearchReplacePlugin.cc \

View File

@ -31,6 +31,7 @@
#include "layVersion.h"
#include "laySignalHandler.h"
#include "layRuntimeErrorForm.h"
#include "layReaderErrorForm.h"
#include "layProgress.h"
#include "layTextProgress.h"
#include "layBackgroundAwareTreeStyle.h"
@ -106,6 +107,7 @@ static void ui_exception_handler_tl (const tl::Exception &ex, QWidget *parent)
const tl::ExitException *gsi_exit = dynamic_cast <const tl::ExitException *> (&ex);
const tl::BreakException *gsi_break = dynamic_cast <const tl::BreakException *> (&ex);
const tl::ScriptError *gsi_excpt = dynamic_cast <const tl::ScriptError *> (&ex);
const db::ReaderUnknownFormatException *reader_excpt = dynamic_cast <const db::ReaderUnknownFormatException *> (&ex);
if (gsi_exit || gsi_break) {
// exit and break exceptions are not shown - they are issued when a script is aborted or
@ -131,11 +133,19 @@ static void ui_exception_handler_tl (const tl::Exception &ex, QWidget *parent)
error_dialog.exec ();
} else {
tl::error << ex.msg ();
if (! parent) {
parent = QApplication::activeWindow () ? QApplication::activeWindow () : lay::MainWindow::instance ();
}
QMessageBox::critical (parent, QObject::tr ("Error"), tl::to_qstring (ex.msg ()));
if (reader_excpt) {
lay::ReaderErrorForm error_dialog (parent, "reader_error_form", reader_excpt);
error_dialog.exec ();
} else {
QMessageBox::critical (parent, QObject::tr ("Error"), tl::to_qstring (ex.msg ()));
}
}
}

View File

@ -0,0 +1,123 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2022 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layReaderErrorForm.h"
#include "layQtTools.h"
#include "dbReader.h"
#include <QMessageBox>
namespace lay
{
// ------------------------------------------------------------
static bool is_text (const std::string &s)
{
for (std::string::const_iterator i = s.begin (); i != s.end (); ++i) {
unsigned char uc = (unsigned char) *i;
if (uc < 32 && uc != '\t' && uc != '\r' && uc != '\n') {
return false;
}
}
return true;
}
static std::string format_hex_dump (const std::string &s)
{
const int bytes_per_line = 16;
std::string hex_dump;
// Some rough estimate of the capacity
hex_dump.reserve ((s.size () / bytes_per_line + 1) * (8 + bytes_per_line * 4) + 100);
const char *ce = s.c_str () + s.size ();
for (const char *c = s.c_str (); c + bytes_per_line <= ce; c += bytes_per_line) {
hex_dump += tl::sprintf ("%04x ", c - s.c_str ());
for (int i = 0; i < bytes_per_line; ++i) {
hex_dump += tl::sprintf ("%02x ", (unsigned char) c [i]);
}
hex_dump += " ";
for (int i = 0; i < bytes_per_line; ++i) {
unsigned char uc = (unsigned char) c[i];
hex_dump += (uc < 32 || uc >= 128) ? '.' : c[i];
}
hex_dump += "\n";
}
return hex_dump;
}
ReaderErrorForm::ReaderErrorForm (QWidget *parent, const char *name, const db::ReaderUnknownFormatException *error)
: QDialog (parent), Ui::ReaderErrorForm ()
{
setObjectName (QString::fromUtf8 (name));
Ui::ReaderErrorForm::setupUi (this);
msg_label->setText (tl::to_qstring (error->basic_msg ()));
if (is_text (error->data ())) {
details_text->setText (tl::to_qstring (error->msg () + "\n\n" + error->data () + (error->has_more () ? "..." : "")));
} else {
details_text->setText (tl::to_qstring (error->msg () + "\n\n" + format_hex_dump (error->data ()) + (error->has_more () ? "..." : "")));
}
details_text->setFont (lay::monospace_font ());
details_frame->hide ();
// "borrow" the error pixmap from the message box
QMessageBox *mb = new QMessageBox (QMessageBox::Critical, QString (), QString ());
QPixmap error_icon = mb->iconPixmap ();
delete mb;
icon_label->setPixmap (error_icon);
connect (details_pb, SIGNAL (clicked ()), this, SLOT (show_details ()));
resize (size ().width (), 50);
}
void
ReaderErrorForm::show_details ()
{
QString t (details_pb->text ());
if (details_frame->isVisible ()) {
details_frame->hide ();
t.replace (QString::fromUtf8 ("<<"), QString::fromUtf8 (">>"));
// It looks like the minimum size is set to a too large value internally.
// Resetting it helps to keep a small-as-possible dialog size.
setMinimumSize (QSize (0, 0));
resize (size ().width (), 0);
} else {
details_frame->show ();
t.replace (QString::fromUtf8 (">>"), QString::fromUtf8 ("<<"));
resize (size ().width (), sizeHint ().height ());
}
details_pb->setText (t);
}
}

View File

@ -0,0 +1,57 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2022 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_rbaReaderErrorForm
#define HDR_rbaReaderErrorForm
#include <string>
#include <vector>
#include <QDialog>
#include "ui_ReaderErrorForm.h"
namespace db
{
class ReaderUnknownFormatException;
}
namespace lay
{
class ReaderErrorForm
: public QDialog, private Ui::ReaderErrorForm
{
Q_OBJECT
public:
ReaderErrorForm (QWidget *parent, const char *name, const db::ReaderUnknownFormatException *error);
public slots:
void show_details ();
};
}
#endif