Environment: Wrap path lists at separator for tooltips

Therefore move the list detection code to the model.

Reason: The HTML wrapping mechanism used before
created hard to read tooltips like:

  /opt/Qt/5.15.2/gcc_64/bin:/
  usr/bin:/home/user/bin:/
  usr/local/sbin:/usr/local/
  bin:/usr/sbin:/usr/bin:/sbin:/
  bin:/usr/games:/usr/local/
  games:/snap/bin

which changes to the list below now:

  /opt/Qt/5.15.2/gcc_64/bin
  /usr/bin
  /home/user/bin
  /usr/local/sbin
  /usr/local/bin
  ...

Task-number: QTCREATORBUG-7993
Change-Id: I08acc2cad0d12cb4309ee50d837c50dc9ccba2d9
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Andre Hartmann
2020-04-02 20:38:09 +02:00
committed by André Hartmann
parent 6ceb2244d8
commit e31af51958
4 changed files with 49 additions and 40 deletions

View File

@@ -167,10 +167,16 @@ QVariant NameValueModel::data(const QModelIndex &index, int role) const
}
QString value = d->m_resultNameValueDictionary.value(resultIterator);
if (role == Qt::ToolTipRole && value.length() > 80) {
// Use html to enable text wrapping
value = value.toHtmlEscaped();
value.prepend(QLatin1String("<html><body>"));
value.append(QLatin1String("</body></html>"));
if (currentEntryIsPathList(index)) {
// For path lists, display one entry per line without separator
const QChar sep = Utils::HostOsInfo::pathListSeparator();
value = value.replace(sep, '\n');
} else {
// Use html to enable text wrapping
value = value.toHtmlEscaped();
value.prepend(QLatin1String("<html><body>"));
value.append(QLatin1String("</body></html>"));
}
}
return value;
}
@@ -437,4 +443,36 @@ void NameValueModel::setUserChanges(const NameValueItems &items)
emit userChangesChanged();
}
bool NameValueModel::currentEntryIsPathList(const QModelIndex &current) const
{
if (!current.isValid())
return false;
// Look at the name first and check it against some well-known path variables. Extend as needed.
const QString varName = indexToVariable(current);
if (varName.compare("PATH", Utils::HostOsInfo::fileNameCaseSensitivity()) == 0)
return true;
if (Utils::HostOsInfo::isMacHost() && varName == "DYLD_LIBRARY_PATH")
return true;
if (Utils::HostOsInfo::isAnyUnixHost() && varName == "LD_LIBRARY_PATH")
return true;
if (varName == "PKG_CONFIG_DIR")
return true;
if (Utils::HostOsInfo::isWindowsHost()
&& QStringList{"INCLUDE", "LIB", "LIBPATH"}.contains(varName)) {
return true;
}
// Now check the value: If it's a list of strings separated by the platform's path separator
// and at least one of the strings is an existing directory, then that's enough proof for us.
QModelIndex valueIndex = current;
if (valueIndex.column() == 0)
valueIndex = valueIndex.siblingAtColumn(1);
const QStringList entries = data(valueIndex).toString()
.split(Utils::HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts);
if (entries.length() < 2)
return false;
return Utils::anyOf(entries, [](const QString &d) { return QFileInfo(d).isDir(); });
}
} // namespace Utils

View File

@@ -70,6 +70,7 @@ public:
void setBaseNameValueDictionary(const NameValueDictionary &dictionary);
NameValueItems userChanges() const;
void setUserChanges(const NameValueItems &items);
bool currentEntryIsPathList(const QModelIndex &current) const;
signals:
void userChangesChanged();

View File

@@ -437,38 +437,6 @@ void EnvironmentWidget::linkActivated(const QString &link)
focusIndex(idx);
}
bool EnvironmentWidget::currentEntryIsPathList(const QModelIndex &current) const
{
if (!current.isValid())
return false;
// Look at the name first and check it against some well-known path variables. Extend as needed.
const QString varName = d->m_model->indexToVariable(current);
if (varName.compare("PATH", Utils::HostOsInfo::fileNameCaseSensitivity()) == 0)
return true;
if (Utils::HostOsInfo::isMacHost() && varName == "DYLD_LIBRARY_PATH")
return true;
if (Utils::HostOsInfo::isAnyUnixHost() && varName == "LD_LIBRARY_PATH")
return true;
if (varName == "PKG_CONFIG_DIR")
return true;
if (Utils::HostOsInfo::isWindowsHost()
&& QStringList{"INCLUDE", "LIB", "LIBPATH"}.contains(varName)) {
return true;
}
// Now check the value: If it's a list of strings separated by the platform's path separator
// and at least one of the strings is an existing directory, then that's enough proof for us.
QModelIndex valueIndex = current;
if (valueIndex.column() == 0)
valueIndex = valueIndex.siblingAtColumn(1);
const QStringList entries = d->m_model->data(valueIndex).toString()
.split(Utils::HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts);
if (entries.length() < 2)
return false;
return Utils::anyOf(entries, [](const QString &d) { return QFileInfo(d).isDir(); });
}
void EnvironmentWidget::updateButtons()
{
environmentCurrentIndexChanged(d->m_environmentView->currentIndex());
@@ -477,7 +445,9 @@ void EnvironmentWidget::updateButtons()
void EnvironmentWidget::editEnvironmentButtonClicked()
{
const QModelIndex current = d->m_environmentView->currentIndex();
if (current.column() == 1 && d->m_type == TypeLocal && currentEntryIsPathList(current)) {
if (current.column() == 1
&& d->m_type == TypeLocal
&& d->m_model->currentEntryIsPathList(current)) {
PathListDialog dlg(d->m_model->indexToVariable(current),
d->m_model->data(current).toString(), this);
if (dlg.exec() == QDialog::Accepted)
@@ -562,8 +532,9 @@ void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &curren
d->m_toggleButton->setText(tr("Disable"));
}
if (d->m_appendPathButton) {
d->m_appendPathButton->setEnabled(currentEntryIsPathList(current));
d->m_prependPathButton->setEnabled(currentEntryIsPathList(current));
const bool isPathList = d->m_model->currentEntryIsPathList(current);
d->m_appendPathButton->setEnabled(isPathList);
d->m_prependPathButton->setEnabled(isPathList);
}
}

View File

@@ -80,7 +80,6 @@ private:
void focusIndex(const QModelIndex &index);
void updateButtons();
void linkActivated(const QString &link);
bool currentEntryIsPathList(const QModelIndex &current) const;
using PathListModifier = std::function<QString(const QString &oldList, const QString &newDir)>;
void amendPathList(Utils::NameValueItem::Operation op);