forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/7.0'
Change-Id: Iab67dffe64bee391bd921ed8832bb17b36ec861b
This commit is contained in:
@@ -2649,7 +2649,8 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
||||
int rangeStartPos = -1;
|
||||
for (auto it = results.begin(); it != results.end();) {
|
||||
const bool wasIfdefedOut = rangeStartPos != -1;
|
||||
if (it->textStyles.mainStyle != C_DISABLED_CODE) {
|
||||
const bool isIfDefedOut = it->textStyles.mainStyle == C_DISABLED_CODE;
|
||||
if (!isIfDefedOut) {
|
||||
if (wasIfdefedOut) {
|
||||
const QTextBlock block = doc->findBlockByNumber(it->line - 1);
|
||||
ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
|
||||
@@ -2661,19 +2662,28 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
||||
|
||||
if (!wasIfdefedOut)
|
||||
rangeStartPos = doc->findBlockByNumber(it->line - 1).position();
|
||||
const int pos = Utils::Text::positionInText(doc, it->line, it->column);
|
||||
const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
|
||||
if (!content.startsWith(QLatin1String("#if"))
|
||||
&& !content.startsWith(QLatin1String("#elif"))
|
||||
&& !content.startsWith(QLatin1String("#else"))
|
||||
&& !content.startsWith(QLatin1String("#endif"))) {
|
||||
static const QStringList ppSuffixes{"if", "ifdef", "elif", "else", "endif"};
|
||||
const QList<QStringView> contentList = content.split(' ', Qt::SkipEmptyParts);
|
||||
if (contentList.size() < 2 || contentList.first() != QLatin1String("#")
|
||||
|| !ppSuffixes.contains(contentList.at(1))) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Does the current line contain a potential "ifdefed-out switcher"?
|
||||
// If not, no state change is possible and we continue with the next line.
|
||||
const auto isPreprocessorControlStatement = [&] {
|
||||
const int pos = Utils::Text::positionInText(doc, it->line, it->column);
|
||||
const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
|
||||
if (content.isEmpty() || content.first() != '#')
|
||||
return false;
|
||||
int offset = 1;
|
||||
while (offset < content.size() && content.at(offset).isSpace())
|
||||
++offset;
|
||||
if (offset == content.size())
|
||||
return false;
|
||||
const QStringView ppDirective = content.mid(offset);
|
||||
return ppDirective.startsWith(QLatin1String("if"))
|
||||
|| ppDirective.startsWith(QLatin1String("elif"))
|
||||
|| ppDirective.startsWith(QLatin1String("else"))
|
||||
|| ppDirective.startsWith(QLatin1String("endif"));
|
||||
};
|
||||
if (!isPreprocessorControlStatement()) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!wasIfdefedOut) {
|
||||
@@ -2700,6 +2710,12 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
||||
if (rangeStartPos != -1)
|
||||
ifdefedOutRanges << BlockRange(rangeStartPos, doc->characterCount());
|
||||
|
||||
qCDebug(clangdLogHighlight) << "found" << ifdefedOutRanges.size() << "ifdefed-out ranges";
|
||||
if (clangdLogHighlight().isDebugEnabled()) {
|
||||
for (const BlockRange &r : qAsConst(ifdefedOutRanges))
|
||||
qCDebug(clangdLogHighlight) << r.first() << r.last();
|
||||
}
|
||||
|
||||
return ifdefedOutRanges;
|
||||
}
|
||||
|
||||
@@ -2741,10 +2757,22 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
// where the user sees that it's being written.
|
||||
if (it->kind() == "CXXOperatorCall") {
|
||||
const QList<AstNode> children = it->children().value_or(QList<AstNode>());
|
||||
|
||||
// Child 1 is the call itself, Child 2 is the named entity on which the call happens
|
||||
// (a lambda or a class instance), after that follow the actual call arguments.
|
||||
if (children.size() < 2)
|
||||
return false;
|
||||
if (!children.last().range().contains(range))
|
||||
|
||||
// The call itself is never modifiable.
|
||||
if (children.first().range() == range)
|
||||
return false;
|
||||
|
||||
// The callable is never displayed as an output parameter.
|
||||
// TODO: A good argument can be made to display objects on which a non-const
|
||||
// operator or function is called as output parameters.
|
||||
if (children.at(1).range() == range)
|
||||
return false;
|
||||
|
||||
QList<AstNode> firstChildTree{children.first()};
|
||||
while (!firstChildTree.isEmpty()) {
|
||||
const AstNode n = firstChildTree.takeFirst();
|
||||
@@ -2859,13 +2887,13 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
|
||||
auto results = QtConcurrent::blockingMapped<HighlightingResults>(tokens, toResult);
|
||||
const QList<BlockRange> ifdefedOutBlocks = cleanupDisabledCode(results, &doc, docContents);
|
||||
QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] {
|
||||
if (textDocument && textDocument->document()->revision() == docRevision)
|
||||
textDocument->setIfdefedOutBlocks(ifdefedOutBlocks);
|
||||
}, Qt::QueuedConnection);
|
||||
ExtraHighlightingResultsCollector(future, results, filePath, ast, &doc, docContents).collect();
|
||||
if (!future.isCanceled()) {
|
||||
qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
|
||||
QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] {
|
||||
if (textDocument && textDocument->document()->revision() == docRevision)
|
||||
textDocument->setIfdefedOutBlocks(ifdefedOutBlocks);
|
||||
}, Qt::QueuedConnection);
|
||||
QList<Range> virtualRanges;
|
||||
for (const HighlightingResult &r : results) {
|
||||
if (r.textStyles.mainStyle != C_VIRTUAL_METHOD)
|
||||
@@ -2880,8 +2908,7 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
client->setVirtualRanges(filePath, virtualRanges, docRevision);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
future.reportResults(QVector<HighlightingResult>(results.cbegin(),
|
||||
results.cend()));
|
||||
future.reportResults(QVector<HighlightingResult>(results.cbegin(), results.cend()));
|
||||
}
|
||||
future.reportFinished();
|
||||
}
|
||||
|
||||
@@ -1285,6 +1285,14 @@ void ClangdTestHighlighting::test_data()
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("const member as function argument") << 868 << 32 << 868 << 43
|
||||
<< QList<int>{C_FIELD} << 0;
|
||||
QTest::newRow("lambda call without arguments (const var)") << 887 << 5 << 887 << 12
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("lambda call without arguments (non-const var)") << 889 << 5 << 889 << 12
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("non-const operator()") << 898 << 5 << 898 << 7
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("const operator()") << 903 << 5 << 903 << 7
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
}
|
||||
|
||||
void ClangdTestHighlighting::test()
|
||||
|
||||
@@ -880,3 +880,25 @@ void constMemberAsFunctionArg()
|
||||
#if 0
|
||||
#define BAR
|
||||
# endif
|
||||
|
||||
void lambdaCall()
|
||||
{
|
||||
const auto lambda1 = [] {};
|
||||
lambda1();
|
||||
auto lambda2 = [] {};
|
||||
lambda2();
|
||||
}
|
||||
|
||||
void callOperators()
|
||||
{
|
||||
struct Callable1 {
|
||||
void operator()() {};
|
||||
};
|
||||
Callable1 c1;
|
||||
c1();
|
||||
struct Callable2 {
|
||||
void operator()() const {};
|
||||
};
|
||||
Callable2 c2;
|
||||
c2();
|
||||
}
|
||||
|
||||
@@ -488,14 +488,14 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
|
||||
if (m_buildConfiguration->isEnabled())
|
||||
setError(QString());
|
||||
});
|
||||
connect(this, &QObject::destroyed, this, [this](const QObject *obj) {
|
||||
connect(this, &QObject::destroyed, this, [this] {
|
||||
updateInitialCMakeArguments();
|
||||
});
|
||||
|
||||
connect(bc->aspect<InitialCMakeArgumentsAspect>(),
|
||||
&Utils::BaseAspect::labelLinkActivated,
|
||||
this,
|
||||
[this](const QString &link) {
|
||||
[this](const QString &) {
|
||||
const CMakeTool *tool = CMakeKitAspect::cmakeTool(
|
||||
m_buildConfiguration->target()->kit());
|
||||
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake.1.html#options");
|
||||
@@ -503,7 +503,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
|
||||
connect(bc->aspect<AdditionalCMakeOptionsAspect>(),
|
||||
&Utils::BaseAspect::labelLinkActivated,
|
||||
this,
|
||||
[this](const QString &link) {
|
||||
[this](const QString &) {
|
||||
const CMakeTool *tool = CMakeKitAspect::cmakeTool(
|
||||
m_buildConfiguration->target()->kit());
|
||||
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake.1.html#options");
|
||||
@@ -527,7 +527,7 @@ void CMakeBuildSettingsWidget::batchEditConfiguration()
|
||||
"To set or change a variable, use -D<variable>:<type>=<value>.<br/>"
|
||||
"<type> can have one of the following values: FILEPATH, PATH, BOOL, INTERNAL, or STRING.<br/>"
|
||||
"To unset a variable, use -U<variable>.<br/>"));
|
||||
connect(label, &QLabel::linkActivated, this, [this](const QString &link) {
|
||||
connect(label, &QLabel::linkActivated, this, [this](const QString &) {
|
||||
const CMakeTool *tool = CMakeKitAspect::cmakeTool(m_buildConfiguration->target()->kit());
|
||||
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake-variables.7.html");
|
||||
});
|
||||
|
||||
@@ -353,7 +353,7 @@ public:
|
||||
m_changeButton(createSubWidget<QPushButton>())
|
||||
{
|
||||
const CMakeTool *tool = CMakeKitAspect::cmakeTool(kit);
|
||||
connect(this, &KitAspectWidget::labelLinkActivated, this, [=](const QString &link) {
|
||||
connect(this, &KitAspectWidget::labelLinkActivated, this, [=](const QString &) {
|
||||
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake-generators.7.html");
|
||||
});
|
||||
|
||||
@@ -972,7 +972,7 @@ private:
|
||||
"To set a variable, use -D<variable>:<type>=<value>.<br/>"
|
||||
"<type> can have one of the following values: FILEPATH, PATH, "
|
||||
"BOOL, INTERNAL, or STRING."));
|
||||
connect(editorLabel, &QLabel::linkActivated, this, [=](const QString &link) {
|
||||
connect(editorLabel, &QLabel::linkActivated, this, [=](const QString &) {
|
||||
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake-variables.7.html");
|
||||
});
|
||||
m_editor->setMinimumSize(800, 200);
|
||||
@@ -984,7 +984,7 @@ private:
|
||||
m_additionalEditor = new QLineEdit;
|
||||
auto additionalLabel = new QLabel(m_dialog);
|
||||
additionalLabel->setText(tr("Additional CMake <a href=\"options\">options</a>:"));
|
||||
connect(additionalLabel, &QLabel::linkActivated, this, [=](const QString &link) {
|
||||
connect(additionalLabel, &QLabel::linkActivated, this, [=](const QString &) {
|
||||
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake.1.html#options");
|
||||
});
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ static void showOutputPane(Flag flags)
|
||||
m_messageOutputWindow->flash();
|
||||
break;
|
||||
case Core::Flag::Disrupt:
|
||||
m_messageOutputWindow->popup(IOutputPane::ModeSwitch);
|
||||
m_messageOutputWindow->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ void CodePasterPluginPrivate::finishPost(const QString &link)
|
||||
if (m_settings.displayOutput.value())
|
||||
MessageManager::writeDisrupting(link);
|
||||
else
|
||||
MessageManager::writeSilently(link);
|
||||
MessageManager::writeFlashing(link);
|
||||
}
|
||||
|
||||
// Extract the characters that can be used for a file name from a title
|
||||
|
||||
@@ -208,6 +208,6 @@ void FileShareProtocol::paste(
|
||||
return;
|
||||
}
|
||||
|
||||
Core::MessageManager::writeSilently(tr("Pasted: %1").arg(saver.filePath().toUserOutput()));
|
||||
emit pasteDone(saver.filePath().toUserOutput());
|
||||
}
|
||||
} // namespace CodePaster
|
||||
|
||||
@@ -1030,6 +1030,7 @@ FilePath DockerDevice::mapToLocalAccess(const FilePath &filePath) const
|
||||
return FilePath::fromString(d->m_mergedDir + '/' + path);
|
||||
#else
|
||||
QTC_CHECK(false);
|
||||
Q_UNUSED(filePath)
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
@@ -1047,6 +1048,7 @@ FilePath DockerDevice::mapFromLocalAccess(const QString &filePath) const
|
||||
QTC_ASSERT(filePath.startsWith(d->m_mergedDir), return FilePath::fromString(filePath));
|
||||
return mapToGlobalPath(FilePath::fromString(filePath.mid(d->m_mergedDir.size())));
|
||||
#else
|
||||
Q_UNUSED(filePath)
|
||||
QTC_CHECK(false);
|
||||
return {};
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,9 @@ public:
|
||||
distributeSpacingVertical,
|
||||
distributeTop,
|
||||
download,
|
||||
downloadUnavailable,
|
||||
downloadUpdate,
|
||||
downloaded,
|
||||
edit,
|
||||
eyeDropper,
|
||||
favorite,
|
||||
|
||||
@@ -484,7 +484,7 @@ void FormEditorView::customNotification(const AbstractView * /*view*/, const QSt
|
||||
|
||||
void FormEditorView::currentStateChanged(const ModelNode & /*node*/)
|
||||
{
|
||||
temporaryBlockView(100);
|
||||
temporaryBlockView();
|
||||
}
|
||||
|
||||
AbstractFormEditorTool *FormEditorView::currentTool() const
|
||||
|
||||
@@ -147,7 +147,7 @@ private:
|
||||
void setupFormEditorItemTree(const QmlItemNode &qmlItemNode);
|
||||
void removeNodeFromScene(const QmlItemNode &qmlItemNode);
|
||||
void createFormEditorWidget();
|
||||
void temporaryBlockView(int duration = 1000);
|
||||
void temporaryBlockView(int duration = 100);
|
||||
void resetNodeInstanceView();
|
||||
void addOrRemoveFormEditorItem(const ModelNode &node);
|
||||
void checkRootModelNode();
|
||||
|
||||
@@ -161,6 +161,8 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
|
||||
, m_itemsWidget(new QQuickWidget(this))
|
||||
, m_imageCache{imageCache}
|
||||
{
|
||||
Q_UNUSED(asynchronousFontImageCache)
|
||||
|
||||
m_compressionTimer.setInterval(200);
|
||||
m_compressionTimer.setSingleShot(true);
|
||||
ItemLibraryModel::registerQmlTypes();
|
||||
|
||||
@@ -865,7 +865,7 @@ ModelNode RewriterView::nodeAtTextCursorPositionHelper(const ModelNode &root, in
|
||||
for (const myPair &pair : data) {
|
||||
ModelNode node = pair.first;
|
||||
i++;
|
||||
if (i >= data.size()) {
|
||||
if (i >= int(data.size())) {
|
||||
lastNode = node;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include <QQuickItem>
|
||||
#include <QQuickWidget>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
ExampleCheckout::ExampleCheckout(QObject *) {}
|
||||
@@ -137,11 +139,11 @@ FileDownloader::~FileDownloader()
|
||||
void FileDownloader::start()
|
||||
{
|
||||
m_tempFile.setFileName(QDir::tempPath() + "/" + name() + ".XXXXXX" + ".zip");
|
||||
|
||||
m_tempFile.open(QIODevice::WriteOnly);
|
||||
|
||||
auto request = QNetworkRequest(m_url);
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, true);
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
|
||||
QNetworkRequest::UserVerifiedRedirectPolicy);
|
||||
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::readyRead, [this, reply]() {
|
||||
@@ -159,20 +161,20 @@ void FileDownloader::start()
|
||||
emit progressChanged();
|
||||
});
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::redirected, [reply](const QUrl &url) {
|
||||
emit reply->redirectAllowed();
|
||||
});
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
|
||||
if (reply->error()) {
|
||||
m_tempFile.remove();
|
||||
if (m_url != reply->url()) {
|
||||
m_url = reply->url();
|
||||
start();
|
||||
} else {
|
||||
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
|
||||
emit downloadFailed();
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
|
||||
emit downloadFailed();
|
||||
} else {
|
||||
m_tempFile.flush();
|
||||
m_tempFile.close();
|
||||
m_finished = true;
|
||||
emit tempFileChanged();
|
||||
emit finishedChanged();
|
||||
}
|
||||
});
|
||||
@@ -181,8 +183,9 @@ void FileDownloader::start()
|
||||
void FileDownloader::setUrl(const QUrl &url)
|
||||
{
|
||||
m_url = url;
|
||||
|
||||
emit nameChanged();
|
||||
|
||||
probeUrl();
|
||||
}
|
||||
|
||||
QUrl FileDownloader::url() const
|
||||
@@ -222,16 +225,71 @@ QString FileDownloader::tempFile() const
|
||||
return QFileInfo(m_tempFile).canonicalFilePath();
|
||||
}
|
||||
|
||||
QDateTime FileDownloader::lastModified() const
|
||||
{
|
||||
return m_lastModified;
|
||||
}
|
||||
|
||||
bool FileDownloader::available() const
|
||||
{
|
||||
return m_available;
|
||||
}
|
||||
|
||||
void FileDownloader::probeUrl()
|
||||
{
|
||||
auto request = QNetworkRequest(m_url);
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
|
||||
QNetworkRequest::UserVerifiedRedirectPolicy);
|
||||
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->head(request);
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::redirected, [reply](const QUrl &url) {
|
||||
emit reply->redirectAllowed();
|
||||
});
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
|
||||
if (reply->error())
|
||||
return;
|
||||
|
||||
m_lastModified = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
|
||||
emit lastModifiedChanged();
|
||||
|
||||
m_available = true;
|
||||
emit availableChanged();
|
||||
});
|
||||
|
||||
QNetworkReply::connect(reply,
|
||||
&QNetworkReply::errorOccurred,
|
||||
[this, reply](QNetworkReply::NetworkError code) {
|
||||
// QNetworkReply::HostNotFoundError
|
||||
// QNetworkReply::ContentNotFoundError
|
||||
m_available = false;
|
||||
emit availableChanged();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
FileExtractor::FileExtractor(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
if (Core::DocumentManager::instance())
|
||||
m_targetPath = Core::DocumentManager::projectsDirectory();
|
||||
m_targetPath = Utils::FilePath::fromString(
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
||||
|
||||
if (!m_targetPath.isEmpty())
|
||||
m_targetPath = m_targetPath.pathAppended("QtDesignStudio");
|
||||
else
|
||||
m_targetPath = "/temp/";
|
||||
|
||||
m_timer.setInterval(500);
|
||||
m_timer.setInterval(100);
|
||||
m_timer.setSingleShot(false);
|
||||
|
||||
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, [this]() {
|
||||
if (targetFolderExists()) {
|
||||
m_birthTime = QFileInfo(m_targetPath.toString() + "/" + m_archiveName).birthTime();
|
||||
} else
|
||||
m_birthTime = QDateTime();
|
||||
|
||||
emit birthTimeChanged();
|
||||
});
|
||||
}
|
||||
|
||||
FileExtractor::~FileExtractor() {}
|
||||
@@ -297,8 +355,17 @@ QString FileExtractor::count() const
|
||||
|
||||
bool FileExtractor::targetFolderExists() const
|
||||
{
|
||||
const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName;
|
||||
return QFileInfo(targetFolder).exists();
|
||||
return QFileInfo::exists(m_targetPath.toString() + "/" + m_archiveName);
|
||||
}
|
||||
|
||||
int FileExtractor::progress() const
|
||||
{
|
||||
return m_progress;
|
||||
}
|
||||
|
||||
QDateTime FileExtractor::birthTime() const
|
||||
{
|
||||
return m_birthTime;
|
||||
}
|
||||
|
||||
QString FileExtractor::archiveName() const
|
||||
@@ -320,8 +387,9 @@ void FileExtractor::extract()
|
||||
m_timer.start();
|
||||
const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName;
|
||||
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||
qint64 compressedSize = QFileInfo(m_sourceFile.toString()).size();
|
||||
|
||||
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder]() {
|
||||
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder, compressedSize]() {
|
||||
static QHash<QString, int> hash;
|
||||
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
|
||||
|
||||
@@ -336,9 +404,15 @@ void FileExtractor::extract()
|
||||
count++;
|
||||
}
|
||||
|
||||
m_size = QString::number(bytesBefore
|
||||
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable());
|
||||
qint64 currentSize = bytesBefore
|
||||
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||
|
||||
// We can not get the uncompressed size of the archive yet, that is why we use an
|
||||
// approximation. We assume a 50% compression rate.
|
||||
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
|
||||
emit progressChanged();
|
||||
|
||||
m_size = QString::number(currentSize);
|
||||
m_count = QString::number(count);
|
||||
emit sizeChanged();
|
||||
});
|
||||
@@ -351,6 +425,11 @@ void FileExtractor::extract()
|
||||
QObject::connect(archive, &Utils::Archive::finished, [this](bool ret) {
|
||||
m_finished = ret;
|
||||
m_timer.stop();
|
||||
|
||||
m_progress = 100;
|
||||
emit progressChanged();
|
||||
|
||||
emit targetFolderExistsChanged();
|
||||
emit finishedChanged();
|
||||
QTC_ASSERT(ret, ;);
|
||||
});
|
||||
|
||||
@@ -78,6 +78,8 @@ class FileExtractor : public QObject
|
||||
Q_PROPERTY(QString sourceFile READ sourceFile WRITE setSourceFile)
|
||||
Q_PROPERTY(bool finished READ finished NOTIFY finishedChanged)
|
||||
Q_PROPERTY(bool targetFolderExists READ targetFolderExists NOTIFY targetFolderExistsChanged)
|
||||
Q_PROPERTY(int progress READ progress NOTIFY progressChanged)
|
||||
Q_PROPERTY(QDateTime birthTime READ birthTime NOTIFY birthTimeChanged)
|
||||
|
||||
public:
|
||||
explicit FileExtractor(QObject *parent = nullptr);
|
||||
@@ -94,6 +96,8 @@ public:
|
||||
QString size() const;
|
||||
QString count() const;
|
||||
bool targetFolderExists() const;
|
||||
int progress() const;
|
||||
QDateTime birthTime() const;
|
||||
|
||||
QString sourceFile() const;
|
||||
QString archiveName() const;
|
||||
@@ -108,6 +112,8 @@ signals:
|
||||
void currentFileChanged();
|
||||
void sizeChanged();
|
||||
void targetFolderExistsChanged();
|
||||
void progressChanged();
|
||||
void birthTimeChanged();
|
||||
|
||||
private:
|
||||
Utils::FilePath m_targetPath;
|
||||
@@ -119,6 +125,8 @@ private:
|
||||
QString m_size;
|
||||
QString m_count;
|
||||
QString m_archiveName;
|
||||
int m_progress = 0;
|
||||
QDateTime m_birthTime;
|
||||
};
|
||||
|
||||
class FileDownloader : public QObject
|
||||
@@ -131,7 +139,9 @@ class FileDownloader : public QObject
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(QString completeBaseName READ completeBaseName NOTIFY nameChanged)
|
||||
Q_PROPERTY(int progress READ progress NOTIFY progressChanged)
|
||||
Q_PROPERTY(QString tempFile READ tempFile NOTIFY finishedChanged)
|
||||
Q_PROPERTY(QString tempFile READ tempFile NOTIFY tempFileChanged)
|
||||
Q_PROPERTY(QDateTime lastModified READ lastModified NOTIFY lastModifiedChanged)
|
||||
Q_PROPERTY(bool available READ available NOTIFY availableChanged)
|
||||
|
||||
public:
|
||||
explicit FileDownloader(QObject *parent = nullptr);
|
||||
@@ -147,6 +157,8 @@ public:
|
||||
QString completeBaseName() const;
|
||||
int progress() const;
|
||||
QString tempFile() const;
|
||||
QDateTime lastModified() const;
|
||||
bool available() const;
|
||||
|
||||
Q_INVOKABLE void start();
|
||||
|
||||
@@ -155,12 +167,19 @@ signals:
|
||||
void errorChanged();
|
||||
void nameChanged();
|
||||
void progressChanged();
|
||||
void tempFileChanged();
|
||||
void downloadFailed();
|
||||
void lastModifiedChanged();
|
||||
void availableChanged();
|
||||
|
||||
private:
|
||||
void probeUrl();
|
||||
|
||||
QUrl m_url;
|
||||
bool m_finished = false;
|
||||
bool m_error = false;
|
||||
int m_progress = 0;
|
||||
QFile m_tempFile;
|
||||
QDateTime m_lastModified;
|
||||
bool m_available;
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ QStringList RecentPresetsStore::addRecentToExisting(const RecentPreset &preset,
|
||||
Utils::erase_one(recents, preset);
|
||||
Utils::prepend(recents, preset);
|
||||
|
||||
if (recents.size() > m_max)
|
||||
if (int(recents.size()) > m_max)
|
||||
recents.pop_back();
|
||||
|
||||
return encodeRecentPresets(recents);
|
||||
|
||||
@@ -232,6 +232,28 @@ public:
|
||||
QDesktopServices::openUrl(QUrl("qthelp://org.qt-project.qtcreator/doc/index.html"));
|
||||
}
|
||||
|
||||
Q_INVOKABLE void openExample(const QString &examplePath,
|
||||
const QString &exampleName,
|
||||
const QString &formFile,
|
||||
const QString &explicitQmlproject)
|
||||
{
|
||||
const QString exampleFolder = examplePath + "/" + exampleName + "/";
|
||||
|
||||
QString projectFile = exampleFolder + exampleName + ".qmlproject";
|
||||
|
||||
if (!explicitQmlproject.isEmpty())
|
||||
projectFile = exampleFolder + explicitQmlproject;
|
||||
|
||||
ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
|
||||
|
||||
const QString qmlFile = QFileInfo(projectFile).dir().absolutePath() + "/" + formFile;
|
||||
|
||||
// This timer should be replaced with a signal send from project loading
|
||||
QTimer::singleShot(1000, [qmlFile](){
|
||||
Core::EditorManager::openEditor(Utils::FilePath::fromString(qmlFile));
|
||||
});
|
||||
}
|
||||
|
||||
Q_INVOKABLE void openExample(const QString &example,
|
||||
const QString &formFile,
|
||||
const QString &url,
|
||||
@@ -272,6 +294,7 @@ public:
|
||||
|
||||
Core::EditorManager::openEditor(qmlFile);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void resetProjects();
|
||||
|
||||
@@ -465,7 +488,7 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
|
||||
case FilePathRole:
|
||||
return data.first;
|
||||
case PrettyFilePathRole:
|
||||
return Utils::withTildeHomePath(data.first);
|
||||
return Utils::withTildeHomePath(QFileInfo(data.first).dir().absolutePath());
|
||||
case PreviewUrl:
|
||||
return QVariant(QStringLiteral("image://project_preview/") + appQmlFile(data.first));
|
||||
case TagData:
|
||||
|
||||
Reference in New Issue
Block a user