Merge remote-tracking branch 'origin/14.0'

Change-Id: I0d5fd257c10eeb452d8767aba63bb7f7faacd48e
This commit is contained in:
Eike Ziller
2024-07-03 10:14:34 +02:00
49 changed files with 458 additions and 260 deletions

View File

@@ -15,6 +15,7 @@ General
* Started work on supporting Lua based plugins (registering language servers,
actions, preferences, and wizards)
([Documentation](https://doc-snapshots.qt.io/qtcreator-extending/lua-extensions.html))
* Added a mode for managing extensions
* Added `Clear` and `Save Contents` to context menus of all output views
* Locator
* Added the option to show results relative to project root
@@ -38,6 +39,9 @@ Editing
* Fixed that after hiding the editor in `Debug` mode, `Edit` mode always opened
when opening documents, even if an external editor window was available
([QTCREATORBUG-30408](https://bugreports.qt.io/browse/QTCREATORBUG-30408))
* Fixed that it wasn't possible to open a file in the text editor if it was
classified as a binary file format by the MIME database
([QTCREATORBUG-31116](https://bugreports.qt.io/browse/QTCREATORBUG-31116))
### C++
@@ -177,6 +181,12 @@ Projects
* Fixed a crash when triggering `Follow Symbol` in a CMake file that does not
belong to a project
([QTCREATORBUG-31077](https://bugreports.qt.io/browse/QTCREATORBUG-31077))
* Fixed that multiple build configurations of the same type used the same
build directory
([QTCREATORBUG-26066](https://bugreports.qt.io/browse/QTCREATORBUG-26066))
* Fixed an issue with adding new files when file globs are used in the CMake
files
([QTCREATORBUG-30445](https://bugreports.qt.io/browse/QTCREATORBUG-30445))
* Presets
* Made CMake settings configurable
([QTCREATORBUG-25972](https://bugreports.qt.io/browse/QTCREATORBUG-25972),
@@ -291,7 +301,8 @@ Platforms
### Remote Linux
* Added the option to use SSH port forwarding for debugging
* Added the `Use SSH port forwarding for debugging` option in `Preferences` >
`Devices` for a `Remote Linux Device`
* Improved the performance of the generic deployment method
* Fixed that the file size check that is performed before parsing C++ files
could freeze Qt Creator until finished for remote projects
@@ -343,8 +354,10 @@ Michael Weghorn
Miikka Heikkinen
Orgad Shaneh
Pranta Dastider
Ralf Habacker
Robert Löhning
Sami Shalayel
Semih Yavuz
Sergey Silin
Shrief Gabr
Teea Poldsam

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -14,11 +14,11 @@
\ingroup creator-reference-debugger
\title Supported Native Debuggers
\title Supported Debuggers
\brief Summary of supported debugger versions.
\QC supports native debuggers for debugging compiled code.
You can use \QC to debug compiled code.
On most supported platforms, you can use the GNU Symbolic Debugger (GDB).
On Microsoft Windows, when using the Microsoft toolchain, you need the
Microsoft Console Debugger (CDB). On \macos and Linux, you can use the LLDB
@@ -34,7 +34,7 @@
\header
\li Platform
\li Compiler
\li Native Debugger
\li Debugger
\row
\li Linux
\li GCC, ICC
@@ -57,9 +57,9 @@
\li Debugging Tools for Windows/CDB
\endtable
The debugger plugin automatically selects a suitable native debugger for
\QC automatically selects a suitable debugger for
each \l{Kits}{kit} from the ones found on the computer. The automatic
setup fails if the native debugger is not installed on the computer or
setup fails if the debugger is not installed on the computer or
if \QC does not support the installed version.
\section1 GDB Versions
@@ -123,7 +123,7 @@
{Mac OS X Debugging Magic}.
\section1 LLDB Versions
The LLDB native debugger has similar functionality to the GDB debugger. LLDB
The LLDB debugger has similar functionality to the GDB debugger. LLDB
is the default debugger in Xcode on \macos for C++ on the desktop.
LLDB is typically used with the Clang compiler (even though you can use it
with GCC, too).

View File

@@ -14,8 +14,7 @@
\title Debugging
The \QC debugger plugin acts as an interface between the \QC
core and external native debuggers that you can use to:
You can use debuggers to:
\list
\li Debug executable binary files - GNU Symbolic Debugger (GDB),
@@ -28,7 +27,7 @@
\section1 Setting Up the Debugger
The debugger plugin automatically selects a suitable native debugger for
\QC automatically selects a suitable debugger for
each \l{Kits}{kit} from the ones found on your system. You can select
another kit. To specify the debugger and compiler to use for each kit, go to
\preferences > \uicontrol Kits.
@@ -36,7 +35,7 @@
\image qtcreator-kits.png {Kits preferences}
You need to set up the debugger only if the automatic setup fails because
the native debugger is missing (for example, you must install the CDB
the debugger is missing (for example, you must install the CDB
debugger on Windows yourself) or because \QC does not support the installed
version. For example, when your system does not have GDB
installed or the installed version is outdated, and you want to use a locally
@@ -58,11 +57,11 @@
Optionally, you can set up the Microsoft Symbol Server if you need
symbol information from Microsoft modules that is not found locally.
For more information, see \l{Supported Native Debuggers} and \l{CDB Paths}.
For more information, see \l{Supported Debuggers} and \l{CDB Paths}.
\section1 Launching the Debugger
The debugger plugin can run the native debuggers in various operating modes
The debuggers run in various operating modes
depending on where and how you start and run the debugged process. Some of
the modes are only available for a particular operating system or platform:
@@ -93,9 +92,8 @@
\section2 GDB Run Modes
The GDB native debugger used internally by the debugger plugin runs in
different modes to cope with the variety of supported platforms and
environments:
The GDB debugger runs in different modes to cope with the variety of
supported platforms and environments:
\list
\li \e{Plain mode} debugs locally started processes that do not need
@@ -591,8 +589,24 @@
in GDB, see \l{https://sourceware.org/gdb/onlinedocs/gdb/Connecting.html}
{Debugging with GDB: Connecting to a Remote Target}.
\sa {Debug}{How To: Debug}, {GDB}, {Debugging},
{Debuggers}, {Debugger}, {Kits}
\section1 Use SSH port forwarding
To enable debugging on remote targets that cannot expose GDB server ports,
map the remote ports to local ports using SSH tunneling. \QC automatically
detects the local and remote ports.
To turn on SSH port forwarding:
\list 1
\li Go to \preferences > \uicontrol Devices.
\image qtcreator-preferences-devices-remote-linux.webp {Remote Linux device preferences}
\li In \uicontrol Device, select \uicontrol {Remote Linux Device}.
\li Select \uicontrol {Use SSH port forwarding for debugging}.
\li Select \uicontrol OK.
\endlist
\sa {Debug}{How To: Debug}, {Remote Linux}{How To: Develop for remote Linux},
{GDB}, {Debugging}, {Debuggers}, {Debugger}, {Kits}
*/
/*!
@@ -770,7 +784,7 @@
The log view acts as a console, so you can send the contents
of the line under the text cursor in the log directly to the
native debugger.
debugger.
\li \l{Troubleshooting Debugger}
\l {Debugger Log}
@@ -865,9 +879,9 @@
\title Examine complex values in Debug views
\QC displays the raw information from the native debuggers in a clear and
\QC displays the raw information from the debuggers in a clear and
concise manner to simplify the debugging process without losing the power
of the native debuggers.
of the debuggers.
\image qtcreator-locals.png {Locals view}
@@ -1150,8 +1164,8 @@
\brief View information about the modules included in a debugged application.
The \uicontrol Modules view displays information that the debugger plugin
has about modules included in the application that is being debugged.
The \uicontrol Modules view displays information about modules included in
the application that is being debugged.
A module is:
@@ -1389,13 +1403,13 @@
\li Set \l{Debugger}{debugger preferences}.
\endlist
\section1 Directly Interacting with Native Debuggers
\section1 Directly Interacting with Debuggers
You can use the left pane of the \uicontrol {Debugger Log} view to directly
interact with the command line of the native debugger.
interact with the command line of the debugger.
Press \key {Ctrl+Enter} to send the contents of the line under the
text cursor to the native debugger. Or, enter the command in the
text cursor to the debugger. Or, enter the command in the
\uicontrol Command field. The right side pane of the
\uicontrol {Debugger Log} view shows the command output.
@@ -1464,7 +1478,7 @@
\brief Load, customize, and add debugging helpers.
\QC uses Python scripts to translate raw memory contents and type information
data from native debugger backends (GDB, LLDB, and CDB are currently supported)
data from debugger backends (GDB, LLDB, and CDB are currently supported)
into the form presented to the user in the
\l {Local Variables and Function Parameters}{Locals}
and \l {Evaluating Expressions}{Expressions} views.
@@ -1520,7 +1534,7 @@
of Qt, or of your own library, at the same time.
To add debugging helpers for custom types, add debugging helper
implementations to the startup file of the native debuggers (for example,
implementations to the startup file of the debuggers (for example,
\c{~/.gdbinit} or \c{~/.lldbinit}) or specify them directly in the
\uicontrol {Additional Startup Commands} in \preferences >
\uicontrol Debugger > \uicontrol GDB.
@@ -1733,7 +1747,7 @@
\endcode
\li \c{putCallItem(self, name, rettype, value, func, *args)} - Uses the
native debugger backend to place the function call \c func returning
debugger backend to place the function call \c func returning
\c rettype on the value specified by \a {value} and to output the
resulting item.
@@ -1880,7 +1894,7 @@
an integral or floating point type.
Type objects, that is, instances of the \c{Dumper.Type} class, can be
created by native debugger backends, usually by evaluating Debug Information
created by debugger backends, usually by evaluating Debug Information
built into or shipped alongside the debugged binary, or created on-the-fly
by the debugging helper.
@@ -2110,7 +2124,7 @@
\l {Run on many platforms}{build and run kit selector}
picked a runnable target and you can run the application.
\li Make sure the debugger is \l{Supported Native Debuggers}{set up properly}.
\li Make sure the debugger is \l{Supported Debuggers}{set up properly}.
\li In the \uicontrol Debug mode, go to \uicontrol View >
\uicontrol Views > \uicontrol {Debugger Log} to open the

View File

@@ -66,8 +66,7 @@
\section1 Debug
Use native debuggers to inspect the state of your application while
debugging.
Use debuggers to inspect the state of your application while it is running.
\generatelist creator-how-to-debug

View File

@@ -143,7 +143,7 @@
You must use Python version 2.6 or 2.7.
For more information, see \l{Supported Native Debuggers}.
For more information, see \l{Supported Debuggers}.
\b {How do I generate a core file in \QC?}

View File

@@ -35,5 +35,6 @@
it is compatible with the GDB on the host.
\sa {Remote Linux}{How To: Develop for remote Linux},
{Run on many platforms}, {Compilers}, {Embedded Platforms}, {Kits}
{Debug remotely with GDB}, {Run on many platforms}, {Compilers},
{Embedded Platforms}, {Kits}
*/

View File

@@ -138,6 +138,6 @@
\include qtcreator-add-linux-device.qdocinc {add linux device} {Remote Linux Device}
\sa {Remote Linux}{How To: Develop for remote Linux},
{Developing for Remote Linux Devices},
{Debug remotely with GDB}, {Developing for Remote Linux Devices},
{Remote Linux Deploy Configuration}
*/

View File

@@ -266,10 +266,10 @@
to find the next one.
\endlist
\QC integrates several native debuggers for inspecting the state of
your application while debugging. The debugger plugin automatically selects
a suitable native debugger for each kit from the ones it finds on the
computer. Edit the kits to override this choice.
\QC integrates several debuggers for inspecting the state of your
application. It automatically selects a suitable debugger for each
kit from the ones it finds on the computer. Edit the kits to override
this choice.
If you install \QC with \QOI, the GNU Symbolic Debugger is installed
automatically and you should be ready to start debugging after you create

View File

@@ -21,7 +21,7 @@
\section1 Debuggers
Set up and use native debuggers to debug executable binary files, as well as
Set up and use debuggers to debug executable binary files, as well as
QML, Java, and Python source code.
\annotatedlist creator-reference-debugger

View File

@@ -15,12 +15,11 @@
\title Add debuggers
The \QC debugger plugin acts as an interface between the \QC core and
external native debuggers such as the GNU Symbolic Debugger (GDB),
You can use debuggers, such as the GNU Symbolic Debugger (GDB),
the Microsoft Console Debugger (CDB), a QML/JavaScript debugger, and the
debugger of the low level virtual machine (LLVM) project, LLDB.
The debugger plugin automatically selects a suitable native debugger for
\QC automatically selects a suitable debugger for
each \l{Kits}{kit} from the ones found on your system.
To override this choice, select \preferences > \uicontrol Kits.
@@ -75,6 +74,6 @@
The debugger disappears from the list when you select \uicontrol Apply.
Until then, you can cancel the deletion by clicking \uicontrol Restore.
\sa {Debugging}, {Debuggers}, {Debugger}, {Supported Native Debuggers},
\sa {Debugging}, {Debuggers}, {Debugger}, {Supported Debuggers},
{Troubleshooting Debugger}
*/

View File

@@ -26,7 +26,7 @@
\li \l{Run Python applications}
\li \l{Python Run Settings}
\li \l{PDB versions}
\li \l{Supported Native Debuggers}
\li \l{Supported Debuggers}
\endlist
For more information about developing with Qt for Python, including

View File

@@ -99,8 +99,8 @@ public:
iter = iter->next;
return *this;
}
bool operator==(const ListIterator &other) { return iter == other.iter; }
bool operator!=(const ListIterator &other) { return iter != other.iter; }
bool operator==(const ListIterator &other) const { return iter == other.iter; }
bool operator!=(const ListIterator &other) const { return iter != other.iter; }
};
ListIterator begin() { return {this}; }
ListIterator end() { return {nullptr}; }

View File

@@ -330,13 +330,10 @@ static QTextLine currentTextLine(const QTextCursor &cursor)
return layout->lineForTextPosition(relativePos);
}
bool MultiTextCursor::multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey)
bool MultiTextCursor::multiCursorEvent(
QKeyEvent *e, QKeySequence::StandardKey matchKey, Qt::KeyboardModifiers filterModifiers)
{
uint searchkey = (e->modifiers() | e->key())
& ~(Qt::KeypadModifier
| Qt::GroupSwitchModifier
| Qt::AltModifier
| Qt::ShiftModifier);
uint searchkey = (e->modifiers() | e->key()) & ~(filterModifiers | Qt::AltModifier);
const QList<QKeySequence> bindings = QKeySequence::keyBindings(matchKey);
return bindings.contains(QKeySequence(searchkey));
@@ -348,42 +345,42 @@ bool MultiTextCursor::handleMoveKeyEvent(QKeyEvent *e,
{
if (e->modifiers() & Qt::AltModifier && !Utils::HostOsInfo::isMacHost()) {
QTextCursor::MoveOperation op = QTextCursor::NoMove;
if (multiCursorAddEvent(e, QKeySequence::MoveToNextWord)) {
if (multiCursorEvent(e, QKeySequence::MoveToNextWord)) {
op = QTextCursor::WordRight;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToPreviousWord)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToPreviousWord)) {
op = QTextCursor::WordLeft;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToEndOfBlock)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToEndOfBlock)) {
op = QTextCursor::EndOfBlock;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToStartOfBlock)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToStartOfBlock)) {
op = QTextCursor::StartOfBlock;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToNextLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToNextLine, Qt::ShiftModifier)) {
op = QTextCursor::Down;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToPreviousLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToPreviousLine, Qt::ShiftModifier)) {
op = QTextCursor::Up;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToStartOfLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToStartOfLine)) {
op = QTextCursor::StartOfLine;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToEndOfLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToEndOfLine)) {
op = QTextCursor::EndOfLine;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToStartOfDocument)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToStartOfDocument)) {
op = QTextCursor::Start;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToEndOfDocument)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToEndOfDocument)) {
op = QTextCursor::End;
} else {
return false;
}
const std::list<QTextCursor> cursors = m_cursorList;
for (QTextCursor cursor : cursors) {
if (camelCaseNavigationEnabled && op == QTextCursor::WordRight)
CamelCaseCursor::right(&cursor, edit, QTextCursor::MoveAnchor);
else if (camelCaseNavigationEnabled && op == QTextCursor::WordLeft)
CamelCaseCursor::left(&cursor, edit, QTextCursor::MoveAnchor);
else
cursor.movePosition(op, QTextCursor::MoveAnchor);
if (op != QTextCursor::NoMove) {
const std::list<QTextCursor> cursors = m_cursorList;
for (QTextCursor cursor : cursors) {
if (camelCaseNavigationEnabled && op == QTextCursor::WordRight)
CamelCaseCursor::right(&cursor, edit, QTextCursor::MoveAnchor);
else if (camelCaseNavigationEnabled && op == QTextCursor::WordLeft)
CamelCaseCursor::left(&cursor, edit, QTextCursor::MoveAnchor);
else
cursor.movePosition(op, QTextCursor::MoveAnchor);
addCursor(cursor);
addCursor(cursor);
}
return true;
}
return true;
}
for (auto it = m_cursorList.begin(); it != m_cursorList.end(); ++it) {
@@ -395,28 +392,28 @@ bool MultiTextCursor::handleMoveKeyEvent(QKeyEvent *e,
op = QTextCursor::Right;
} else if (e == QKeySequence::MoveToPreviousChar) {
op = QTextCursor::Left;
} else if (e == QKeySequence::SelectNextChar) {
} else if (multiCursorEvent(e, QKeySequence::SelectNextChar)) {
op = QTextCursor::Right;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectPreviousChar) {
} else if (multiCursorEvent(e, QKeySequence::SelectPreviousChar)) {
op = QTextCursor::Left;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectNextWord) {
} else if (multiCursorEvent(e, QKeySequence::SelectNextWord)) {
op = QTextCursor::WordRight;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectPreviousWord) {
} else if (multiCursorEvent(e, QKeySequence::SelectPreviousWord)) {
op = QTextCursor::WordLeft;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectStartOfLine) {
} else if (multiCursorEvent(e, QKeySequence::SelectStartOfLine)) {
op = QTextCursor::StartOfLine;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectEndOfLine) {
} else if (multiCursorEvent(e, QKeySequence::SelectEndOfLine)) {
op = QTextCursor::EndOfLine;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectStartOfBlock) {
} else if (multiCursorEvent(e, QKeySequence::SelectStartOfBlock)) {
op = QTextCursor::StartOfBlock;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectEndOfBlock) {
} else if (multiCursorEvent(e, QKeySequence::SelectEndOfBlock)) {
op = QTextCursor::EndOfBlock;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectStartOfDocument) {

View File

@@ -108,7 +108,10 @@ public:
const_iterator constBegin() const { return m_cursorMap.cbegin(); }
const_iterator constEnd() const { return m_cursorMap.cend(); }
static bool multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey);
static bool multiCursorEvent(
QKeyEvent *e,
QKeySequence::StandardKey matchKey,
Qt::KeyboardModifiers additionalFilterModifier = {});
private:
std::list<QTextCursor> m_cursorList;

View File

@@ -20,10 +20,10 @@ namespace Android::Internal::AndroidAvdManager {
static Q_LOGGING_CATEGORY(avdManagerLog, "qtc.android.avdManager", QtWarningMsg)
QString startAvd(const QString &name)
QString startAvd(const QString &name, const std::optional<QFuture<void>> &future)
{
if (!findAvd(name).isEmpty() || startAvdAsync(name))
return waitForAvd(name);
return waitForAvd(name, future);
return {};
}

View File

@@ -8,7 +8,7 @@
namespace Android::Internal::AndroidAvdManager {
QString startAvd(const QString &name);
QString startAvd(const QString &name, const std::optional<QFuture<void>> &future = {});
bool startAvdAsync(const QString &avdName);
QString findAvd(const QString &avdName);
QString waitForAvd(const QString &avdName, const std::optional<QFuture<void>> &future = {});

View File

@@ -111,15 +111,14 @@ static void startAvd(const IDevice::Ptr &device, QWidget *parent)
const AndroidDevice *androidDev = static_cast<const AndroidDevice *>(device.get());
const QString name = androidDev->avdName();
qCDebug(androidDeviceLog, "Starting Android AVD id \"%s\".", qPrintable(name));
auto future = Utils::asyncRun([name, device] {
const QString serialNumber = AndroidAvdManager::startAvd(name);
Utils::futureSynchronizer()->addFuture(Utils::asyncRun([name, device](QPromise<void> &promise) {
const QString serialNumber = AndroidAvdManager::startAvd(name, promise.future());
// Mark the AVD as ReadyToUse once we know it's started
if (!serialNumber.isEmpty()) {
DeviceManager *const devMgr = DeviceManager::instance();
devMgr->setDeviceState(device->id(), IDevice::DeviceReadyToUse);
}
});
// TODO: use future!
}));
}
static void setEmulatorArguments(QWidget *parent)

View File

@@ -29,43 +29,15 @@ DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic, TextDocument *docum
: TextMark(document, diagnostic.location.line, clangToolsCategory())
, m_diagnostic(diagnostic)
{
setSettingsPage(Constants::SETTINGS_PAGE_ID);
const bool isError = diagnostic.type == "error" || diagnostic.type == "fatal";
setColor(isError ? Theme::CodeModel_Error_TextMarkColor : Theme::CodeModel_Warning_TextMarkColor);
setPriority(isError ? TextEditor::TextMark::HighPriority : TextEditor::TextMark::NormalPriority);
QIcon markIcon = diagnostic.icon();
setIcon(markIcon.isNull() ? Icons::CODEMODEL_WARNING.icon() : markIcon);
setToolTip(createDiagnosticToolTipString(diagnostic, std::nullopt, true));
setLineAnnotation(diagnostic.description);
setActionsProvider([diagnostic] {
// Copy to clipboard action
QList<QAction *> actions;
QAction *action = new QAction();
action->setIcon(Icon::fromTheme("edit-copy"));
action->setToolTip(Tr::tr("Copy to Clipboard"));
QObject::connect(action, &QAction::triggered, [diagnostic] {
const QString text = createFullLocationString(diagnostic.location)
+ ": "
+ diagnostic.description;
setClipboardAndSelection(text);
});
actions << action;
// Disable diagnostic action
action = new QAction();
action->setIcon(Icons::BROKEN.icon());
action->setToolTip(Tr::tr("Disable Diagnostic"));
QObject::connect(action, &QAction::triggered, [diagnostic] { disableChecks({diagnostic}); });
actions << action;
return actions;
});
initialize();
}
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
: TextMark(diagnostic.location.filePath, diagnostic.location.line, clangToolsCategory())
, m_diagnostic(diagnostic)
{}
{
initialize();
}
void DiagnosticMark::disable()
{
@@ -89,6 +61,41 @@ Diagnostic DiagnosticMark::diagnostic() const
return m_diagnostic;
}
void DiagnosticMark::initialize()
{
setSettingsPage(Constants::SETTINGS_PAGE_ID);
const bool isError = m_diagnostic.type == "error" || m_diagnostic.type == "fatal";
setColor(isError ? Theme::CodeModel_Error_TextMarkColor : Theme::CodeModel_Warning_TextMarkColor);
setPriority(isError ? TextEditor::TextMark::HighPriority : TextEditor::TextMark::NormalPriority);
QIcon markIcon = m_diagnostic.icon();
setIcon(markIcon.isNull() ? Icons::CODEMODEL_WARNING.icon() : markIcon);
setToolTip(createDiagnosticToolTipString(m_diagnostic, std::nullopt, true));
setLineAnnotation(m_diagnostic.description);
setActionsProvider([diagnostic = m_diagnostic] {
// Copy to clipboard action
QList<QAction *> actions;
QAction *action = new QAction();
action->setIcon(Icon::fromTheme("edit-copy"));
action->setToolTip(Tr::tr("Copy to Clipboard"));
QObject::connect(action, &QAction::triggered, [diagnostic] {
const QString text = createFullLocationString(diagnostic.location)
+ ": "
+ diagnostic.description;
setClipboardAndSelection(text);
});
actions << action;
// Disable diagnostic action
action = new QAction();
action->setIcon(Icons::BROKEN.icon());
action->setToolTip(Tr::tr("Disable Diagnostic"));
QObject::connect(action, &QAction::triggered, [diagnostic] { disableChecks({diagnostic}); });
actions << action;
return actions;
});
}
} // namespace Internal
} // namespace ClangTools

View File

@@ -25,6 +25,7 @@ public:
std::optional<CppEditor::ClangToolType> toolType;
private:
void initialize();
const Diagnostic m_diagnostic;
bool m_enabled = true;
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

After

Width:  |  Height:  |  Size: 540 B

View File

@@ -214,21 +214,13 @@ void RichTextDelegate::paint(QPainter *painter,
m_doc.setHtml(options.text);
m_doc.setTextWidth(options.rect.width());
options.text = "";
options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget);
painter->translate(options.rect.left(), options.rect.top());
QRect clip(0, 0, options.rect.width(), options.rect.height());
QAbstractTextDocumentLayout::PaintContext paintContext;
paintContext.palette = options.palette;
painter->setClipRect(clip);
paintContext.clip = clip;
if (qobject_cast<const QAbstractItemView *>(options.widget)->selectionModel()->isSelected(index)) {
QAbstractTextDocumentLayout::Selection selection;
selection.cursor = QTextCursor(&m_doc);
selection.cursor.select(QTextCursor::Document);
selection.format.setBackground(options.palette.brush(QPalette::Highlight));
selection.format.setForeground(options.palette.brush(QPalette::HighlightedText));
paintContext.selections << selection;
}
m_doc.documentLayout()->draw(painter, paintContext);
painter->restore();
}

View File

@@ -349,9 +349,8 @@ void ModeManager::currentTabChanged(int index)
if (!mode)
return;
// FIXME: This hardcoded context update is required for the Debug and Edit modes, since
// they use the editor widget, which is already a context widget so the main window won't
// go further up the parent tree to find the mode context.
// Set the mode's context regardless of focus widget.
// Whenever a mode is active, it's Context is active.
ICore::updateAdditionalContexts(d->m_addedContexts, mode->context());
d->m_addedContexts = mode->context();

View File

@@ -19,10 +19,12 @@
namespace Cppcheck::Internal {
ManualRunDialog::ManualRunDialog(const ProjectExplorer::Project *project)
ManualRunDialog::ManualRunDialog(const ProjectExplorer::Project *project,
CppcheckSettings *settings)
: m_model(new ProjectExplorer::SelectableFilesFromDirModel(this))
{
QTC_ASSERT(project, return );
QTC_ASSERT(settings, return);
setWindowTitle(Tr::tr("Cppcheck Run Configuration"));
@@ -52,9 +54,7 @@ ManualRunDialog::ManualRunDialog(const ProjectExplorer::Project *project)
analyzeButton->setEnabled(m_model->hasCheckedFiles());
});
m_manualRunSettings.readSettings();
m_manualRunSettings.setAutoApply(true);
auto optionsWidget = m_manualRunSettings.layouter()().emerge();
auto optionsWidget = settings->layouter()().emerge();
auto layout = new QVBoxLayout(this);
layout->addWidget(optionsWidget);

View File

@@ -3,8 +3,6 @@
#pragma once
#include "cppchecksettings.h"
#include <QDialog>
namespace Utils {
@@ -19,18 +17,18 @@ class SelectableFilesFromDirModel;
namespace Cppcheck::Internal {
class CppcheckSettings;
class ManualRunDialog : public QDialog
{
public:
explicit ManualRunDialog(const ProjectExplorer::Project *project);
explicit ManualRunDialog(const ProjectExplorer::Project *project, CppcheckSettings *settings);
Utils::FilePaths filePaths() const;
QSize sizeHint() const override;
const CppcheckSettings &manualRunSettings() const { return m_manualRunSettings; }
private:
ProjectExplorer::SelectableFilesFromDirModel *m_model;
CppcheckSettings m_manualRunSettings;
};
} // Cppcheck::Internal

View File

@@ -40,6 +40,7 @@ class CppcheckPluginPrivate final : public QObject
{
public:
explicit CppcheckPluginPrivate();
~CppcheckPluginPrivate();
CppcheckTextMarkManager marks;
CppcheckTool tool{marks, Constants::CHECK_PROGRESS_ID};
@@ -49,9 +50,12 @@ public:
Utils::Perspective perspective{Constants::PERSPECTIVE_ID, ::Cppcheck::Tr::tr("Cppcheck")};
Action *manualRunAction = nullptr;
QHash<Project *, CppcheckSettings *> projectSettings;
void startManualRun();
void updateManualRunAction();
void saveProjectSettings(Project *project);
void loadProjectSettings(Project *project);
};
CppcheckPluginPrivate::CppcheckPluginPrivate()
@@ -104,6 +108,29 @@ CppcheckPluginPrivate::CppcheckPluginPrivate()
action, &QAction::setEnabled);
perspective.addToolBarAction(action);
}
connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged,
this, [this](Project *project) {
if (!project)
return;
CppcheckSettings *settings = projectSettings.value(project, nullptr);
if (!settings) {
settings = new CppcheckSettings;
settings->readSettings();
settings->setAutoApply(true);
connect(project, &Project::aboutToSaveSettings,
this, [this, project]{ saveProjectSettings(project); });
connect(project, &Project::settingsLoaded,
this, [this, project]{ loadProjectSettings(project); });
projectSettings.insert(project, settings);
loadProjectSettings(project);
}
});
}
CppcheckPluginPrivate::~CppcheckPluginPrivate()
{
qDeleteAll(projectSettings);
projectSettings.clear();
}
void CppcheckPluginPrivate::startManualRun()
@@ -112,7 +139,9 @@ void CppcheckPluginPrivate::startManualRun()
if (!project)
return;
ManualRunDialog dialog(project);
CppcheckSettings *settings = projectSettings.value(project, nullptr);
QTC_ASSERT(settings, return);
ManualRunDialog dialog(project, settings);
if (dialog.exec() == ManualRunDialog::Rejected)
return;
@@ -123,7 +152,7 @@ void CppcheckPluginPrivate::startManualRun()
return;
manualRunTool.setProject(project);
manualRunTool.updateOptions(dialog.manualRunSettings());
manualRunTool.updateOptions(*settings);
manualRunTool.check(files);
perspective.select();
}
@@ -138,6 +167,30 @@ void CppcheckPluginPrivate::updateManualRunAction()
manualRunAction->setEnabled(canRun);
}
void CppcheckPluginPrivate::saveProjectSettings(Project *project)
{
QTC_ASSERT(project, return);
CppcheckSettings *settings = projectSettings.value(project, nullptr);
QTC_ASSERT(settings, return);
Store store;
settings->toMap(store);
project->setNamedSettings("CppcheckManual", Utils::variantFromStore(store));
}
void CppcheckPluginPrivate::loadProjectSettings(Project *project)
{
QTC_ASSERT(project, return);
CppcheckSettings *settings = projectSettings.value(project, nullptr);
QTC_ASSERT(settings, return);
const QVariant variant = project->namedSettings("CppcheckManual");
if (!variant.isValid())
return;
Store store = Utils::storeFromVariant(project->namedSettings("CppcheckManual"));
settings->fromMap(store);
}
class CppcheckPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT

