diff --git a/docs/smart-device-bom.md b/docs/smart-device-bom.md
index d62823919..4252332c5 100644
--- a/docs/smart-device-bom.md
+++ b/docs/smart-device-bom.md
@@ -42,10 +42,18 @@ unit conventions and decimal quantities are not changed implicitly.
## BOM Policy
-The default BOM query exports one row per Simple or Master element. Slave
-contacts, terminal-strip elements, reports, thumbnails, and conductor
-definitions are excluded. A Master device is counted once and PLC I/O entries
-are not expanded. The existing `exclude_from_bom` property is honored by the
+The default BOM query exports one row per Simple, Master, Slave or Terminal
+element: an auxiliary contact block and a terminal block are parts of their
+own (discussion #847). Reports, thumbnails and conductor definitions are
+excluded. A Master device is counted once and PLC I/O entries are not
+expanded.
+
+Two options leave rows out (#1178). Contact blocks: uncheck **Contacts
+esclaves** in the dialog, or pass `--no-slaves`. Junctions, the
+terminal-type symbols drawn where wires branch (`114_connections`), which
+have no label, designation, manufacturer or manufacturer reference: check
+**Laisser de côté les jonctions**, or pass `--no-junctions`. A terminal block
+with a label or a part number is kept. The existing `exclude_from_bom` property is honored by the
SQL view, including common true representations (`true`, `1`, `yes`, `on`).
The default columns are:
diff --git a/misc/qet-mcp/README.md b/misc/qet-mcp/README.md
index 616ad5234..60e66ae23 100644
--- a/misc/qet-mcp/README.md
+++ b/misc/qet-mcp/README.md
@@ -678,6 +678,12 @@ Python, plus the hang guard on `addConductor` and the database refresh in
`source_date_epoch` if given, else the server's own `SOURCE_DATE_EPOCH`,
else 0 (1 January 1970). The result's `"reproducible"` is false, with a
hint, when the QElectroTech build is too old to honour it.
+- **`"no_slaves"` and `"no_junctions"` shorten a `bom` export.** The first
+ leaves out the contact blocks, which otherwise get a row of their own; the
+ second leaves out terminal-type elements with no label, designation,
+ manufacturer or manufacturer reference, such as the junction dots of
+ `114_connections`. They pass `--no-slaves` and `--no-junctions`; an older
+ QElectroTech ignores both and exports every row, so check the row count.
- **`qet_export` isolates its launch.** SingleApplication keys its socket
on `applicationFilePath()`, so a second launch of the same binary path
forwards its request to an already-running instance and returns *that*
diff --git a/misc/qet-mcp/qet_mcp.py b/misc/qet-mcp/qet_mcp.py
index 29c3ca812..a0ce6e98e 100755
--- a/misc/qet-mcp/qet_mcp.py
+++ b/misc/qet-mcp/qet_mcp.py
@@ -1059,10 +1059,13 @@ def _source_date_epoch(value) -> int:
def tool_export(binary: str, project: str, format: str, output: str,
timeout: int = 180, reproducible: bool = False,
- source_date_epoch: int | None = None) -> dict:
+ source_date_epoch: int | None = None,
+ no_slaves: bool = False, no_junctions: bool = False) -> dict:
if format not in EXPORT_FORMATS:
raise ValueError(f"unknown format {format!r}; "
f"expected one of {', '.join(sorted(EXPORT_FORMATS))}")
+ if (no_slaves or no_junctions) and format != "bom":
+ raise ValueError("no_slaves and no_junctions only apply to format \"bom\"")
proj = Path(project).expanduser()
if not proj.is_file():
raise ValueError(f"no such project: {proj}")
@@ -1080,8 +1083,12 @@ def tool_export(binary: str, project: str, format: str, output: str,
if reproducible or source_date_epoch is not None:
epoch = _source_date_epoch(source_date_epoch)
extra_env = {"SOURCE_DATE_EPOCH": str(epoch)}
- result = _run_qet(binary, [flag, str(proj), output], timeout,
- extra_env=extra_env)
+ args = [flag, str(proj), output]
+ if no_slaves:
+ args.append("--no-slaves")
+ if no_junctions:
+ args.append("--no-junctions")
+ result = _run_qet(binary, args, timeout, extra_env=extra_env)
out = Path(output).expanduser()
result["output"] = str(out)
result["output_exists"] = out.exists()
@@ -4783,13 +4790,24 @@ TOOLS = [
"carries, in seconds since 1970 UTC. "
"Default: this server's own "
"SOURCE_DATE_EPOCH, else 0"},
+ "no_slaves": {"type": "boolean", "default": False,
+ "description": "bom: leave out the contact blocks (slave "
+ "elements), which otherwise get a row of "
+ "their own with their master's label"},
+ "no_junctions": {"type": "boolean", "default": False,
+ "description": "bom: leave out the junctions: "
+ "terminal-type elements with no label, "
+ "designation, manufacturer or "
+ "manufacturer reference"},
},
"required": ["project", "format", "output"],
},
"handler": lambda a: tool_export(a["binary"], a["project"], a["format"],
a["output"], a.get("timeout", 180),
a.get("reproducible", False),
- a.get("source_date_epoch")),
+ a.get("source_date_epoch"),
+ a.get("no_slaves", False),
+ a.get("no_junctions", False)),
},
{
"name": "qet_edit",
diff --git a/misc/qet-mcp/test_qet_mcp.py b/misc/qet-mcp/test_qet_mcp.py
index 9cd59ab32..9848f0710 100644
--- a/misc/qet-mcp/test_qet_mcp.py
+++ b/misc/qet-mcp/test_qet_mcp.py
@@ -4025,6 +4025,36 @@ class ProjectNewValidation(unittest.TestCase):
self.assertFalse(Path(new).exists())
+class BomExportOptions(unittest.TestCase):
+ """qet_export's no_slaves and no_junctions become --export-bom flags (#1178)."""
+
+ def run_export(self, format="bom", **kw):
+ seen = []
+ def fake(binary, args, timeout=180, **rest):
+ seen.extend(args)
+ return {"ok": True}
+ with tempfile.TemporaryDirectory() as tmp:
+ proj = Path(tmp) / "a.qet"
+ proj.write_text("")
+ with unittest.mock.patch.object(m, "_run_qet", fake):
+ m.tool_export("qet", str(proj), format, str(Path(tmp) / "o.csv"), **kw)
+ return seen
+
+ def test_off_by_default(self):
+ args = self.run_export()
+ self.assertNotIn("--no-slaves", args)
+ self.assertNotIn("--no-junctions", args)
+
+ def test_flags_after_the_output(self):
+ args = self.run_export(no_slaves=True, no_junctions=True)
+ self.assertEqual(args[0], "--export-bom")
+ self.assertEqual(args[3:], ["--no-slaves", "--no-junctions"])
+
+ def test_refused_for_other_formats(self):
+ with self.assertRaises(ValueError):
+ self.run_export(format="wiring", no_junctions=True)
+
+
class ReproducibleExport(unittest.TestCase):
"""qet_export's "reproducible" sets SOURCE_DATE_EPOCH for the run."""
diff --git a/sources/bomexport.cpp b/sources/bomexport.cpp
index a84bb51b2..97ecdff61 100644
--- a/sources/bomexport.cpp
+++ b/sources/bomexport.cpp
@@ -57,7 +57,32 @@ QStringList BomExport::defaultColumns()
};
}
-QString BomExport::defaultQuery()
+/**
+ @brief BomExport::junctionFilter
+ @return a condition true for every row that is not a junction: a
+ terminal-type element with no label and no part data. Some users draw
+ the dots and bends where wires branch as their own terminal-type
+ symbols, and each one became an empty row of the parts list (#1178).
+ A terminal block with a label or a part number is kept.
+*/
+QString BomExport::junctionFilter()
+{
+ return QStringLiteral("NOT (element_type = 'terminal' "
+ "AND IFNULL(label, '') = '' "
+ "AND IFNULL(designation, '') = '' "
+ "AND IFNULL(manufacturer, '') = '' "
+ "AND IFNULL(manufacturer_reference, '') = '')");
+}
+
+/**
+ @brief BomExport::defaultQuery
+ @param include_slaves : false leaves out the contact blocks (slave
+ elements), which otherwise appear as rows of their own
+ @param include_junctions : false leaves out the junctions, see
+ junctionFilter()
+ @return the query of the parts list
+*/
+QString BomExport::defaultQuery(bool include_slaves, bool include_junctions)
{
//Slaves and terminals are included because both are routinely
//separately orderable hardware. A circuit breaker can carry ten or
@@ -77,11 +102,16 @@ QString BomExport::defaultQuery()
//and the conductor definition stay out because they are not hardware.
//
//See discussion #847.
+ const QString types = include_slaves
+ ? QStringLiteral("'simple', 'master', 'slave', 'terminal'")
+ : QStringLiteral("'simple', 'master', 'terminal'");
+ const QString junctions = include_junctions
+ ? QString()
+ : QStringLiteral(" AND ") + junctionFilter();
return QStringLiteral("SELECT %1 FROM element_nomenclature_view "
- "WHERE element_type IN "
- "('simple', 'master', 'slave', 'terminal') "
+ "WHERE element_type IN (%2)%3 "
"ORDER BY diagram_position, position, label")
- .arg(defaultColumns().join(QStringLiteral(", ")));
+ .arg(defaultColumns().join(QStringLiteral(", ")), types, junctions);
}
QByteArray BomExport::toCsv(QSqlQuery &query, const QStringList &headers,
diff --git a/sources/bomexport.h b/sources/bomexport.h
index 0241165a0..5305d378e 100644
--- a/sources/bomexport.h
+++ b/sources/bomexport.h
@@ -27,7 +27,9 @@ class QSqlQuery;
namespace BomExport
{
QStringList defaultColumns();
- QString defaultQuery();
+ QString defaultQuery(bool include_slaves = true,
+ bool include_junctions = true);
+ QString junctionFilter();
QByteArray toCsv(QSqlQuery &query, const QStringList &headers,
bool include_headers = true, int *row_count = nullptr);
bool writeCsv(const QString &file_path, const QByteArray &csv,
diff --git a/sources/cli_export.cpp b/sources/cli_export.cpp
index b6e20557a..6dc295196 100644
--- a/sources/cli_export.cpp
+++ b/sources/cli_export.cpp
@@ -408,10 +408,12 @@ int exportCsv(QETProject &project, const QString &format, const QString &output)
/// Bill of materials from the same project database and default query as the
/// GUI nomenclature export.
-int exportBom(QETProject &project, const QString &output)
+int exportBom(QETProject &project, const QString &output,
+ bool includeSlaves, bool includeJunctions)
{
project.dataBase()->updateDB();
- QSqlQuery query = project.dataBase()->newQuery(BomExport::defaultQuery());
+ QSqlQuery query = project.dataBase()->newQuery(
+ BomExport::defaultQuery(includeSlaves, includeJunctions));
if (!query.exec()) {
err << "BOM query failed: " << query.lastError().text() << "\n";
return 1;
@@ -980,6 +982,9 @@ int run(const QStringList &args)
// collected below.
QStringList filtered = args;
const bool showTerminals = filtered.removeAll("--show-terminals") > 0;
+ // --no-slaves and --no-junctions leave rows out of --export-bom.
+ const bool includeSlaves = filtered.removeAll("--no-slaves") == 0;
+ const bool includeJunctions = filtered.removeAll("--no-junctions") == 0;
QString flag;
QStringList rest;
@@ -1037,7 +1042,7 @@ int run(const QStringList &args)
if (format == "cables" || format == "wires")
return exportCsv(project, format, output);
if (format == "bom")
- return exportBom(project, output);
+ return exportBom(project, output, includeSlaves, includeJunctions);
if (format == "wiring")
return exportWiring(project, output);
if (format == "nets")
diff --git a/sources/cli_export.h b/sources/cli_export.h
index 8ad1b1d12..e9323a035 100644
--- a/sources/cli_export.h
+++ b/sources/cli_export.h
@@ -48,7 +48,7 @@ namespace CLIExport {
qelectrotech --export-dxf [--show-terminals]
qelectrotech --export-cables
qelectrotech --export-wires
- qelectrotech --export-bom
+ qelectrotech --export-bom [--no-slaves] [--no-junctions]
qelectrotech --export-wiring
qelectrotech --export-nets
qelectrotech --export-links
@@ -69,6 +69,11 @@ namespace CLIExport {
cables: wiring list (one row per conductor) as CSV.
wires: list of distinct wire numbers as CSV.
bom: bill of materials (one row per element) as CSV.
+ --no-slaves: leave the contact blocks (slave elements) out of the
+ bill of materials.
+ --no-junctions: leave the junctions out of the bill of materials:
+ terminal-type elements with no label, designation,
+ manufacturer or manufacturer reference.
wiring: from-to wiring list (one row per conductor) as CSV, read from
the project database. Same logical list as `cables`, which
reads the document XML instead; the two are meant to agree,
diff --git a/sources/dataBase/ui/elementquerywidget.cpp b/sources/dataBase/ui/elementquerywidget.cpp
index 6331efb63..9afb47a51 100644
--- a/sources/dataBase/ui/elementquerywidget.cpp
+++ b/sources/dataBase/ui/elementquerywidget.cpp
@@ -56,6 +56,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
m_button_group.addButton(ui->m_protection_cb, 5);
m_button_group.addButton(ui->m_thumbnail_cb, 6);
m_button_group.addButton(ui->m_plc_cb, 7);
+ m_button_group.addButton(ui->m_slave_cb, 8);
connect(&m_button_group, static_cast(&QButtonGroup::idClicked), [this](int id)
{
@@ -78,27 +79,12 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
}
else
{
- int checked = 0;
- for (int i=1 ; i<8 ; ++i) {
- if (m_button_group.button(i)->isChecked()) {++checked;}
- }
-
- switch (checked)
- {
- case 0 :
- check_box->setCheckState(Qt::Unchecked);
- break;
- case 7:
- check_box->setCheckState(Qt::Checked);
- break;
- default:
- check_box->setCheckState(Qt::PartiallyChecked);
- break;
- }
+ updateAllCheckState();
}
updateQueryLine();
});
+ updateAllCheckState();
setUpItems();
fillSavedQuery();
@@ -203,8 +189,12 @@ void ElementQueryWidget::setQuery(const QString &query)
if (ui->m_plc_cb->isChecked()) {
++c;
}
+ ui->m_slave_cb->setChecked (str_type.contains(ElementData::typeToString(ElementData::Slave)));
+ if (ui->m_slave_cb->isChecked()) {
+ ++c;
+ }
- if (c == 7) {
+ if (c == 8) {
ui->m_all_cb->setCheckState(Qt::Checked);
} else if (c > 0) {
ui->m_all_cb->setCheckState(Qt::PartiallyChecked);
@@ -395,6 +385,11 @@ QString ElementQueryWidget::queryStr() const
where += QStringLiteral(" element_sub_type = '") += ElementData::masterTypeToString(ElementData::PLC) += "'";
b = true;
}
+ if (ui->m_slave_cb->isChecked()) {
+ if (b) where +=" OR";
+ where += QStringLiteral(" element_type = '") += ElementData::typeToString(ElementData::Slave) += "'";
+ b = true;
+ }
where.append(")");
if (where == " WHERE ()") {
@@ -406,6 +401,10 @@ QString ElementQueryWidget::queryStr() const
// widget's query reads FROM that view, so a flagged element never
// reaches this point in the first place.
+ if (!m_extra_filter.isEmpty()) {
+ filter_ += QStringLiteral(" AND ") + m_extra_filter;
+ }
+
if (where.isEmpty() && !filter_.isEmpty()) {
filter_.remove(0, 4); //Remove the first " AND" of filter.
filter_.prepend( " WHERE");
@@ -456,6 +455,64 @@ void ElementQueryWidget::setCount(QString text, bool set)
updateQueryLine();
}
+/**
+ @brief ElementQueryWidget::setSlavesIncluded
+ Check or uncheck the contact blocks (slave elements) in the element
+ type filter. The box is unchecked by default, which keeps the tables
+ made before it existed as they were.
+ @param included
+*/
+void ElementQueryWidget::setSlavesIncluded(bool included)
+{
+ ui->m_slave_cb->setChecked(included);
+ updateAllCheckState();
+ updateQueryLine();
+}
+
+/**
+ @brief ElementQueryWidget::updateAllCheckState
+ Set the "all" check box from the element type check boxes.
+*/
+void ElementQueryWidget::updateAllCheckState()
+{
+ int checked = 0;
+ for (int i=1 ; i<9 ; ++i) {
+ if (m_button_group.button(i)->isChecked()) {++checked;}
+ }
+
+ switch (checked)
+ {
+ case 0 :
+ ui->m_all_cb->setCheckState(Qt::Unchecked);
+ break;
+ case 8:
+ ui->m_all_cb->setCheckState(Qt::Checked);
+ break;
+ default:
+ ui->m_all_cb->setCheckState(Qt::PartiallyChecked);
+ break;
+ }
+}
+
+/**
+ @brief ElementQueryWidget::setExtraFilter
+ Add a condition every row of the query must meet, on top of the filters
+ chosen in this widget.
+ @param text : the condition, ex : "label != ''"
+ @param set :
+ true by default -> the condition is used.
+ false -> the condition is removed.
+*/
+void ElementQueryWidget::setExtraFilter(const QString &text, bool set)
+{
+ if (set) {
+ m_extra_filter = text;
+ } else {
+ m_extra_filter.clear();
+ }
+ updateQueryLine();
+}
+
/**
@brief ElementQueryWidget::updateQueryLine
*/
diff --git a/sources/dataBase/ui/elementquerywidget.h b/sources/dataBase/ui/elementquerywidget.h
index f89883793..99cdf034d 100644
--- a/sources/dataBase/ui/elementquerywidget.h
+++ b/sources/dataBase/ui/elementquerywidget.h
@@ -45,6 +45,8 @@ class ElementQueryWidget : public QWidget
QString queryStr() const;
void setGroupBy(QString text, bool set = true);
void setCount(QString text, bool set = true);
+ void setSlavesIncluded(bool included);
+ void setExtraFilter(const QString &text, bool set = true);
static QString modelIdentifier() {return "nomenclature";}
@@ -67,6 +69,7 @@ class ElementQueryWidget : public QWidget
void on_m_choosen_list_itemDoubleClicked(QListWidgetItem *item);
void updateQueryLine();
+ void updateAllCheckState();
QStringList selectedKeys() const;
void setUpItems();
QPair FilterFor(const QString &key) const;
@@ -82,7 +85,8 @@ class ElementQueryWidget : public QWidget
QList m_items_list;
QString m_custom_query,
m_group_by,
- m_count;
+ m_count,
+ m_extra_filter;
QHash > m_filter;
};
diff --git a/sources/dataBase/ui/elementquerywidget.ui b/sources/dataBase/ui/elementquerywidget.ui
index 2464c6c81..5e01e2c5b 100644
--- a/sources/dataBase/ui/elementquerywidget.ui
+++ b/sources/dataBase/ui/elementquerywidget.ui
@@ -318,6 +318,16 @@
+ -
+
+
+ Contacts esclaves
+
+
+ false
+
+
+
diff --git a/sources/scripting/qetscriptapi.cpp b/sources/scripting/qetscriptapi.cpp
index 78c0833d1..0faeab5ae 100644
--- a/sources/scripting/qetscriptapi.cpp
+++ b/sources/scripting/qetscriptapi.cpp
@@ -323,9 +323,13 @@ bool QetScriptApi::exportWires(const QString &output)
return runFlag(QStringLiteral("--export-wires"), {output});
}
-bool QetScriptApi::exportBom(const QString &output)
+bool QetScriptApi::exportBom(const QString &output, bool noSlaves,
+ bool noJunctions)
{
- return runFlag(QStringLiteral("--export-bom"), {output});
+ QStringList args{output};
+ if (noSlaves) args << QStringLiteral("--no-slaves");
+ if (noJunctions) args << QStringLiteral("--no-junctions");
+ return runFlag(QStringLiteral("--export-bom"), args);
}
bool QetScriptApi::exportWiring(const QString &output)
diff --git a/sources/scripting/qetscriptapi.h b/sources/scripting/qetscriptapi.h
index 6b9e6bb9b..918c08408 100644
--- a/sources/scripting/qetscriptapi.h
+++ b/sources/scripting/qetscriptapi.h
@@ -384,7 +384,8 @@ class QetScriptApi : public QObject
Q_INVOKABLE bool exportDxf(const QString &outDir, bool showTerminals = false);
Q_INVOKABLE bool exportCables(const QString &output);
Q_INVOKABLE bool exportWires(const QString &output);
- Q_INVOKABLE bool exportBom(const QString &output);
+ Q_INVOKABLE bool exportBom(const QString &output, bool noSlaves = false,
+ bool noJunctions = false);
Q_INVOKABLE bool exportWiring(const QString &output);
Q_INVOKABLE bool exportNets(const QString &output);
Q_INVOKABLE bool exportLinks(const QString &output);
diff --git a/sources/ui/bomexportdialog.cpp b/sources/ui/bomexportdialog.cpp
index 703b9e3c6..af884cfc8 100644
--- a/sources/ui/bomexportdialog.cpp
+++ b/sources/ui/bomexportdialog.cpp
@@ -46,6 +46,9 @@ BOMExportDialog::BOMExportDialog(QETProject *project, QWidget *parent) :
m_query_widget = new ElementQueryWidget(this);
ui->m_main_layout->insertWidget(0, m_query_widget);
m_query_widget->setQuery(BomExport::defaultQuery());
+ //The contact blocks are parts of their own, as in the command line
+ //export; unchecking "Contacts esclaves" leaves them out.
+ m_query_widget->setSlavesIncluded(true);
on_m_format_as_bom_clicked(false);
m_preview_model = new QSqlQueryModel(this);
@@ -145,6 +148,15 @@ void BOMExportDialog::on_m_format_as_bom_clicked(bool checked) {
m_query_widget->setCount("COUNT(*) AS designation_qty", checked);
}
+/**
+ @brief BOMExportDialog::on_m_no_junctions_clicked
+ @param checked : true leaves out the junctions, see
+ BomExport::junctionFilter()
+*/
+void BOMExportDialog::on_m_no_junctions_clicked(bool checked) {
+ m_query_widget->setExtraFilter(BomExport::junctionFilter(), checked);
+}
+
/**
@brief BOMExportDialog::on_m_preview_pb_clicked
Run the current query and show its result live, without going through
diff --git a/sources/ui/bomexportdialog.h b/sources/ui/bomexportdialog.h
index 0c5a0743e..924b3fc8a 100644
--- a/sources/ui/bomexportdialog.h
+++ b/sources/ui/bomexportdialog.h
@@ -45,6 +45,7 @@ class BOMExportDialog : public QDialog
private slots:
void on_m_format_as_bom_clicked(bool checked);
+ void on_m_no_junctions_clicked(bool checked);
void on_m_preview_pb_clicked();
private:
diff --git a/sources/ui/bomexportdialog.ui b/sources/ui/bomexportdialog.ui
index 04b673f46..4a3ffa8f4 100644
--- a/sources/ui/bomexportdialog.ui
+++ b/sources/ui/bomexportdialog.ui
@@ -40,6 +40,19 @@
+ -
+
+
+ Bornes sans repère, désignation, fabricant ni référence fabricant
+
+
+ Laisser de côté les jonctions
+
+
+ false
+
+
+
-
diff --git a/tests/qttest/tst_smart_device.cpp b/tests/qttest/tst_smart_device.cpp
index ced7ecbdc..e36571026 100644
--- a/tests/qttest/tst_smart_device.cpp
+++ b/tests/qttest/tst_smart_device.cpp
@@ -120,6 +120,34 @@ void SmartDeviceTest::defaultQueryAndCsv()
QVERIFY(csv.contains("Terminal block"));
QVERIFY(!csv.contains("Must not be exported"));
QVERIFY(csv.indexOf("-K1") < csv.indexOf("-K2"));
+
+ //#1178: a junction -- a terminal-type symbol drawn where wires
+ //branch -- has no label and no part data. It can be left out, and
+ //so can the contact blocks; a terminal block with only a part
+ //number stays.
+ QSqlQuery raw(db);
+ QVERIFY(raw.exec(QStringLiteral(
+ "INSERT INTO element_nomenclature_view "
+ "(label, element_type, diagram_position, position) "
+ "VALUES (NULL, 'terminal', 1, 6)")));
+ QVERIFY(raw.exec(QStringLiteral(
+ "INSERT INTO element_nomenclature_view "
+ "(label, designation, manufacturer, manufacturer_reference, "
+ "element_type, diagram_position, position) "
+ "VALUES ('', '', '', 'PT 2,5', 'terminal', 1, 7)")));
+ auto count = [&db](const QString &sql) {
+ QSqlQuery q(db);
+ if (!q.exec(sql))
+ return -1;
+ int n = 0;
+ while (q.next())
+ ++n;
+ return n;
+ };
+ QCOMPARE(count(BomExport::defaultQuery()), 6);
+ QCOMPARE(count(BomExport::defaultQuery(true, false)), 5);
+ QCOMPARE(count(BomExport::defaultQuery(false, true)), 5);
+ QCOMPARE(count(BomExport::defaultQuery(false, false)), 4);
}
QSqlDatabase::removeDatabase(connection);
}