Merge remote-tracking branch 'origin/5.0'

Change-Id: I4236e3d2f87d56aea787905f4b78b1f5f933c069
This commit is contained in:
Eike Ziller
2021-08-03 14:19:44 +02:00
37 changed files with 406 additions and 226 deletions

View File

@@ -34,6 +34,7 @@ import StudioTheme 1.0 as StudioTheme
Item {
property var selectedAssets: ({})
property int allExpandedState: 0
property string delFilePath: ""
DropArea {
id: dropArea
@@ -83,14 +84,25 @@ Item {
StudioControls.MenuItem {
text: qsTr("Expand All")
enabled: allExpandedState !== 1
visible: !delFilePath
height: visible ? implicitHeight : 0
onTriggered: assetsModel.toggleExpandAll(true)
}
StudioControls.MenuItem {
text: qsTr("Collapse All")
enabled: allExpandedState !== 2
visible: !delFilePath
height: visible ? implicitHeight : 0
onTriggered: assetsModel.toggleExpandAll(false)
}
StudioControls.MenuItem {
text: qsTr("Delete File")
visible: delFilePath
height: visible ? implicitHeight : 0
onTriggered: assetsModel.removeFile(delFilePath)
}
}
}
@@ -121,6 +133,7 @@ Item {
dirExpanded = !dirExpanded
}
onShowContextMenu: {
delFilePath = ""
allExpandedState = assetsModel.getAllExpandedState()
contextMenu.popup()
}
@@ -173,6 +186,7 @@ Item {
readonly property string suffix: fileName.substr(-4)
readonly property bool isFont: suffix === ".ttf" || suffix === ".otf"
property bool currFileSelected: false
MouseArea {
id: mouseArea
@@ -190,7 +204,8 @@ Item {
var ctrlDown = mouse.modifiers & Qt.ControlModifier
if (!selectedAssets[filePath] && !ctrlDown)
selectedAssets = {}
selectedAssets[filePath] = true
currFileSelected = ctrlDown ? !selectedAssets[filePath] : true
selectedAssets[filePath] = currFileSelected
selectedAssetsChanged()
var selectedAssetsArr = []
@@ -199,9 +214,12 @@ Item {
selectedAssetsArr.push(assetPath)
}
rootView.startDragAsset(selectedAssetsArr, mapToGlobal(mouse.x, mouse.y))
if (currFileSelected)
rootView.startDragAsset(selectedAssetsArr, mapToGlobal(mouse.x, mouse.y))
} else {
print("TODO: impl context menu")
delFilePath = filePath
tooltipBackend.hideTooltip()
contextMenu.popup()
}
}
@@ -209,13 +227,13 @@ Item {
if (mouse.button === Qt.LeftButton) {
if (!(mouse.modifiers & Qt.ControlModifier))
selectedAssets = {}
selectedAssets[filePath] = true
selectedAssets[filePath] = currFileSelected
selectedAssetsChanged()
}
}
ToolTip {
visible: !isFont && mouseArea.containsMouse
visible: !isFont && mouseArea.containsMouse && !contextMenu.visible
text: filePath
delay: 1000
}

View File

@@ -58,24 +58,18 @@ Section {
ExpandingSpacer {}
}
PropertyLabel { text: qsTr("Alignment") }
PropertyLabel { text: qsTr("Alignment H") }
SecondColumnLayout {
AligmentHorizontalButtons {
id: horizontalAlignmentButtons
backendValue: backendValues.%2_horizontalAlignment;
}
AlignmentHorizontalButtons {}
Spacer {
implicitWidth: StudioTheme.Values.controlGap
+ StudioTheme.Values.controlLabelWidth
+ StudioTheme.Values.controlGap
+ StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
- horizontalAlignmentButtons.implicitWidth
}
ExpandingSpacer {}
}
AligmentVerticalButtons {
PropertyLabel { text: qsTr("Alignment V") }
SecondColumnLayout {
AlignmentVerticalButtons {
backendValue: backendValues.%2_verticalAlignment;
}
}

View File

@@ -28,7 +28,6 @@ import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme
import "../QtQuick" as Q
Rectangle {
id: itemPane
@@ -49,7 +48,7 @@ Rectangle {
y: -1
width: itemPane.width
Q.ComponentSection {}
ComponentSection {}
Column {
anchors.left: parent.left

View File

@@ -29,8 +29,9 @@ import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Row {
id: alignmentHorizontalButtons
id: root
property string scope: "Text"
property bool blueHighlight: false
property variant backendValue: backendValues.horizontalAlignment
property variant value: backendValue.enumeration
@@ -42,6 +43,7 @@ Row {
buttonAlignLeft.checked = true
buttonAlignHCenter.checked = false
buttonAlignRight.checked = false
buttonAlignJustify.checked = false
if (value !== undefined) {
if (value === "AlignLeft")
@@ -50,6 +52,8 @@ Row {
buttonAlignHCenter.checked = true
else if (value === "AlignRight")
buttonAlignRight.checked = true
else if (value === "AlignJustify")
buttonAlignJustify.checked = true
}
evaluate()
}
@@ -75,7 +79,7 @@ Row {
ExtendedFunctionLogic {
id: extFuncLogic
backendValue: alignmentHorizontalButtons.backendValue
backendValue: root.backendValue
}
StudioControls.ButtonRow {
@@ -98,7 +102,7 @@ Row {
iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignLeft")
backendValue.setEnumeration(root.scope, "AlignLeft")
}
}
@@ -111,7 +115,7 @@ Row {
iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignHCenter")
backendValue.setEnumeration(root.scope, "AlignHCenter")
}
}
@@ -124,7 +128,20 @@ Row {
iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignRight")
backendValue.setEnumeration(root.scope, "AlignRight")
}
}
StudioControls.AbstractButton {
id: buttonAlignJustify
buttonIcon: StudioTheme.Constants.textAlignJustified
checkable: true
autoExclusive: true
StudioControls.ButtonGroup.group: group
iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration(root.scope, "AlignJustify")
}
}
}

View File

@@ -29,8 +29,9 @@ import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Row {
id: alignmentVerticalButtons
id: root
property string scope: "Text"
property bool blueHighlight: false
property variant backendValue: backendValues.verticalAlignment
property variant value: backendValue.enumeration
@@ -75,7 +76,7 @@ Row {
ExtendedFunctionLogic {
id: extFuncLogic
backendValue: alignmentVerticalButtons.backendValue
backendValue: root.backendValue
}
StudioControls.ButtonRow {
@@ -100,7 +101,7 @@ Row {
iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignTop")
backendValue.setEnumeration(root.scope, "AlignTop")
}
}
StudioControls.AbstractButton {
@@ -112,7 +113,7 @@ Row {
iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignVCenter")
backendValue.setEnumeration(root.scope, "AlignVCenter")
}
}
StudioControls.AbstractButton {
@@ -124,7 +125,7 @@ Row {
iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignBottom")
backendValue.setEnumeration(root.scope, "AlignBottom")
}
}
}

View File

@@ -277,22 +277,20 @@ Section {
enabled: !styleNameComboBox.styleSet
}
PropertyLabel { text: qsTr("Alignment") }
PropertyLabel { text: qsTr("Alignment H") }
SecondColumnLayout {
AligmentHorizontalButtons { id: horizontalAlignmentButtons }
AlignmentHorizontalButtons {}
Spacer {
visible: root.showVerticalAlignment
implicitWidth: StudioTheme.Values.controlGap
+ StudioTheme.Values.controlLabelWidth
+ StudioTheme.Values.controlGap
+ StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
- horizontalAlignmentButtons.implicitWidth
}
ExpandingSpacer {}
}
AligmentVerticalButtons { visible: root.showVerticalAlignment }
PropertyLabel { text: qsTr("Alignment V") }
SecondColumnLayout {
AlignmentVerticalButtons { visible: root.showVerticalAlignment }
ExpandingSpacer {}
}
PropertyLabel {

View File

@@ -29,7 +29,6 @@ import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import QtQuick.Templates 2.15 as T
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Section {
@@ -213,22 +212,24 @@ Section {
onActiveFocusChanged: annotationEdit.z = activeFocus ? 10 : 0
}
StudioControls.AbstractButton {
AbstractButton {
id: editAnnotationButton
buttonIcon: StudioTheme.Constants.edit
tooltip: qsTr("Edit annotation")
onClicked: annotationEditor.showWidget()
onHoveredChanged: annotationEditor.checkAux()
}
StudioControls.AbstractButton {
AbstractButton {
id: removeAnnotationButton
buttonIcon: StudioTheme.Constants.closeCross
tooltip: qsTr("Remove annotation")
onClicked: annotationEditor.removeFullAnnotation()
onHoveredChanged: annotationEditor.checkAux()
}
}
StudioControls.AbstractButton {
AbstractButton {
id: addAnnotationButton
implicitWidth: StudioTheme.Values.singleControlColumnWidth
width: StudioTheme.Values.singleControlColumnWidth

View File

@@ -30,6 +30,12 @@ import StudioTheme 1.0 as StudioTheme
ScrollBar {
id: scrollBar
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
property bool scrollBarVisible: parent.childrenRect.width > parent.width
orientation: Qt.Horizontal
@@ -40,6 +46,8 @@ ScrollBar {
- (parent.bothVisible ? parent.verticalThickness : 0)
padding: 0
minimumSize: orientation == Qt.Horizontal ? height / width : width / height
background: Rectangle {
color: StudioTheme.Values.themeScrollBarTrack
}

View File

@@ -181,22 +181,20 @@ Section {
ExpandingSpacer {}
}
PropertyLabel { text: qsTr("Alignment") }
PropertyLabel { text: qsTr("Alignment H") }
SecondColumnLayout {
AligmentHorizontalButtons { id: horizontalAlignmentButtons }
AlignmentHorizontalButtons {}
Spacer {
visible: root.showVerticalAlignment
implicitWidth: StudioTheme.Values.controlGap
+ StudioTheme.Values.controlLabelWidth
+ StudioTheme.Values.controlGap
+ StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
- horizontalAlignmentButtons.implicitWidth
}
ExpandingSpacer {}
}
AligmentVerticalButtons { visible: root.showVerticalAlignment }
PropertyLabel { text: qsTr("Alignment V") }
SecondColumnLayout {
AlignmentVerticalButtons { visible: root.showVerticalAlignment }
ExpandingSpacer {}
}
PropertyLabel {

View File

@@ -30,8 +30,15 @@ import StudioTheme 1.0 as StudioTheme
ScrollBar {
id: scrollBar
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
property bool scrollBarVisible: parent.childrenRect.height > parent.height
minimumSize: orientation == Qt.Horizontal ? height / width : width / height
orientation: Qt.Vertical
policy: scrollBar.scrollBarVisible ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
x: parent.width - width

View File

@@ -1,7 +1,7 @@
AbstractButton 2.0 AbstractButton.qml
ActionIndicator 2.0 ActionIndicator.qml
AligmentHorizontalButtons 2.0 AligmentHorizontalButtons.qml
AligmentVerticalButtons 2.0 AligmentVerticalButtons.qml
AlignmentHorizontalButtons 2.0 AlignmentHorizontalButtons.qml
AlignmentVerticalButtons 2.0 AlignmentVerticalButtons.qml
AnchorButtons 2.0 AnchorButtons.qml
BoolButtonRowButton 2.0 BoolButtonRowButton.qml
Button 2.0 Button.qml
@@ -16,6 +16,7 @@ ColorPalette 2.0 ColorPalette.qml
ColorPicker 2.0 ColorPicker.qml
ComboBox 2.0 ComboBox.qml
ComponentButton 2.0 ComponentButton.qml
ComponentSection 2.0 ComponentSection.qml
ControlLabel 2.0 ControlLabel.qml
singleton Controller 2.0 Controller.qml
DoubleSpinBox 2.0 DoubleSpinBox.qml

View File

@@ -126,43 +126,45 @@ QtObject {
readonly property string play: "\u0079"
readonly property string plus: "\u007A"
readonly property string promote: "\u007B"
readonly property string redo: "\u007C"
readonly property string rotationFill: "\u007D"
readonly property string rotationOutline: "\u007E"
readonly property string search: "\u007F"
readonly property string sectionToggle: "\u0080"
readonly property string splitColumns: "\u0081"
readonly property string splitRows: "\u0082"
readonly property string startNode: "\u0083"
readonly property string testIcon: "\u0084"
readonly property string textAlignBottom: "\u0085"
readonly property string textAlignCenter: "\u0086"
readonly property string textAlignLeft: "\u0087"
readonly property string textAlignMiddle: "\u0088"
readonly property string textAlignRight: "\u0089"
readonly property string textAlignTop: "\u008A"
readonly property string textBulletList: "\u008B"
readonly property string textFullJustification: "\u008C"
readonly property string textNumberedList: "\u008D"
readonly property string tickIcon: "\u008E"
readonly property string transparent: "\u008F"
readonly property string triState: "\u0090"
readonly property string triangleArcA: "\u0091"
readonly property string triangleArcB: "\u0092"
readonly property string triangleCornerA: "\u0093"
readonly property string triangleCornerB: "\u0094"
readonly property string unLinked: "\u0095"
readonly property string undo: "\u0096"
readonly property string unpin: "\u0097"
readonly property string upDownIcon: "\u0098"
readonly property string upDownSquare2: "\u0099"
readonly property string visibilityOff: "\u009A"
readonly property string visibilityOn: "\u009B"
readonly property string wildcard: "\u009C"
readonly property string zoomAll: "\u009D"
readonly property string zoomIn: "\u009E"
readonly property string zoomOut: "\u009F"
readonly property string zoomSelection: "\u00A0"
readonly property string readOnly: "\u007C"
readonly property string redo: "\u007D"
readonly property string rotationFill: "\u007E"
readonly property string rotationOutline: "\u007F"
readonly property string search: "\u0080"
readonly property string sectionToggle: "\u0081"
readonly property string splitColumns: "\u0082"
readonly property string splitRows: "\u0083"
readonly property string startNode: "\u0084"
readonly property string testIcon: "\u0085"
readonly property string textAlignBottom: "\u0086"
readonly property string textAlignCenter: "\u0087"
readonly property string textAlignJustified: "\u0088"
readonly property string textAlignLeft: "\u0089"
readonly property string textAlignMiddle: "\u008A"
readonly property string textAlignRight: "\u008B"
readonly property string textAlignTop: "\u008C"
readonly property string textBulletList: "\u008D"
readonly property string textFullJustification: "\u008E"
readonly property string textNumberedList: "\u008F"
readonly property string tickIcon: "\u0090"
readonly property string transparent: "\u0091"
readonly property string triState: "\u0092"
readonly property string triangleArcA: "\u0093"
readonly property string triangleArcB: "\u0094"
readonly property string triangleCornerA: "\u0095"
readonly property string triangleCornerB: "\u0096"
readonly property string unLinked: "\u0097"
readonly property string undo: "\u0098"
readonly property string unpin: "\u0099"
readonly property string upDownIcon: "\u009A"
readonly property string upDownSquare2: "\u009B"
readonly property string visibilityOff: "\u009C"
readonly property string visibilityOn: "\u009D"
readonly property string wildcard: "\u009E"
readonly property string zoomAll: "\u009F"
readonly property string zoomIn: "\u00A0"
readonly property string zoomOut: "\u00A1"
readonly property string zoomSelection: "\u00A2"
readonly property font iconFont: Qt.font({
"family": controlIcons.name,

View File

@@ -203,31 +203,6 @@ static inline int askMsgSendFailed()
QMessageBox::Retry);
}
// taken from utils/fileutils.cpp. We cannot use utils here since that depends app_version.h.
static bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath)
{
QFileInfo srcFileInfo(srcFilePath);
if (srcFileInfo.isDir()) {
QDir targetDir(tgtFilePath);
targetDir.cdUp();
if (!targetDir.mkdir(Utils::FilePath::fromString(tgtFilePath).fileName()))
return false;
QDir sourceDir(srcFilePath);
const QStringList fileNames = sourceDir.entryList
(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
for (const QString &fileName : fileNames) {
const QString newSrcFilePath = srcFilePath + '/' + fileName;
const QString newTgtFilePath = tgtFilePath + '/' + fileName;
if (!copyRecursively(newSrcFilePath, newTgtFilePath))
return false;
}
} else {
if (!QFile::copy(srcFilePath, tgtFilePath))
return false;
}
return true;
}
static inline QStringList getPluginPaths()
{
QStringList rc(QDir::cleanPath(QApplication::applicationDirPath()

View File

@@ -774,15 +774,15 @@ bool QtcProcess::readDataFromProcess(int timeoutS,
finished = waitForFinished(timeoutS > 0 ? timeoutS * 1000 : -1)
|| state() == QProcess::NotRunning;
// First check 'stdout'
if (d->m_process->bytesAvailable()) { // applies to readChannel() only
const QByteArray newStdOut = readAllStandardOutput();
if (!newStdOut.isEmpty()) {
hasData = true;
const QByteArray newStdOut = d->m_process->readAllStandardOutput();
if (stdOut)
stdOut->append(newStdOut);
}
// Check 'stderr' separately. This is a special handling
// for 'git pull' and the like which prints its progress on stderr.
const QByteArray newStdErr = d->m_process->readAllStandardError();
const QByteArray newStdErr = readAllStandardError();
if (!newStdErr.isEmpty()) {
hasData = true;
if (stdErr)

View File

@@ -682,6 +682,8 @@ public:
Private(ClangdClient *q, Project *project)
: q(q), settings(CppTools::ClangdProjectSettings(project).settings()) {}
void findUsages(TextEditor::TextDocument *document, const QTextCursor &cursor,
const QString &searchTerm, const Utils::optional<QString> &replacement);
void handleFindUsagesResult(quint64 key, const QList<Location> &locations);
static void handleRenameRequest(const SearchResult *search,
const ReplacementData &replacementData,
@@ -868,69 +870,31 @@ void ClangdClient::closeExtraFile(const Utils::FilePath &filePath)
void ClangdClient::findUsages(TextEditor::TextDocument *document, const QTextCursor &cursor,
const Utils::optional<QString> &replacement)
{
// TODO: This will be wrong for e.g. operators. Use a Symbol info request to get the real symbol string.
const QString searchTerm = d->searchTermFromCursor(cursor);
if (searchTerm.isEmpty())
// Quick check: Are we even on anything searchable?
if (d->searchTermFromCursor(cursor).isEmpty())
return;
ReferencesData refData;
refData.key = d->nextJobId++;
if (replacement) {
ReplacementData replacementData;
replacementData.oldSymbolName = searchTerm;
replacementData.newSymbolName = *replacement;
if (replacementData.newSymbolName.isEmpty())
replacementData.newSymbolName = replacementData.oldSymbolName;
refData.replacementData = replacementData;
}
refData.search = SearchResultWindow::instance()->startNewSearch(
tr("C++ Usages:"),
{},
searchTerm,
replacement ? SearchResultWindow::SearchAndReplace : SearchResultWindow::SearchOnly,
SearchResultWindow::PreserveCaseDisabled,
"CppEditor");
if (refData.categorize)
refData.search->setFilter(new CppTools::CppSearchResultFilter);
if (refData.replacementData) {
refData.search->setTextToReplace(refData.replacementData->newSymbolName);
const auto renameFilesCheckBox = new QCheckBox;
renameFilesCheckBox->setVisible(false);
refData.search->setAdditionalReplaceWidget(renameFilesCheckBox);
const auto renameHandler =
[search = refData.search](const QString &newSymbolName,
const QList<SearchResultItem> &checkedItems,
bool preserveCase) {
const auto replacementData = search->userData().value<ReplacementData>();
Private::handleRenameRequest(search, replacementData, newSymbolName, checkedItems,
preserveCase);
};
connect(refData.search, &SearchResult::replaceButtonClicked, renameHandler);
}
connect(refData.search, &SearchResult::activated, [](const SearchResultItem& item) {
Core::EditorManager::openEditorAtSearchResult(item);
});
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
d->runningFindUsages.insert(refData.key, refData);
const Utils::optional<MessageId> requestId = symbolSupport().findUsages(
document, cursor, [this, key = refData.key](const QList<Location> &locations) {
d->handleFindUsagesResult(key, locations);
});
if (!requestId) {
d->finishSearch(refData, false);
return;
}
connect(refData.search, &SearchResult::cancelled, this, [this, requestId, key = refData.key] {
const auto refData = d->runningFindUsages.find(key);
if (refData == d->runningFindUsages.end())
// Get the proper spelling of the search term from clang, so we can put it into the
// search widget.
const TextDocumentIdentifier docId(DocumentUri::fromFilePath(document->filePath()));
const TextDocumentPositionParams params(docId, Range(cursor).start());
SymbolInfoRequest symReq(params);
symReq.setResponseCallback([this, doc = QPointer(document), cursor, replacement]
(const SymbolInfoRequest::Response &response) {
if (!doc)
return;
cancelRequest(*requestId);
refData->canceled = true;
refData->search->disconnect(this);
d->finishSearch(*refData, true);
const auto result = response.result();
if (!result)
return;
const auto list = Utils::get_if<QList<SymbolDetails>>(&result.value());
if (!list || list->isEmpty())
return;
const SymbolDetails &sd = list->first();
if (sd.name().isEmpty())
return;
d->findUsages(doc.data(), cursor, sd.name(), replacement);
});
sendContent(symReq);
}
void ClangdClient::enableTesting() { d->isTesting = true; }
@@ -971,6 +935,71 @@ QVersionNumber ClangdClient::versionNumber() const
CppTools::ClangdSettings::Data ClangdClient::settingsData() const { return d->settings; }
void ClangdClient::Private::findUsages(TextEditor::TextDocument *document,
const QTextCursor &cursor, const QString &searchTerm,
const Utils::optional<QString> &replacement)
{
ReferencesData refData;
refData.key = nextJobId++;
if (replacement) {
ReplacementData replacementData;
replacementData.oldSymbolName = searchTerm;
replacementData.newSymbolName = *replacement;
if (replacementData.newSymbolName.isEmpty())
replacementData.newSymbolName = replacementData.oldSymbolName;
refData.replacementData = replacementData;
}
refData.search = SearchResultWindow::instance()->startNewSearch(
tr("C++ Usages:"),
{},
searchTerm,
replacement ? SearchResultWindow::SearchAndReplace : SearchResultWindow::SearchOnly,
SearchResultWindow::PreserveCaseDisabled,
"CppEditor");
if (refData.categorize)
refData.search->setFilter(new CppTools::CppSearchResultFilter);
if (refData.replacementData) {
refData.search->setTextToReplace(refData.replacementData->newSymbolName);
const auto renameFilesCheckBox = new QCheckBox;
renameFilesCheckBox->setVisible(false);
refData.search->setAdditionalReplaceWidget(renameFilesCheckBox);
const auto renameHandler =
[search = refData.search](const QString &newSymbolName,
const QList<SearchResultItem> &checkedItems,
bool preserveCase) {
const auto replacementData = search->userData().value<ReplacementData>();
Private::handleRenameRequest(search, replacementData, newSymbolName, checkedItems,
preserveCase);
};
connect(refData.search, &SearchResult::replaceButtonClicked, renameHandler);
}
connect(refData.search, &SearchResult::activated, [](const SearchResultItem& item) {
Core::EditorManager::openEditorAtSearchResult(item);
});
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
runningFindUsages.insert(refData.key, refData);
const Utils::optional<MessageId> requestId = q->symbolSupport().findUsages(
document, cursor, [this, key = refData.key](const QList<Location> &locations) {
handleFindUsagesResult(key, locations);
});
if (!requestId) {
finishSearch(refData, false);
return;
}
QObject::connect(refData.search, &SearchResult::cancelled, q, [this, requestId, key = refData.key] {
const auto refData = runningFindUsages.find(key);
if (refData == runningFindUsages.end())
return;
q->cancelRequest(*requestId);
refData->canceled = true;
refData->search->disconnect(q);
finishSearch(*refData, true);
});
}
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
{
const auto refData = runningFindUsages.find(key);
@@ -2217,7 +2246,7 @@ static void cleanupDisabledCode(TextEditor::HighlightingResults &results, QTextD
continue;
}
if (wasInDisabled && (it == results.end()
if (wasInDisabled && (it + 1 == results.end()
|| (it + 1)->textStyles.mainStyle != TextEditor::C_DISABLED_CODE)) {
// The #else or #endif that ends disabled code should not be disabled.
it = results.erase(it);

View File

@@ -358,9 +358,12 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
setPriority(isError ? TextEditor::TextMark::HighPriority
: TextEditor::TextMark::NormalPriority);
setIcon(isError ? Icons::CODEMODEL_ERROR.icon() : Icons::CODEMODEL_WARNING.icon());
setLineAnnotation(diagnostic.message());
setColor(isError ? Theme::CodeModel_Error_TextMarkColor
: Theme::CodeModel_Warning_TextMarkColor);
if (client->project()) {
setLineAnnotation(diagnostic.message());
setColor(isError ? Theme::CodeModel_Error_TextMarkColor
: Theme::CodeModel_Warning_TextMarkColor);
ClangDiagnosticManager::addTask(m_diagnostic);
}
// Copy to clipboard action
QVector<QAction *> actions;
@@ -387,8 +390,6 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
}
setActions(actions);
ClangDiagnosticManager::addTask(m_diagnostic);
}
bool ClangdTextMark::addToolTipContent(QLayout *target) const

View File

@@ -947,7 +947,7 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(k);
auto sdkLocation = bs->data(Android::Constants::SdkLocation).value<FilePath>();
if (qt->qtVersion() >= QtSupport::QtVersionNumber{6, 0, 0}) {
if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber{6, 0, 0}) {
initialArgs.append("-DQT_HOST_PATH:PATH=%{Qt:QT_HOST_PREFIX}");
initialArgs.append("-DANDROID_SDK_ROOT:PATH=" + sdkLocation.path());
} else {
@@ -956,7 +956,7 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
}
const IDevice::ConstPtr device = DeviceKitAspect::device(k);
if (device->osType() == Utils::OsTypeMac) {
if (device && device->osType() == Utils::OsTypeMac) {
if (isIos(k)) {
QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(k);
if (qt && qt->qtVersion().majorVersion >= 6) {

View File

@@ -110,7 +110,8 @@ void ExecuteFilter::accept(LocatorFilterEntry selection,
d.executable = value;
} else {
d.executable = value.left(pos);
d.arguments = value.right(value.length() - pos - 1);
d.arguments = Utils::globalMacroExpander()->expand(
value.right(value.length() - pos - 1));
}
if (m_process->state() != QProcess::NotRunning) {

View File

@@ -253,6 +253,8 @@ QuickFixOperationTest::QuickFixOperationTest(const QList<QuickFixTestDocument::P
// Check
QString result = testDocument->m_editorWidget->document()->toPlainText();
removeTrailingWhitespace(result);
QEXPECT_FAIL("escape string literal: raw string literal", "FIXME", Continue);
QEXPECT_FAIL("escape string literal: unescape adjacent literals", "FIXME", Continue);
if (!expectedFailMessage.isEmpty())
QEXPECT_FAIL("", expectedFailMessage.data(), Continue);
else if (result != testDocument->m_expectedSource) {
@@ -1750,6 +1752,26 @@ void CppEditorPlugin::test_quickfix_data()
<< CppQuickFixFactoryPtr(new ConvertToCamelCase(true))
<< _("void @WhAt_TODO_hErE();\n")
<< _("void WhAtTODOHErE();\n");
QTest::newRow("escape string literal: simple case")
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
<< _(R"(const char *str = @"àxyz";)")
<< _(R"(const char *str = "\xc3\xa0xyz";)");
QTest::newRow("escape string literal: simple case reverse")
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
<< _(R"(const char *str = @"\xc3\xa0xyz";)")
<< _(R"(const char *str = "àxyz";)");
QTest::newRow("escape string literal: raw string literal")
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
<< _(R"x(const char *str = @R"(àxyz)";)x")
<< _(R"x(const char *str = R"(\xc3\xa0xyz)";)x");
QTest::newRow("escape string literal: splitting required")
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
<< _(R"(const char *str = @"àf23бgб1";)")
<< _(R"(const char *str = "\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)");
QTest::newRow("escape string literal: unescape adjacent literals")
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
<< _(R"(const char *str = @"\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)")
<< _(R"(const char *str = "àf23бgб1";)");
}
void CppEditorPlugin::test_quickfix()

View File

@@ -7079,17 +7079,25 @@ private:
return false;
}
static QByteArray escapeString(const QByteArray &contents)
static QByteArrayList escapeString(const QByteArray &contents)
{
QByteArray newContents;
QByteArrayList newContents;
QByteArray chunk;
bool wasEscaped = false;
for (const quint8 c : contents) {
if (isascii(c) && isprint(c)) {
newContents += c;
} else {
newContents += QByteArray("\\x") +
QByteArray::number(c, 16).rightJustified(2, '0');
const bool needsEscape = !isascii(c) || !isprint(c);
if (!needsEscape && wasEscaped && std::isxdigit(c) && !chunk.isEmpty()) {
newContents << chunk;
chunk.clear();
}
if (needsEscape)
chunk += QByteArray("\\x") + QByteArray::number(c, 16).rightJustified(2, '0');
else
chunk += c;
wasEscaped = needsEscape;
}
if (!chunk.isEmpty())
newContents << chunk;
return newContents;
}
@@ -7154,25 +7162,35 @@ public:
QTC_ASSERT(stringLiteral, return);
const QByteArray oldContents(currentFile->tokenAt(stringLiteral->literal_token).
identifier->chars());
QByteArray newContents;
QByteArrayList newContents;
if (m_escape)
newContents = escapeString(oldContents);
else
newContents = unescapeString(oldContents);
newContents = {unescapeString(oldContents)};
if (oldContents != newContents) {
// Check UTF-8 byte array is correct or not.
QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
QScopedPointer<QTextDecoder> decoder(utf8codec->makeDecoder());
const QString str = decoder->toUnicode(newContents);
const QByteArray utf8buf = str.toUtf8();
if (utf8codec->canEncode(str) && newContents == utf8buf) {
ChangeSet changes;
changes.replace(startPos + 1, endPos - 1, str);
currentFile->setChangeSet(changes);
currentFile->apply();
}
if (newContents.isEmpty()
|| (newContents.size() == 1 && newContents.first() == oldContents)) {
return;
}
QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
QScopedPointer<QTextDecoder> decoder(utf8codec->makeDecoder());
ChangeSet changes;
bool replace = true;
for (const QByteArray &chunk : qAsConst(newContents)) {
const QString str = decoder->toUnicode(chunk);
const QByteArray utf8buf = str.toUtf8();
if (!utf8codec->canEncode(str) || chunk != utf8buf)
return;
if (replace)
changes.replace(startPos + 1, endPos - 1, str);
else
changes.insert(endPos, "\"" + str + "\"");
replace = false;
}
currentFile->setChangeSet(changes);
currentFile->apply();
}
private:

View File

@@ -210,7 +210,13 @@ void SemanticHighlighter::onHighlighterResultAvailable(int from, int to)
}
QTC_ASSERT(paren.pos != -1, continue);
paren.source = parenSource();
parentheses.second << paren;
static const auto posCmp = [](const Parenthesis &p1, const Parenthesis &p2) {
return p1.pos < p2.pos;
};
const auto it = std::lower_bound(parentheses.second.begin(), parentheses.second.end(),
paren, posCmp);
parentheses.second.insert(it, paren);
}
if (parentheses.first.isValid())
TextDocumentLayout::setParentheses(parentheses.first, parentheses.second);

View File

@@ -84,13 +84,26 @@ public:
}.attachTo(this);
}
void apply() final { m_group.apply(); m_group.writeSettings(ICore::settings()); }
void apply() final;
void finish() final { m_group.finish(); }
private:
AspectContainer &m_group = debuggerSettings()->page1;
};
void CommonOptionsPageWidget::apply()
{
const DebuggerSettings *s = debuggerSettings();
const bool originalPostMortem = s->registerForPostMortem->value();
const bool currentPostMortem = s->registerForPostMortem->volatileValue().toBool();
// explicitly trigger setValue() to override the setValueSilently() and trigger the registration
if (originalPostMortem != currentPostMortem)
s->registerForPostMortem->setValue(currentPostMortem);
m_group.apply();
m_group.writeSettings(ICore::settings());
}
CommonOptionsPage::CommonOptionsPage()
{
setId(DEBUGGER_COMMON_SETTINGS_ID);

View File

@@ -161,7 +161,7 @@ static QMap<qint64, QString> getLocalProcessDataUsingPs(const QString &column)
psProcess.start();
if (psProcess.waitForStarted()) {
QByteArray output;
if (psProcess.readDataFromProcess(30000, &output, nullptr, false)) {
if (psProcess.readDataFromProcess(30, &output, nullptr, false)) {
// Split "457 /Users/foo.app arg1 arg2"
const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
const int lineCount = lines.size();

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>373</width>
<height>282</height>
<width>550</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">

View File

@@ -134,6 +134,7 @@ public:
play,
plus,
promote,
readOnly,
redo,
rotationFill,
rotationOutline,
@@ -145,6 +146,7 @@ public:
testIcon,
textAlignBottom,
textAlignCenter,
textAlignJustified,
textAlignLeft,
textAlignMiddle,
textAlignRight,

View File

@@ -30,6 +30,9 @@
#include <synchronousimagecache.h>
#include <theme.h>
#include <hdrimage.h>
#include <designersettings.h>
#include <coreplugin/icore.h>
#include <QDebug>
#include <QDir>
@@ -39,6 +42,8 @@
#include <QMetaProperty>
#include <QPainter>
#include <QRawFont>
#include <QMessageBox>
#include <QCheckBox>
#include <utils/stylehelper.h>
#include <utils/filesystemwatcher.h>
@@ -94,6 +99,41 @@ void ItemLibraryAssetsModel::toggleExpandAll(bool expand)
endResetModel();
}
void ItemLibraryAssetsModel::removeFile(const QString &filePath)
{
bool askBeforeDelete = DesignerSettings::getValue(
DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool();
bool assetDelete = true;
if (askBeforeDelete) {
QMessageBox msg(QMessageBox::Question, tr("Confirm Delete File"),
tr("\"%1\" might be in use. Delete anyway?").arg(filePath),
QMessageBox::No | QMessageBox::Yes);
QCheckBox cb;
cb.setText(tr("Do not ask this again"));
msg.setCheckBox(&cb);
int ret = msg.exec();
if (ret == QMessageBox::No)
assetDelete = false;
if (cb.isChecked())
DesignerSettings::setValue(DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET, false);
}
if (assetDelete) {
if (!QFile::exists(filePath)) {
QMessageBox::warning(Core::ICore::dialogParent(),
tr("Failed to Locate File"),
tr("Could not find \"%1\".").arg(filePath));
} else if (!QFile::remove(filePath)) {
QMessageBox::warning(Core::ICore::dialogParent(),
tr("Failed to Delete File"),
tr("Could not delete \"%1\".").arg(filePath));
}
}
}
const QStringList &ItemLibraryAssetsModel::supportedImageSuffixes()
{
static QStringList retList;

View File

@@ -81,6 +81,7 @@ public:
Q_INVOKABLE void toggleExpandAll(bool expand);
Q_INVOKABLE DirExpandState getAllExpandedState() const;
Q_INVOKABLE void removeFile(const QString &filePath);
private:
SynchronousImageCache &m_fontImageCache;

View File

@@ -81,6 +81,7 @@ void DesignerSettings::fromSettings(QSettings *settings)
restoreValue(settings, DesignerSettingsKey::COLOR_PALETTE_FAVORITE, QStringList());
restoreValue(settings, DesignerSettingsKey::ALWAYS_DESIGN_MODE, true);
restoreValue(settings, DesignerSettingsKey::DISABLE_ITEM_LIBRARY_UPDATE_TIMER, true);
restoreValue(settings, DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET, true);
settings->endGroup();
settings->endGroup();

View File

@@ -71,6 +71,7 @@ const char COLOR_PALETTE_RECENT[] = "ColorPaletteRecent";
const char COLOR_PALETTE_FAVORITE[] = "ColorPaletteFavorite";
const char ALWAYS_DESIGN_MODE[] = "AlwaysDesignMode";
const char DISABLE_ITEM_LIBRARY_UPDATE_TIMER[] = "DisableItemLibraryUpdateTimer";
const char ASK_BEFORE_DELETING_ASSET[] = "AskBeforeDeletingAsset";
}
class QMLDESIGNERCORE_EXPORT DesignerSettings : public QHash<QByteArray, QVariant>

View File

@@ -178,6 +178,8 @@ DesignerSettings SettingsPageWidget::settings() const
m_ui.featureTimelineEditorCheckBox->isChecked());
settings.insert(DesignerSettingsKey::ALWAYS_DESIGN_MODE,
m_ui.designerAlwaysDesignModeCheckBox->isChecked());
settings.insert(DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET,
m_ui.askBeforeDeletingAssetCheckBox->isChecked());
return settings;
}
@@ -247,6 +249,8 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings)
DesignerSettingsKey::ALWAYS_DESIGN_MODE).toBool());
m_ui.featureTimelineEditorCheckBox->setChecked(settings.value(
DesignerSettingsKey::ENABLE_TIMELINEVIEW).toBool());
m_ui.askBeforeDeletingAssetCheckBox->setChecked(settings.value(
DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool());
if (settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) {
m_ui.debugGroupBox->hide();

View File

@@ -416,6 +416,13 @@
<string>Features</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="1">
<widget class="QCheckBox" name="featureTimelineEditorCheckBox">
<property name="text">
<string>Enable Timeline editor</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="designerAlwaysDesignModeCheckBox">
<property name="text">
@@ -423,10 +430,10 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="featureTimelineEditorCheckBox">
<item row="1" column="0">
<widget class="QCheckBox" name="askBeforeDeletingAssetCheckBox">
<property name="text">
<string>Enable Timeline editor</string>
<string>Ask for confirmation before deleting asset</string>
</property>
</widget>
</item>

View File

@@ -157,6 +157,7 @@ void FileDownloader::start()
m_url = reply->url();
start();
} else {
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
emit downloadFailed();
}
} else {

View File

@@ -1,3 +1,8 @@
#
# Internal Qt Creator variable reference
#
set(__just_reference_QT_QMAKE_EXECUTABLE ${QT_QMAKE_EXECUTABLE})
if (EXISTS "${CMAKE_SOURCE_DIR}/QtCreatorPackageManager.cmake")
include("${CMAKE_SOURCE_DIR}/QtCreatorPackageManager.cmake")
endif()

View File

@@ -178,6 +178,14 @@ def substituteTildeWithinToolchains(settingsDir):
__substitute__(toolchains, "~", home)
test.log("Substituted all tildes with '%s' inside toolchains.xml..." % home)
def substituteTildeWithinQtVersion(settingsDir):
toolchains = os.path.join(settingsDir, "QtProject", 'qtcreator', 'qtversion.xml')
home = os.path.expanduser("~")
__substitute__(toolchains, "~", home)
test.log("Substituted all tildes with '%s' inside qtversion.xml..." % home)
def substituteDefaultCompiler(settingsDir):
compiler = None
if platform.system() == 'Darwin':
@@ -309,6 +317,7 @@ def copySettingsToTmpDir(destination=None, omitFiles=[]):
shutil.copy(os.path.join(r, ff), currentPath)
if platform.system() in ('Linux', 'Darwin'):
substituteTildeWithinToolchains(tmpSettingsDir)
substituteTildeWithinQtVersion(tmpSettingsDir)
substituteDefaultCompiler(tmpSettingsDir)
elif platform.system() in ('Windows', 'Microsoft'):
substituteCdb(tmpSettingsDir)

View File

@@ -64,11 +64,11 @@ def performTest(workingDir, projectName, availableConfigs):
for kit, config in availableConfigs:
# switching from MSVC to MinGW build will fail on the clean step of 'Rebuild All Projects'
# because of differences between MSVC's and MinGW's Makefile (so clean before changing kit)
invokeMenuItem('Build', 'Clean Project "%s"' % projectName)
selectFromLocator("t clean", "Clean (Clean Project)")
verifyBuildConfig(kit, config, True, True, True)
test.log("Selected kit '%s'" % Targets.getStringForTarget(kit))
# explicitly build before start debugging for adding the executable as allowed program to WinFW
invokeMenuItem("Build", "Rebuild All Projects")
selectFromLocator("t rebuild", "Rebuild (Rebuild All Projects)")
waitForCompile()
if not checkCompile():
test.fatal("Compile had errors... Skipping current build config")