View File

@@ -5,6 +5,8 @@ add_qtc_plugin(ExtensionManager
extensionmanagerconstants.h
extensionmanagerplugin.cpp
extensionmanagertr.h
extensionmanagersettings.cpp
extensionmanagersettings.h
extensionmanagerwidget.cpp
extensionmanagerwidget.h
extensionsbrowser.cpp

View File

@@ -13,6 +13,8 @@ QtcPlugin {
"extensionmanagerconstants.h",
"extensionmanagerplugin.cpp",
"extensionmanagertr.h",
"extensionmanagersettings.cpp",
"extensionmanagersettings.h",
"extensionmanagerwidget.cpp",
"extensionmanagerwidget.h",
"extensionsbrowser.cpp",

View File

@@ -0,0 +1,59 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "extensionmanagersettings.h"
#include "extensionmanagertr.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/dialogs/ioptionspage.h>
#include <utils/layoutbuilder.h>
namespace ExtensionManager::Internal {
ExtensionManagerSettings &settings()
{
static ExtensionManagerSettings theExtensionManagerSettings;
return theExtensionManagerSettings;
}
ExtensionManagerSettings::ExtensionManagerSettings()
{
setAutoApply(false);
setSettingsGroup("ExtensionManager");
externalRepoUrl.setDefaultValue("https://qc-extensions.qt.io");
externalRepoUrl.setReadOnly(true);
useExternalRepo.setSettingsKey("UseExternalRepo");
useExternalRepo.setLabelText(Tr::tr("Use external repository"));
useExternalRepo.setToolTip(Tr::tr("Repository: %1").arg(externalRepoUrl()));
useExternalRepo.setDefaultValue(false);
setLayouter([this] {
using namespace Layouting;
return Column {
useExternalRepo,
st
};
});
readSettings();
}
class ExtensionManagerSettingsPage : public Core::IOptionsPage
{
public:
ExtensionManagerSettingsPage()
{
setId("ExtensionManager");
setDisplayName(Tr::tr("Extensions"));
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
setSettingsProvider([] { return &settings(); });
}
};
const ExtensionManagerSettingsPage settingsPage;
} // ExtensionManager::Internal

View File

@@ -0,0 +1,21 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <utils/aspects.h>
namespace ExtensionManager::Internal {
class ExtensionManagerSettings final : public Utils::AspectContainer
{
public:
ExtensionManagerSettings();
Utils::StringAspect externalRepoUrl{this};
Utils::BoolAspect useExternalRepo{this};
};
ExtensionManagerSettings &settings();
} // ExtensionManager::Internal

View File

@@ -5,7 +5,7 @@
#include "extensionmanagertr.h"
#include "extensionsmodel.h"
#include "utils/hostosinfo.h"
#include "extensionmanagersettings.h"
#ifdef WITH_TESTS
#include "extensionmanager_test.h"
@@ -29,6 +29,7 @@
#include <utils/elidinglabel.h>
#include <utils/fancylineedit.h>
#include <utils/hostosinfo.h>
#include <utils/icon.h>
#include <utils/layoutbuilder.h>
#include <utils/networkaccessmanager.h>
@@ -399,14 +400,18 @@ void ExtensionsBrowser::fetchExtensions()
// d->model->setExtensionsJson(testData("defaultpacks")); return;
#endif // WITH_TESTS
if (!settings().useExternalRepo()) {
d->model->setExtensionsJson({});
return;
}
using namespace Tasking;
const auto onQuerySetup = [this](NetworkQuery &query) {
const QString host = "https://qc-extensions.qt.io";
const QString url = "%1/api/v1/search?request=";
const QString requestTemplate
= R"({"version":"%1","host_os":"%2","host_os_version":"%3","host_architecture":"%4","page_size":200})";
const QString request = url.arg(host) + requestTemplate
const QString request = url.arg(settings().externalRepoUrl()) + requestTemplate
.arg(QCoreApplication::applicationVersion())
.arg(osTypeToString(HostOsInfo::hostOs()))
.arg(QSysInfo::productVersion())
@@ -444,6 +449,7 @@ QLabel *tfLabel(const TextFormat &tf, bool singleLine)
label->setFixedHeight(tf.lineHeight());
label->setFont(tf.font());
label->setAlignment(Qt::Alignment(tf.drawTextFlags));
label->setTextInteractionFlags(Qt::TextSelectableByMouse);
QPalette pal = label->palette();
pal.setColor(QPalette::WindowText, tf.color());

View File

@@ -66,10 +66,14 @@ protected:
return QVariant::fromValue(
Link(m_client->serverUriToHostPath(m_item.uri()), start.line() + 1, start.character()));
}
case AnnotationRole:
case AnnotationRole: {
QStringList result;
if (const std::optional<QString> detail = m_item.detail())
return *detail;
return {};
result << *detail;
if (childCount() > 0)
result << QString("[%1]").arg(childCount());
return result.isEmpty() ? QVariant() : QVariant(result.join(' '));
}
default:
return TreeItem::data(column, role);
}

View File

@@ -1,4 +1,4 @@
---@meta Layout
---@meta Gui
local gui = {}

View File

@@ -37,6 +37,7 @@ public:
Utils::ProcessResultData resultData() const;
static QString transferMethodName(FileTransferMethod method);
QString transferMethodName() const { return transferMethodName(transferMethod()); }
signals:
void progress(const QString &progressMessage);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 B

After

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 B

After

Width:  |  Height:  |  Size: 594 B

View File

@@ -572,14 +572,15 @@ static QStringList environmentTemplatesPaths()
}
static bool s_searchPathsInitialized = false;
Q_GLOBAL_STATIC(FilePath, s_installedWizardsPath, {Core::ICore::resourcePath(WIZARD_PATH)})
Q_GLOBAL_STATIC(FilePaths, s_additionalWizardPaths)
FilePaths &JsonWizardFactory::searchPaths()
{
static FilePaths m_searchPaths;
if (!s_searchPathsInitialized) {
s_searchPathsInitialized = true;
m_searchPaths = {Core::ICore::userResourcePath(WIZARD_PATH),
Core::ICore::resourcePath(WIZARD_PATH)};
m_searchPaths = {Core::ICore::userResourcePath(WIZARD_PATH), *s_installedWizardsPath};
for (const QString &environmentTemplateDirName : environmentTemplatesPaths())
m_searchPaths << FilePath::fromString(environmentTemplateDirName);
m_searchPaths << Utils::transform(
@@ -598,6 +599,7 @@ FilePaths &JsonWizardFactory::searchPaths()
}
}
}
m_searchPaths += *s_additionalWizardPaths;
}
return m_searchPaths;
@@ -610,12 +612,16 @@ void JsonWizardFactory::resetSearchPaths()
void JsonWizardFactory::addWizardPath(const FilePath &path)
{
searchPaths().append(path);
s_additionalWizardPaths->append(path);
}
void JsonWizardFactory::clearWizardPaths()
/*!
\internal
*/
void JsonWizardFactory::setInstalledWizardsPath(const Utils::FilePath &path)
{
searchPaths().clear();
*s_installedWizardsPath = path;
resetSearchPaths();
}
void JsonWizardFactory::setVerbose(int level)

