[LyX/master] Fix (biblatex) file encoding handling in GuiBibtex (#13109)

Juergen Spitzmueller spitz at lyx.org
Tue Oct 8 12:05:47 UTC 2024


commit 83006fc0805ef8a4bc6713e7aa5d68b3cc6135ce
Author: Juergen Spitzmueller <spitz at lyx.org>
Date:   Tue Oct 8 14:04:34 2024 +0200

    Fix (biblatex) file encoding handling in GuiBibtex (#13109)
---
 src/frontends/qt/GuiBibtex.cpp | 163 +++++++++++++++++++++++++++++++++--------
 src/frontends/qt/GuiBibtex.h   |  13 +++-
 2 files changed, 143 insertions(+), 33 deletions(-)

diff --git a/src/frontends/qt/GuiBibtex.cpp b/src/frontends/qt/GuiBibtex.cpp
index e6eff146f5..eeb8910cdd 100644
--- a/src/frontends/qt/GuiBibtex.cpp
+++ b/src/frontends/qt/GuiBibtex.cpp
@@ -181,8 +181,31 @@ void GuiBibtex::setButtons()
 
 void GuiBibtex::selUpdated()
 {
+	vector<docstring> nfe;
+	if (usingBiblatex()) {
+		// check for current file encodings
+		for (int i = 0; i != selected_model_.rowCount(); ++i) {
+			QStandardItem const * key = selected_model_.item(i, 0);
+			QComboBox * cb = qobject_cast<QComboBox*>(selectedLV->indexWidget(selected_model_.index(i, 1)));
+			QString fenc = cb ? cb->itemData(cb->currentIndex()).toString() : QString();
+			if (fenc.isEmpty())
+				fenc = cached_file_encodings_[key->text()];
+			else
+				cached_file_encodings_[key->text()] = fenc;
+			docstring const enc = qstring_to_ucs4(key->text()) + " " + qstring_to_ucs4(fenc);
+			if (key && !key->text().isEmpty() && !fenc.isEmpty() && fenc != "general")
+				nfe.push_back(enc);
+		}
+	}
 	selectionManager->update();
 	editPB->setEnabled(deletePB->isEnabled());
+	if (usingBiblatex()) {
+		// Set file encodings as assembled above
+		for (int i = 0; i != selected_model_.rowCount(); ++i)
+			addEncCombo(i);
+		if (!nfe.empty())
+			setFileEncodings(nfe);
+	}
 	updateReAbs();
 	changed();
 }
@@ -282,7 +305,6 @@ void GuiBibtex::inheritPressed()
 		if (!selected_bibs_.contains(toqstr(f))) {
 			selected_bibs_.append(toqstr(f));
 			setSelectedBibs(selected_bibs_);
-			string enc;
 			if (usingBiblatex()) {
 				string const bfe = buffer().masterParams().bibFileEncoding(to_utf8(f));
 				if (!bfe.empty())
@@ -299,6 +321,48 @@ void GuiBibtex::inheritPressed()
 }
 
 
+void GuiBibtex::updateFileEncodings()
+{
+	vector<docstring> nfe;
+	for (int i = 0; i != selected_model_.rowCount(); ++i) {
+		QStandardItem const * key = selected_model_.item(i, 0);
+		QComboBox * cb = qobject_cast<QComboBox*>(selectedLV->indexWidget(selected_model_.index(i, 1)));
+		QString fenc = cb ? cb->itemData(cb->currentIndex()).toString() : QString();
+		docstring const enc = qstring_to_ucs4(key->text()) + " " + qstring_to_ucs4(fenc);
+		if (key && !key->text().isEmpty() && !fenc.isEmpty() && fenc != "general")
+			nfe.push_back(enc);
+	}
+	if (!nfe.empty()) {
+		setFileEncodings(nfe);
+		change_adaptor();
+	}
+}
+
+
+bool GuiBibtex::hasFileEncodings() const
+{
+	if (!usingBiblatex())
+		// only with biblatex, we have file encodings
+		return false;
+
+	// first check the applied encodings
+	docstring_list const mbibs = buffer().masterBuffer()->getBibfiles();
+	for (auto const & f : mbibs) {
+		string const bfe = buffer().masterParams().bibFileEncoding(to_utf8(f));
+		if (!bfe.empty() && bfe != "general")
+			return true;
+	}
+
+	// now check unapplied ones
+	for (QString const & enc : cached_file_encodings_) {
+		if (!enc.isEmpty() && enc != "general")
+			return true;
+	}
+
+	return false;
+}
+
+
 void GuiBibtex::relAbsPressed()
 {
 	LocalPath const p = localPathSelected();
@@ -373,6 +437,28 @@ void GuiBibtex::updateReAbs()
 }
 
 
+void GuiBibtex::addEncCombo(int const row)
+{
+	QComboBox * ecb = qobject_cast<QComboBox*>(selectedLV->indexWidget(selected_model_.index(row, 1)));
+	if (ecb)
+		// encoding combo already exists
+		return;
+
+	// Add new combo and fill it
+	QComboBox * cb = new QComboBox;
+	cb->addItem(qt_("General Encoding"), "general");
+	cb->addItem(qt_("Document Encoding"), "auto");
+	QMap<QString, QString>::const_iterator it = encodings_.constBegin();
+	while (it != encodings_.constEnd()) {
+		cb->addItem(it.key(), it.value());
+		++it;
+	}
+	cb->setToolTip(qt_("If this bibliography database uses a different "
+			   "encoding than specified below, set it here"));
+	selectedLV->setIndexWidget(selected_model_.index(row, 1), cb);
+}
+
+
 void GuiBibtex::setSelectedBibs(QStringList const & sl)
 {
 	selected_model_.clear();
@@ -380,7 +466,28 @@ void GuiBibtex::setSelectedBibs(QStringList const & sl)
 	headers << qt_("Database")
 		<< qt_("File Encoding");
 	selected_model_.setHorizontalHeaderLabels(headers);
-	bool const moreencs = usingBiblatex() && sl.count() > 1;
+	QStringList::const_iterator it  = sl.begin();
+	QStringList::const_iterator end = sl.end();
+	for (int i = 0; it != end; ++it, ++i) {
+		QStandardItem * si = new QStandardItem();
+		si->setData(*it);
+		si->setText(*it);
+		si->setToolTip(*it);
+		si->setEditable(false);
+		selected_model_.insertRow(i, si);
+		addEncCombo(i);
+		QString const enc = cached_file_encodings_[*it];
+		if (!enc.isEmpty()) {
+			QComboBox * cb = qobject_cast<QComboBox*>(selectedLV->indexWidget(selected_model_.index(i, 1)));
+			cb->setCurrentIndex(cb->findData(enc));
+		}
+	}
+
+	// Decide if we show file encoding combos. This is the case:
+	// 1. if we use Biblatex
+	// 2. and we have multiple items (otherwise you could set the genral encodung)
+	// 3. or a single item already has a non-standard encoding set
+	bool const moreencs = usingBiblatex() && (sl.count() > 1 || hasFileEncodings());
 	selectedLV->setColumnHidden(1, !moreencs);
 	selectedLV->verticalHeader()->setVisible(false);
 	selectedLV->horizontalHeader()->setVisible(moreencs);
@@ -395,28 +502,8 @@ void GuiBibtex::setSelectedBibs(QStringList const & sl)
 		bibEncodingCO->setToolTip(qt_("If your bibliography databases use a different "
 					      "encoding than the LyX document, specify it here"));
 	}
-	QStringList::const_iterator it  = sl.begin();
-	QStringList::const_iterator end = sl.end();
-	for (int i = 0; it != end; ++it, ++i) {
-		QStandardItem * si = new QStandardItem();
-		si->setData(*it);
-		si->setText(*it);
-		si->setToolTip(*it);
-		si->setEditable(false);
-		selected_model_.insertRow(i, si);
-		QComboBox * cb = new QComboBox;
-		cb->addItem(qt_("General Encoding"), "general");
-		cb->addItem(qt_("Document Encoding"), "auto");
-		QMap<QString, QString>::const_iterator it = encodings_.constBegin();
-		while (it != encodings_.constEnd()) {
-			cb->addItem(it.key(), it.value());
-			++it;
-		}
-		cb->setToolTip(qt_("If this bibliography database uses a different "
-				   "encoding than specified below, set it here"));
-		selectedLV->setIndexWidget(selected_model_.index(i, 1), cb);
-	}
 	editPB->setEnabled(deletePB->isEnabled());
+	updateFileEncodings();
 	updateReAbs();
 }
 
@@ -523,11 +610,12 @@ void GuiBibtex::applyView()
 {
 	docstring dbs;
 
-	int maxCount = selected_bibs_.count();
+	QStringList sb = selectedBibs();
+	int maxCount = sb.count();
 	for (int i = 0; i < maxCount; i++) {
 		if (i != 0)
 			dbs += ',';
-		QString item = selected_bibs_.at(i);
+		QString item = sb.at(i);
 		docstring bibfile = qstring_to_ucs4(item);
 		dbs += bibfile;
 	}
@@ -630,17 +718,30 @@ vector<docstring> GuiBibtex::getFileEncodings()
 
 void GuiBibtex::setFileEncodings(vector<docstring> const & m)
 {
+	if (!usingBiblatex())
+		// no file encodings
+		return;
+
 	for (docstring const & s: m) {
 		docstring key;
 		QString enc = toqstr(split(s, key, ' '));
+		// check if we have the key
 		QModelIndexList qmil =
-				selected_model_.match(selected_model_.index(0, 0),
-						     Qt::DisplayRole, toqstr(key), 1,
-						     Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
-		if (!qmil.empty()) {
-			QComboBox * cb = qobject_cast<QComboBox*>(selectedLV->indexWidget(selected_model_.index(qmil.front().row(), 1)));
-			cb->setCurrentIndex(cb->findData(enc));
+			selected_model_.match(selected_model_.index(0, 0),
+					     Qt::DisplayRole, toqstr(key), 1,
+					     Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
+		if (qmil.isEmpty())
+			continue;
+		int const row = qmil.front().row();
+		// assure we have an encoding combo in this row ...
+		QComboBox * cb = qobject_cast<QComboBox*>(selectedLV->indexWidget(selected_model_.index(row, 1)));
+		if (!cb) {
+			addEncCombo(row);
+			cb = qobject_cast<QComboBox*>(selectedLV->indexWidget(selected_model_.index(row, 1)));
 		}
+		if (!qmil.empty())
+			// ... and set it to the desired value
+			cb->setCurrentIndex(cb->findData(enc));
 	}
 }
 
diff --git a/src/frontends/qt/GuiBibtex.h b/src/frontends/qt/GuiBibtex.h
index fdbe7901d7..5906f85a7b 100644
--- a/src/frontends/qt/GuiBibtex.h
+++ b/src/frontends/qt/GuiBibtex.h
@@ -91,6 +91,8 @@ private:
 	std::vector<docstring> getFileEncodings();
 	///
 	void setFileEncodings(std::vector<docstring> const & m);
+	/// Does this have non-default file encodings?
+	bool hasFileEncodings() const;
 
 	///
 	bool initialiseParams(std::string const & data) override;
@@ -110,8 +112,13 @@ private:
 		LP_Relative
 	};
 	LocalPath localPathSelected();
-	///
+	/// Update "Make Relative/Absolute" button text and status
 	void updateReAbs();
+	/// Update the file encodings in the available widget
+	void updateFileEncodings();
+	/// Add an encoding combo to the selected
+	/// item in row \p row if noe exists yet
+	void addEncCombo(int const row);
 
 private:
 	///
@@ -128,8 +135,10 @@ private:
 	QStringList selected_bibs_;
 	/// contains the search box
 	FancyLineEdit * filter_;
-	///
+	/// List of available encodings
 	QMap<QString, QString> encodings_;
+	/// cache of not yet applied file encodings
+	QMap<QString, QString> cached_file_encodings_;
 };
 
 } // namespace frontend


More information about the lyx-cvs mailing list