forked from qt-creator/qt-creator
Merge "Merge remote-tracking branch 'origin/11.0'"
This commit is contained in:
@@ -54,6 +54,10 @@ bool UnixPtyProcess::startProcess(const QString &shellPath,
|
||||
int rc = 0;
|
||||
|
||||
m_shellProcess.m_handleMaster = ::posix_openpt(O_RDWR | O_NOCTTY);
|
||||
|
||||
int flags = fcntl(m_shellProcess.m_handleMaster, F_GETFL, 0);
|
||||
fcntl(m_shellProcess.m_handleMaster, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
if (m_shellProcess.m_handleMaster <= 0) {
|
||||
m_lastError = QString("UnixPty Error: unable to open master -> %1").arg(QLatin1String(strerror(errno)));
|
||||
kill();
|
||||
@@ -308,10 +312,7 @@ QByteArray UnixPtyProcess::readAll()
|
||||
|
||||
qint64 UnixPtyProcess::write(const QByteArray &byteArray)
|
||||
{
|
||||
int result = ::write(m_shellProcess.m_handleMaster, byteArray.constData(), byteArray.size());
|
||||
Q_UNUSED(result)
|
||||
|
||||
return byteArray.size();
|
||||
return ::write(m_shellProcess.m_handleMaster, byteArray.constData(), byteArray.size());
|
||||
}
|
||||
|
||||
bool UnixPtyProcess::isAvailable()
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <vterm.h>
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QTimer>
|
||||
|
||||
namespace TerminalSolution {
|
||||
|
||||
@@ -20,6 +21,8 @@ QColor toQColor(const VTermColor &c)
|
||||
return QColor(qRgb(c.rgb.red, c.rgb.green, c.rgb.blue));
|
||||
};
|
||||
|
||||
constexpr int batchFlushSize = 256;
|
||||
|
||||
struct TerminalSurfacePrivate
|
||||
{
|
||||
TerminalSurfacePrivate(TerminalSurface *surface, const QSize &initialGridSize)
|
||||
@@ -29,13 +32,64 @@ struct TerminalSurfacePrivate
|
||||
, q(surface)
|
||||
{}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if (m_writeBuffer.isEmpty())
|
||||
return;
|
||||
|
||||
QByteArray data = m_writeBuffer.left(batchFlushSize);
|
||||
qint64 result = m_writeToPty(data);
|
||||
|
||||
if (result != data.size()) {
|
||||
// Not all data was written, remove the unwritten data from the array
|
||||
data.resize(qMax(0, result));
|
||||
}
|
||||
|
||||
// Remove the written data from the buffer
|
||||
if (data.size() > 0)
|
||||
m_writeBuffer = m_writeBuffer.mid(data.size());
|
||||
|
||||
if (!m_writeBuffer.isEmpty())
|
||||
m_delayWriteTimer.start();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
m_delayWriteTimer.setInterval(1);
|
||||
m_delayWriteTimer.setSingleShot(true);
|
||||
|
||||
QObject::connect(&m_delayWriteTimer, &QTimer::timeout, &m_delayWriteTimer, [this] {
|
||||
flush();
|
||||
});
|
||||
|
||||
vterm_set_utf8(m_vterm.get(), true);
|
||||
|
||||
static auto writeToPty = [](const char *s, size_t len, void *user) {
|
||||
auto p = static_cast<TerminalSurfacePrivate *>(user);
|
||||
emit p->q->writeToPty(QByteArray(s, static_cast<int>(len)));
|
||||
QByteArray d(s, len);
|
||||
|
||||
// If its just a couple of chars, or we already have data in the writeBuffer,
|
||||
// add the new data to the write buffer and start the delay timer
|
||||
if (d.size() < batchFlushSize || !p->m_writeBuffer.isEmpty()) {
|
||||
p->m_writeBuffer.append(d);
|
||||
p->m_delayWriteTimer.start();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to write the data ...
|
||||
qint64 result = p->m_writeToPty(d);
|
||||
|
||||
if (result != d.size()) {
|
||||
// if writing failed, append the data to the writeBuffer and start the delay timer
|
||||
|
||||
// Check if partial data may have already been written ...
|
||||
if (result <= 0)
|
||||
p->m_writeBuffer.append(d);
|
||||
else
|
||||
p->m_writeBuffer.append(d.mid(result));
|
||||
|
||||
p->m_delayWriteTimer.start();
|
||||
}
|
||||
};
|
||||
|
||||
vterm_output_set_callback(m_vterm.get(), writeToPty, this);
|
||||
@@ -319,6 +373,10 @@ struct TerminalSurfacePrivate
|
||||
SurfaceIntegration *m_surfaceIntegration{nullptr};
|
||||
|
||||
TerminalSurface *q;
|
||||
QTimer m_delayWriteTimer;
|
||||
QByteArray m_writeBuffer;
|
||||
|
||||
TerminalSurface::WriteToPty m_writeToPty;
|
||||
};
|
||||
|
||||
TerminalSurface::TerminalSurface(QSize initialGridSize)
|
||||
@@ -393,7 +451,7 @@ void TerminalSurface::clearAll()
|
||||
vterm_input_write(d->m_vterm.get(), data.constData(), data.size());
|
||||
|
||||
// Send Ctrl+L which will clear the screen
|
||||
emit writeToPty(QByteArray("\f"));
|
||||
d->m_writeToPty(QByteArray("\f"));
|
||||
}
|
||||
|
||||
void TerminalSurface::resize(QSize newSize)
|
||||
@@ -539,6 +597,11 @@ void TerminalSurface::mouseButton(Qt::MouseButton button,
|
||||
vterm_mouse_button(d->m_vterm.get(), btnIdx, pressed, qtModifierToVTerm(modifiers));
|
||||
}
|
||||
|
||||
void TerminalSurface::setWriteToPty(WriteToPty writeToPty)
|
||||
{
|
||||
d->m_writeToPty = writeToPty;
|
||||
}
|
||||
|
||||
CellIterator TerminalSurface::begin() const
|
||||
{
|
||||
auto res = CellIterator(this, {0, 0});
|
||||
|
||||
@@ -98,10 +98,12 @@ public:
|
||||
SurfaceIntegration *surfaceIntegration() const;
|
||||
void setSurfaceIntegration(SurfaceIntegration *surfaceIntegration);
|
||||
|
||||
using WriteToPty = std::function<qint64(const QByteArray &)>;
|
||||
void setWriteToPty(WriteToPty writeToPty);
|
||||
|
||||
void mouseMove(QPoint pos, Qt::KeyboardModifiers modifiers);
|
||||
void mouseButton(Qt::MouseButton button, bool pressed, Qt::KeyboardModifiers modifiers);
|
||||
signals:
|
||||
void writeToPty(const QByteArray &data);
|
||||
void invalidated(QRect grid);
|
||||
void fullSizeChanged(QSize newSize);
|
||||
void cursorChanged(Cursor oldCursor, Cursor newCursor);
|
||||
|
||||
@@ -170,7 +170,7 @@ void TerminalView::setupSurface()
|
||||
if (d->m_surfaceIntegration)
|
||||
d->m_surface->setSurfaceIntegration(d->m_surfaceIntegration);
|
||||
|
||||
connect(d->m_surface.get(), &TerminalSurface::writeToPty, this, &TerminalView::writeToPty);
|
||||
d->m_surface->setWriteToPty([this](const QByteArray &data) { return writeToPty(data); });
|
||||
|
||||
connect(d->m_surface.get(), &TerminalSurface::fullSizeChanged, this, [this] {
|
||||
updateScrollBars();
|
||||
|
||||
@@ -105,7 +105,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
virtual void writeToPty(const QByteArray &data) { Q_UNUSED(data); }
|
||||
virtual qint64 writeToPty(const QByteArray &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return 0;
|
||||
}
|
||||
void writeToTerminal(const QByteArray &data, bool forceFlush);
|
||||
|
||||
void restart();
|
||||
|
||||
@@ -1564,9 +1564,11 @@ qint64 Process::writeRaw(const QByteArray &input)
|
||||
QTC_ASSERT(state() == QProcess::Running, return -1);
|
||||
QTC_ASSERT(QThread::currentThread() == thread(), return -1);
|
||||
qint64 result = -1;
|
||||
QMetaObject::invokeMethod(d->m_process.get(), [this, input] {
|
||||
d->m_process->write(input);
|
||||
}, d->connectionType(), &result);
|
||||
QMetaObject::invokeMethod(
|
||||
d->m_process.get(),
|
||||
[this, input] { return d->m_process->write(input); },
|
||||
d->connectionType(),
|
||||
&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,36 @@ CommandsFile::CommandsFile(const FilePath &filename)
|
||||
|
||||
}
|
||||
|
||||
// XML attributes cannot contain these characters, and
|
||||
// QXmlStreamWriter just bails out with an error.
|
||||
// QKeySequence::toString() should probably not result in these
|
||||
// characters, but it currently does, see QTCREATORBUG-29431
|
||||
static bool containsInvalidCharacters(const QString &s)
|
||||
{
|
||||
const auto end = s.constEnd();
|
||||
for (auto it = s.constBegin(); it != end; ++it) {
|
||||
// from QXmlStreamWriterPrivate::writeEscaped
|
||||
if (*it == u'\v' || *it == u'\f' || *it <= u'\x1F' || *it >= u'\uFFFE') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static QString toAttribute(const QString &s)
|
||||
{
|
||||
if (containsInvalidCharacters(s))
|
||||
return "0x" + QString::fromUtf8(s.toUtf8().toHex());
|
||||
return s;
|
||||
}
|
||||
|
||||
static QString fromAttribute(const QStringView &s)
|
||||
{
|
||||
if (s.startsWith(QLatin1String("0x")))
|
||||
return QString::fromUtf8(QByteArray::fromHex(s.sliced(2).toUtf8()));
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
@@ -76,7 +106,7 @@ QMap<QString, QList<QKeySequence>> CommandsFile::importCommands() const
|
||||
QTC_ASSERT(!currentId.isEmpty(), continue);
|
||||
const QXmlStreamAttributes attributes = r.attributes();
|
||||
if (attributes.hasAttribute(ctx.valueAttribute)) {
|
||||
const QString keyString = attributes.value(ctx.valueAttribute).toString();
|
||||
const QString keyString = fromAttribute(attributes.value(ctx.valueAttribute));
|
||||
QList<QKeySequence> keys = result.value(currentId);
|
||||
result.insert(currentId, keys << QKeySequence(keyString));
|
||||
}
|
||||
@@ -93,7 +123,6 @@ QMap<QString, QList<QKeySequence>> CommandsFile::importCommands() const
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
|
||||
bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
|
||||
{
|
||||
FileSaver saver(m_filePath, QIODevice::Text);
|
||||
@@ -118,7 +147,7 @@ bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
|
||||
w.writeAttribute(ctx.idAttribute, id.toString());
|
||||
for (const QKeySequence &k : item->m_keys) {
|
||||
w.writeEmptyElement(ctx.keyElement);
|
||||
w.writeAttribute(ctx.valueAttribute, k.toString());
|
||||
w.writeAttribute(ctx.valueAttribute, toAttribute(k.toString()));
|
||||
}
|
||||
w.writeEndElement(); // Shortcut
|
||||
}
|
||||
@@ -126,7 +155,8 @@ bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
|
||||
w.writeEndElement();
|
||||
w.writeEndDocument();
|
||||
|
||||
saver.setResult(&w);
|
||||
if (!saver.setResult(&w))
|
||||
qWarning() << saver.errorString();
|
||||
}
|
||||
return saver.finalize();
|
||||
}
|
||||
|
||||
@@ -426,6 +426,7 @@ public:
|
||||
QList<ParameterAction *> m_projectActions;
|
||||
QList<QAction *> m_repositoryActions;
|
||||
ParameterAction *m_applyCurrentFilePatchAction = nullptr;
|
||||
|
||||
Gerrit::Internal::GerritPlugin m_gerritPlugin;
|
||||
|
||||
QPointer<StashDialog> m_stashDialog;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <coreplugin/icore.h>
|
||||
#include <debugger/debuggeritem.h>
|
||||
#include <debugger/debuggeritemmanager.h>
|
||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
#include <projectexplorer/toolchainmanager.h>
|
||||
@@ -447,7 +448,8 @@ static ToolChain *iarToolChain(const FilePath &path, Id language)
|
||||
== BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
|
||||
});
|
||||
if (iarFactory) {
|
||||
Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}, {}));
|
||||
Toolchains detected = iarFactory->autoDetect(
|
||||
{{}, DeviceManager::defaultDesktopDevice(), {}});
|
||||
if (detected.isEmpty())
|
||||
detected = iarFactory->detectForImport({path, language});
|
||||
for (auto tc : detected) {
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
|
||||
#include "toolchainoptionspage.h"
|
||||
|
||||
#include "toolchain.h"
|
||||
#include "abi.h"
|
||||
#include "devicesupport/devicemanager.h"
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "projectexplorertr.h"
|
||||
#include "toolchain.h"
|
||||
#include "toolchainconfigwidget.h"
|
||||
#include "toolchainmanager.h"
|
||||
|
||||
@@ -407,7 +408,7 @@ void ToolChainOptionsWidget::redetectToolchains()
|
||||
QSet<ToolChain *> toDelete;
|
||||
ToolChainManager::resetBadToolchains();
|
||||
for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
|
||||
const ToolchainDetector detector(knownTcs, {}, {}); // FIXME: Pass device and search paths
|
||||
const ToolchainDetector detector(knownTcs, DeviceManager::defaultDesktopDevice(), {}); // FIXME: Pass search paths
|
||||
for (ToolChain * const tc : f->autoDetect(detector)) {
|
||||
if (knownTcs.contains(tc) || toDelete.contains(tc))
|
||||
continue;
|
||||
|
||||
@@ -1675,8 +1675,8 @@ void DesignerActionManager::createDefaultDesignerActions()
|
||||
setFlowStartDisplayName,
|
||||
{},
|
||||
flowCategory,
|
||||
2,
|
||||
{},
|
||||
2,
|
||||
&setFlowStartItem,
|
||||
&isFlowItem,
|
||||
&flowOptionVisible));
|
||||
|
||||
@@ -260,10 +260,12 @@ void TerminalWidget::closeTerminal()
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void TerminalWidget::writeToPty(const QByteArray &data)
|
||||
qint64 TerminalWidget::writeToPty(const QByteArray &data)
|
||||
{
|
||||
if (m_process && m_process->isRunning())
|
||||
m_process->writeRaw(data);
|
||||
return m_process->writeRaw(data);
|
||||
|
||||
return data.size();
|
||||
}
|
||||
|
||||
void TerminalWidget::resizePty(QSize newSize)
|
||||
|
||||
@@ -71,7 +71,7 @@ protected:
|
||||
void linkActivated(const Link &link) override;
|
||||
void contextMenuRequested(const QPoint &pos) override;
|
||||
|
||||
void writeToPty(const QByteArray &data) override;
|
||||
qint64 writeToPty(const QByteArray &data) override;
|
||||
void resizePty(QSize newSize) override;
|
||||
void setClipboard(const QString &text) override;
|
||||
std::optional<TerminalView::Link> toLink(const QString &text) override;
|
||||
|
||||
Reference in New Issue
Block a user