View File

@@ -27,7 +27,6 @@ class PROJECTEXPLORER_EXPORT JsonWizardFactory : public Core::IWizardFactory
public:
// Add search paths for wizard.json files. All subdirs are going to be checked.
static void addWizardPath(const Utils::FilePath &path);
static void clearWizardPaths();
// actual interface of the wizard factory:
class Generator {
@@ -59,6 +58,9 @@ public:
virtual std::pair<int, QStringList> screenSizeInfoFromPage(const QString &pageType) const;
// internal
static void setInstalledWizardsPath(const Utils::FilePath &path);
private:
Utils::Wizard *runWizardImpl(const Utils::FilePath &path, QWidget *parent, Utils::Id platform,
const QVariantMap &variables, bool showWizard = true) override;

View File

@@ -161,14 +161,10 @@ void ExampleSetModel::recreateModel(const QtVersions &qtVersionsIn)
// Sort by Qt version, example sets not associated to Qt last
Utils::sort(items, [](QStandardItem *a, QStandardItem *b) {
const QVersionNumber versionB = b->data(kVersionRole).value<QVersionNumber>();
if (versionB.isNull())
return true;
const QVersionNumber versionA = a->data(kVersionRole).value<QVersionNumber>();
if (versionA.isNull())
return false;
if (versionA == versionB)
return a->data(Qt::DisplayRole).toString() < b->data(Qt::DisplayRole).toString();
return versionA < versionB;
if (versionA != versionB)
return versionA < versionB;
return a->data(Qt::DisplayRole).toString() < b->data(Qt::DisplayRole).toString();
});
for (QStandardItem *item : std::as_const(items))

View File

@@ -176,12 +176,16 @@ GroupItem GenericDeployStep::transferTask(const Storage<FilesToTransfer> &storag
const auto onError = [this](const FileTransfer &transfer) {
const ProcessResultData result = transfer.resultData();
if (result.m_error == QProcess::FailedToStart) {
addErrorMessage(Tr::tr("rsync failed to start: %1").arg(result.m_errorString));
addErrorMessage(Tr::tr("%1 failed to start: %2")
.arg(transfer.transferMethodName(), result.m_errorString));
} else if (result.m_exitStatus == QProcess::CrashExit) {
addErrorMessage(Tr::tr("rsync crashed."));
addErrorMessage(Tr::tr("%1 crashed.").arg(transfer.transferMethodName()));
} else if (result.m_exitCode != 0) {
addErrorMessage(Tr::tr("rsync failed with exit code %1.").arg(result.m_exitCode)
+ "\n" + result.m_errorString);
addErrorMessage(
Tr::tr("%1 failed with exit code %2.")
.arg(transfer.transferMethodName())
.arg(result.m_exitCode)
+ "\n" + result.m_errorString);
}
};
return FileTransferTask(onSetup, onError, CallDoneIf::Error);

View File

@@ -27,11 +27,6 @@ using namespace Utils;
namespace RemoteLinux {
namespace Internal {
struct TransferStorage
{
bool useGenericCopy = false;
};
class GenericLinuxDeviceTesterPrivate
{
public:
@@ -43,8 +38,7 @@ public:
GroupItem echoTask(const QString &contents) const;
GroupItem unameTask() const;
GroupItem gathererTask() const;
GroupItem transferTask(FileTransferMethod method,
const Storage<TransferStorage> &storage) const;
GroupItem transferTask(FileTransferMethod method) const;
GroupItem transferTasks() const;
GroupItem commandTasks() const;
@@ -192,8 +186,7 @@ GroupItem GenericLinuxDeviceTesterPrivate::gathererTask() const
};
}
GroupItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method,
const Storage<TransferStorage> &storage) const
GroupItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method) const
{
const auto onSetup = [this, method](FileTransfer &transfer) {
emit q->progressMessage(Tr::tr("Checking whether \"%1\" works...")
@@ -201,7 +194,7 @@ GroupItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod metho
transfer.setTransferMethod(method);
transfer.setTestDevice(m_device);
};
const auto onDone = [this, method, storage](const FileTransfer &transfer, DoneWith result) {
const auto onDone = [this, method](const FileTransfer &transfer, DoneWith result) {
const QString methodName = FileTransfer::transferMethodName(method);
if (result == DoneWith::Success) {
emit q->progressMessage(Tr::tr("\"%1\" is functional.\n").arg(methodName));
@@ -209,8 +202,6 @@ GroupItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod metho
m_device->setExtraData(Constants::SUPPORTS_RSYNC, true);
else if (method == FileTransferMethod::Sftp)
m_device->setExtraData(Constants::SUPPORTS_SFTP, true);
else
storage->useGenericCopy = true;
return;
}
const ProcessResultData resultData = transfer.resultData();
@@ -251,13 +242,11 @@ GroupItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod metho
GroupItem GenericLinuxDeviceTesterPrivate::transferTasks() const
{
Storage<TransferStorage> storage;
return Group {
continueOnSuccess,
storage,
transferTask(FileTransferMethod::GenericCopy, storage),
transferTask(FileTransferMethod::Sftp, storage),
transferTask(FileTransferMethod::Rsync, storage),
transferTask(FileTransferMethod::GenericCopy),
transferTask(FileTransferMethod::Sftp),
transferTask(FileTransferMethod::Rsync),
onGroupDone([this] {
emit q->errorMessage(Tr::tr("Deployment to this device will not work out of the box.")
+ "\n");

View File

@@ -609,8 +609,7 @@ void StudioWelcomePlugin::extensionsInitialized()
// Enable QDS new project dialog and QDS wizards
if (Core::ICore::isQtDesignStudio()) {
ProjectExplorer::JsonWizardFactory::clearWizardPaths();
ProjectExplorer::JsonWizardFactory::addWizardPath(
ProjectExplorer::JsonWizardFactory::setInstalledWizardsPath(
Core::ICore::resourcePath("qmldesigner/studio_templates"));
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });

View File

@@ -3087,15 +3087,21 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
if (ro || !isPrintableText(eventText)) {
QTextCursor::MoveOperation blockSelectionOperation = QTextCursor::NoMove;
if (e->modifiers() == (Qt::AltModifier | Qt::ShiftModifier) && !Utils::HostOsInfo::isMacHost()) {
if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToNextLine))
if (e->modifiers() == (Qt::AltModifier | Qt::ShiftModifier)
&& !Utils::HostOsInfo::isMacHost()) {
if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToNextLine, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::Down;
else if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToPreviousLine))
} else if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToPreviousLine, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::Up;
else if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToNextChar))
} else if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToNextChar, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::NextCharacter;
else if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToPreviousChar))
} else if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToPreviousChar, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::PreviousCharacter;
}
}
if (blockSelectionOperation != QTextCursor::NoMove) {
@@ -7431,6 +7437,25 @@ void TextEditorWidgetPrivate::handleBackspaceKey()
QTC_ASSERT(!q->multiTextCursor().hasSelection(), return);
MultiTextCursor cursor = m_cursors;
cursor.beginEditBlock();
const TabSettings tabSettings = m_document->tabSettings();
const TypingSettings &typingSettings = m_document->typingSettings();
auto behavior = typingSettings.m_smartBackspaceBehavior;
if (cursor.hasMultipleCursors()) {
if (behavior == TypingSettings::BackspaceFollowsPreviousIndents) {
behavior = TypingSettings::BackspaceNeverIndents;
} else if (behavior == TypingSettings::BackspaceUnindents) {
for (QTextCursor &c : cursor) {
if (c.positionInBlock() == 0
|| c.positionInBlock() > TabSettings::firstNonSpace(c.block().text())) {
behavior = TypingSettings::BackspaceNeverIndents;
break;
}
}
}
}
for (QTextCursor &c : cursor) {
const int pos = c.position();
if (!pos)
@@ -7443,9 +7468,6 @@ void TextEditorWidgetPrivate::handleBackspaceKey()
cursorWithinSnippet = snippetCheckCursor(snippetCursor);
}
const TabSettings tabSettings = m_document->tabSettings();
const TypingSettings &typingSettings = m_document->typingSettings();
if (typingSettings.m_autoIndent && !m_autoCompleteHighlightPos.isEmpty()
&& (m_autoCompleteHighlightPos.last() == c) && m_removeAutoCompletedText
&& m_autoCompleter->autoBackspace(c)) {
@@ -7453,12 +7475,12 @@ void TextEditorWidgetPrivate::handleBackspaceKey()
}
bool handled = false;
if (typingSettings.m_smartBackspaceBehavior == TypingSettings::BackspaceNeverIndents) {
if (behavior == TypingSettings::BackspaceNeverIndents) {
if (cursorWithinSnippet)
c.beginEditBlock();
c.deletePreviousChar();
handled = true;
} else if (typingSettings.m_smartBackspaceBehavior
} else if (behavior
== TypingSettings::BackspaceFollowsPreviousIndents) {
QTextBlock currentBlock = c.block();
int positionInBlock = pos - currentBlock.position();
@@ -7493,7 +7515,7 @@ void TextEditorWidgetPrivate::handleBackspaceKey()
}
}
}
} else if (typingSettings.m_smartBackspaceBehavior == TypingSettings::BackspaceUnindents) {
} else if (behavior == TypingSettings::BackspaceUnindents) {
if (c.positionInBlock() == 0
|| c.positionInBlock() > TabSettings::firstNonSpace(c.block().text())) {
if (cursorWithinSnippet)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 B

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

After

Width:  |  Height:  |  Size: 273 B

View File

@@ -8727,17 +8727,10 @@
width="100%"
height="100%"
style="stroke-width:0.88039" />
<g
id="g34266"
style="stroke:#000000;stroke-linecap:round;stroke-linejoin:round;fill:none">
<path
id="path34132"
d="M 51,54 V 64 H 65 V 54 m -16,-2 9,-6 9,6"
style="stroke-width:2" />
<path
id="path34224"
d="m 60.5,58.5 h 1 v 1 h -1 z m 0,-3 h 1 v 1 h -1 z m -3,3 h 1 v 1 h -1 z m 0,-3 h 1 v 1 h -1 z m -3,3 h 1 v 1 h -1 z m 0,-3 h 1 v 1 h -1 z" />
</g>
<path
id="path4"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linejoin:round"
d="m 55,64 v -7 h 6 v 7 M 50,52.5 V 64 H 66 V 52.5 l -8,-6 z" />
</g>
<g
transform="translate(-55,264)"
@@ -8757,6 +8750,20 @@
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round"
d="m 100,63 h 16 m -16,-4 h 12 m -12,-4 h 16 m -16,-4 h 12 m -12,-4 h 16" />
</g>
<g
id="mode_design_pen">
<rect
style="fill:#ffffff"
id="rect17"
width="13"
height="21"
x="83"
y="280" />
<path
id="path47960"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
d="M 91,290.5 A 1.5,1.5 0 0 1 89.5,292 1.5,1.5 0 0 1 88,290.5 1.5,1.5 0 0 1 89.5,289 1.5,1.5 0 0 1 91,290.5 Z M 89.5,281 v 8 m -3.5,6 c 7,0 7,0 7,0 m -4.5,-14 h 2 l 4,10 -1.5,4 1.5,3 h -10 l 1.5,-3 -1.5,-4 z" />
</g>
<g
transform="translate(-69,264)"
style="display:inline"
@@ -8770,16 +8777,12 @@
id="use5913-0"
width="100%"
height="100%" />
<g
id="g49500"
inkscape:transform-center-y="0.70710678"
transform="rotate(-45,157.5,54.5)"
inkscape:transform-center-x="-0.70710678">
<path
id="path47960"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
d="M 159,54.5 A 1.5,1.5 0 0 1 157.5,56 1.5,1.5 0 0 1 156,54.5 1.5,1.5 0 0 1 157.5,53 1.5,1.5 0 0 1 159,54.5 Z M 157.5,45 v 8 m -3.5,6 c 7,0 7,0 7,0 m -4.5,-14 h 2 l 4,10 -1.5,4 1.5,3 h -10 l 1.5,-3 -1.5,-4 z" />
</g>
<use
x="0"
y="0"
xlink:href="#mode_design_pen"
id="use18"
transform="rotate(-135,75.244119,159.91674)" />
</g>
<g
transform="translate(-83,264)"
@@ -8809,6 +8812,14 @@
ry="5" />
</g>
</g>
<g
id="mode_project_wrench">
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linejoin:round"
d="m 159,277 v 5.5 l 0.5,0.5 h 3 l 0.5,-0.5 V 277 c 0.5,0 4.0272,1.45336 4,5.5 -0.0269,3.99991 -4,5.5 -4,5.5 v 9 c 0,1.5 -1,2 -2,2 -1,0 -2,-0.5 -2,-2 v -9 c 0,0 -3.99599,-1.5 -4,-5.5 -0.004,-4.12282 3.5,-5.5 4,-5.5 z"
id="path8"
sodipodi:nodetypes="ccccccscssscsc" />
</g>
<g
transform="translate(-97,264)"
style="display:inline"
@@ -8822,32 +8833,12 @@
id="use5913-0-8-3"
width="100%"
height="100%" />
<circle
style="fill:none;stroke:#000000;stroke-width:2"
id="path86372"
cx="258"
cy="55"
r="9" />
<g
id="g88204"
transform="rotate(45,258,55)">
<path
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round"
d="m 258,60.5 v -5"
id="path86584"
sodipodi:nodetypes="cc" />
<circle
style="fill:#000000"
id="path86725"
cx="258"
cy="52.5"
r="3.5" />
<path
style="fill:none;stroke:#ffffff"
d="M 258,52 V 48"
id="path87283"
sodipodi:nodetypes="cc" />
</g>
<use
x="0"
y="0"
xlink:href="#mode_project_wrench"
id="use17"
transform="rotate(45,489.04885,287.88225)" />
</g>
<g
transform="translate(-162,264)"
@@ -9063,6 +9054,31 @@
d="m 765,51 6,6 -6,7 z"
id="path34590" />
</g>
<g
id="build_hammer"
transform="translate(-667,327)">
<rect
style="fill:#ffffff"
id="rect11"
width="20"
height="22"
x="854"
y="47" />
<rect
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round"
id="rect8"
width="4"
height="15"
x="862"
y="53"
ry="1"
rx="1" />
<path
style="fill:none;stroke:#000000;stroke-width:2"
d="m 870,48 h -8.5 c -2,0 -4,3 -5,5 H 870 Z"
id="path11"
sodipodi:nodetypes="csccc" />
</g>
<g
transform="translate(-664,297)"
style="display:inline"
@@ -9076,18 +9092,12 @@
id="use5913-0-8-1-89"
width="100%"
height="100%" />
<g
id="g29289"
transform="rotate(30,861.61602,58.5)">
<path
id="path25494"
style="fill:#ffffff;stroke:#000000;stroke-width:4;stroke-linejoin:round;paint-order:markers stroke fill"
d="m 858,52 h 6 v -1 h -6 m 2,6 h 1 v 10 h -1 z" />
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round"
d="m 858,50 c -1.5,0 -3.5,1.5 -3.5,3 h 3.5"
id="path26814" />
</g>
<use
x="0"
y="0"
xlink:href="#build_hammer"
id="use20"
transform="rotate(45,922.51682,1023.5188)" />
</g>
<g
transform="translate(-247.5,256)"

Before

Width:  |  Height:  |  Size: 374 KiB

After

Width:  |  Height:  |  Size: 374 KiB