Merge remote-tracking branch 'origin/10.0' into HEAD

Change-Id: I55ff1d27695d6d7715538695e442bf097a1f3a1f
This commit is contained in:
David Schulz
2023-02-01 06:39:05 +01:00
100 changed files with 6356 additions and 853 deletions

View File

@@ -46,6 +46,7 @@
\li \l{Using Bazaar} \li \l{Using Bazaar}
\li \l{Using ClearCase} \li \l{Using ClearCase}
\li \l{Using CVS} \li \l{Using CVS}
\li \l{Using Fossil}
\li \l{Using Git} \li \l{Using Git}
\li \l{Using GitLab} \li \l{Using GitLab}
\li \l{Using Mercurial} \li \l{Using Mercurial}

View File

@@ -10,7 +10,7 @@
/*! /*!
\previouspage creator-vcs-clearcase.html \previouspage creator-vcs-clearcase.html
\page creator-vcs-cvs.html \page creator-vcs-cvs.html
\nextpage creator-vcs-git.html \nextpage creator-vcs-fossil.html
\title Using CVS \title Using CVS

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2018 Artur Shepilko
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page creator-vcs-fossil.html
\previouspage creator-vcs-cvs.html
\nextpage creator-vcs-git.html
\title Using Fossil
Fossil is an open source distributed version control system, designed
and developed by the creator of SQLite. A stand-alone Fossil executable
contains a source control management engine, web interface, issue tracker,
wiki, and built-in web server. Fossil is available for Linux, Windows,
and \macos.
To use Fossil from \QC, you must install and configure it, as described in
the following sections.
\section1 Configuring Fossil
\list 1
\li Download the \l{http://fossil-scm.org}{Fossil SCM client} and
install the \c fossil executable file in your \c PATH.
\li Create or designate a directory to store local Fossil repositories
and remote clones. For example: \c ~/fossils/qt.
\li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Version Control} > \uicontrol Fossil, and set the
designated directory in the \uicontrol {Default path} field.
\endlist
To create a local Fossil repository, select \uicontrol Tools >
\uicontrol Fossil > \uicontrol {Create Repository}.
To clone a remote Fossil repository, select \uicontrol File >
\uicontrol {New Project} > \uicontrol {Import Project} >
\uicontrol {Fossil Clone}.
\section1 Additional Fossil Functions
In addition to the standard version control system functions described in
\l {Using Version Control Systems}, the \uicontrol Fossil submenu contains
the following items:
\table
\header
\li Menu Item
\li Description
\row
\li \uicontrol Pull
\li Pull changes from the remote repository.
\row
\li \uicontrol Push
\li Push committed changes to the remote repository.
\row
\li \uicontrol Update
\li Change the version of the current checkout. Any uncommitted
changes are retained and applied to the new checkout.
\row
\li \uicontrol Settings
\li Configure the settings of the local repository.
\endtable
*/

View File

@@ -37,14 +37,12 @@
\li \l{http://www.nongnu.org/cvs/} \li \l{http://www.nongnu.org/cvs/}
\li \li
\row \row
\li \l{https://doc.qt.io/qtcreator/creator-vcs-fossil.html}{Fossil} \li \l{Using Fossil}{Fossil}
\li \l{https://fossil-scm.org/index.html/doc/trunk/www/index.wiki} \li \l{https://fossil-scm.org/index.html/doc/trunk/www/index.wiki}
\li To use Fossil, you need to build the Fossil plugin from \li Disabled by default. To enable the plugin, select
\l{https://code.qt.io/cgit/qt-creator/plugin-fossil-scm.git/} \uicontrol Help > \uicontrol {About Plugins} >
{sources}, and install Fossil as described in \uicontrol {Version Control} > \uicontrol Fossil.
\l{https://doc.qt.io/qtcreator/creator-vcs-fossil.html} \row
{Qt Creator Fossil Plugin Manual}.
\row
\li \l{Using Git}{Git} \li \l{Using Git}{Git}
\li \l{http://git-scm.com/} \li \l{http://git-scm.com/}
\li Git version 1.9.0, or later \li Git version 1.9.0, or later
@@ -66,8 +64,6 @@
Disabled by default. To enable the plugin, select Disabled by default. To enable the plugin, select
\uicontrol Help > \uicontrol {About Plugins} > \uicontrol Help > \uicontrol {About Plugins} >
\uicontrol {Version Control} > \uicontrol Perforce. \uicontrol {Version Control} > \uicontrol Perforce.
Then select \uicontrol {Restart Now} to restart \QC
and load the plugin.
\row \row
\li \l{Using Subversion}{Subversion} \li \l{Using Subversion}{Subversion}
\li \l{http://subversion.apache.org/} \li \l{http://subversion.apache.org/}
@@ -103,8 +99,7 @@
\li \l{Using Bazaar} \li \l{Using Bazaar}
\li \l{Using ClearCase} \li \l{Using ClearCase}
\li \l{Using CVS} \li \l{Using CVS}
\li \l{https://doc.qt.io/qtcreator/creator-vcs-fossil.html} \li \l{Using Fossil}
{Qt Creator Fossil Plugin Manual}
\li \l{Using Git} \li \l{Using Git}
\li \l{Using GitLab} \li \l{Using GitLab}
\li \l{Using Mercurial} \li \l{Using Mercurial}

View File

@@ -13,7 +13,7 @@
\previouspage studio-developer-topics.html \previouspage studio-developer-topics.html
\nextpage studio-porting-projects.html \nextpage studio-porting-projects.html
\else \else
\previouspage creator-vcs-cvs.html \previouspage creator-vcs-fossil.html
\nextpage creator-vcs-gitlab.html \nextpage creator-vcs-gitlab.html
\endif \endif

View File

@@ -2,10 +2,22 @@ cmake_minimum_required(VERSION 3.16)
project(%{ProjectName} VERSION 0.1 LANGUAGES CXX) project(%{ProjectName} VERSION 0.1 LANGUAGES CXX)
@if !%{HasQSPSetup}
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
@endif
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 REQUIRED COMPONENTS Quick) find_package(Qt6 %{MinimumSupportedQtVersion} REQUIRED COMPONENTS Quick)
@if %{HasQSPSetup}
@if %{UsesAutoResourcePrefix}
qt_standard_project_setup(
MIN_VERSION 6.5
)
@else
qt_standard_project_setup()
@endif
@endif
qt_add_executable(%{TargetName} qt_add_executable(%{TargetName}
main.cpp main.cpp
@@ -14,7 +26,7 @@ qt_add_executable(%{TargetName}
qt_add_qml_module(%{TargetName} qt_add_qml_module(%{TargetName}
URI %{ProjectName} URI %{ProjectName}
VERSION 1.0 VERSION 1.0
QML_FILES main.qml QML_FILES Main.qml
) )
set_target_properties(%{TargetName} PROPERTIES set_target_properties(%{TargetName} PROPERTIES

View File

@@ -10,13 +10,25 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
const QUrl url(u"qrc:/%{JS: value('ProjectName')}/main.qml"_qs); @if !%{HasLoadFromModule}
const QUrl url(u"qrc:/%{JS: value('ProjectName')}/Main.qml"_qs);
@endif
@if %{HasFailureSignal}
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
&app, []() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
@else
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) { &app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl) if (!obj && url == objUrl)
QCoreApplication::exit(-1); QCoreApplication::exit(-1);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);
@endif
@if %{HasLoadFromModule}
engine.loadFromModule("%{JS: value('ProjectName')}", "Main");
@else
engine.load(url); engine.load(url);
@endif
return app.exec(); return app.exec();
} }

View File

@@ -16,6 +16,6 @@ CppApplication {
Group { Group {
Qt.core.resourcePrefix: "%{ProjectName}/" Qt.core.resourcePrefix: "%{ProjectName}/"
fileTags: ["qt.qml.qml", "qt.core.resource_data"] fileTags: ["qt.qml.qml", "qt.core.resource_data"]
files: ["main.qml"] files: ["Main.qml"]
} }
} }

View File

@@ -17,6 +17,10 @@
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src') }" }, { "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src') }" },
{ "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0 }" }, { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0 }" },
{ "key": "TargetName", "value": "%{JS: 'app' + value('ProjectName') }" }, { "key": "TargetName", "value": "%{JS: 'app' + value('ProjectName') }" },
{ "key": "HasQSPSetup", "value": "%{JS: value('MinimumSupportedQtVersion') > '6.2' }"},
{ "key": "HasFailureSignal", "value": "%{JS: value('MinimumSupportedQtVersion') > '6.3' }"},
{ "key": "UsesAutoResourcePrefix", "value": "%{JS: value('MinimumSupportedQtVersion') > '6.4' && value('BuildSystem') === 'cmake' }"},
{ "key": "HasLoadFromModule", "value": "%{JS: value('MinimumSupportedQtVersion') > '6.4' && value('UsesAutoResourcePrefix') }"},
{ "key": "QdsWizardPath", "value": "%{IDE:ResourcePath}/qmldesigner/studio_templates/projects" }, { "key": "QdsWizardPath", "value": "%{IDE:ResourcePath}/qmldesigner/studio_templates/projects" },
{ "key": "QdsProjectStyle", "value": "%{JS: value('BuildSystem') === 'cmake' ? %{QdsProjectStyleInput} : false }" }, { "key": "QdsProjectStyle", "value": "%{JS: value('BuildSystem') === 'cmake' ? %{QdsProjectStyleInput} : false }" },
{ "key": "NoQdsProjectStyle", "value": "%{JS: !%{QdsProjectStyle} }" }, { "key": "NoQdsProjectStyle", "value": "%{JS: !%{QdsProjectStyle} }" },
@@ -104,6 +108,16 @@
{ {
"checked": "%{UseVirtualKeyboardByDefault}" "checked": "%{UseVirtualKeyboardByDefault}"
} }
},
{
"name": "MinimumSupportedQtVersion",
"trDisplayName": "The minimum version of Qt you want to build the application for",
"type": "ComboBox",
"data":
{
"items": [ "6.2", "6.4", "6.5" ],
"index": 1
}
} }
] ]
}, },
@@ -146,8 +160,8 @@
"condition": "%{NoQdsProjectStyle}" "condition": "%{NoQdsProjectStyle}"
}, },
{ {
"source": "main.qml.tpl", "source": "Main.qml.tpl",
"target": "main.qml", "target": "Main.qml",
"openInEditor": true, "openInEditor": true,
"condition": "%{NoQdsProjectStyle}" "condition": "%{NoQdsProjectStyle}"
}, },

View File

@@ -9,17 +9,12 @@
"icon": "qtquickuiprototype.png", "icon": "qtquickuiprototype.png",
"iconKind": "Themed", "iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('QmlProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQtQuick.6" ],
"options": "options":
[ [
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qmlproject')}" }, { "key": "QmlProjectFileName", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qmlproject')}" },
{ "key": "IsQt6", "value": "%{JS: value('QtVersion').IsQt6}" },
{ "key": "MainQmlFileName", "value": "%{JS: Util.fileName(value('ProjectName'), 'qml')}" }, { "key": "MainQmlFileName", "value": "%{JS: Util.fileName(value('ProjectName'), 'qml')}" },
{ "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
{ "key": "QtQuickWindowVersion", "value": "%{JS: value('QtVersion').QtQuickWindowVersion}" },
{ "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: value('QtVersion').QtQuickVirtualKeyboardImport}" },
{ "key": "QtQuickFeature", "value": "%{JS: (value('QtQuickVersion')=='') ? 'QtSupport.Wizards.FeatureQtQuick.6' : 'QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}'}" },
{ "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0}" } { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0}" }
], ],
@@ -36,68 +31,6 @@
"typeId": "Fields", "typeId": "Fields",
"data": "data":
[ [
{
"name": "QtVersion",
"trDisplayName": "Minimum required Qt version:",
"type": "ComboBox",
"data":
{
"index": 1,
"items":
[
{
"trKey": "Qt 6",
"value":
{
"QtQuickVersion": "",
"QtQuickWindowVersion": "",
"QtQuickVirtualKeyboardImport": "",
"IsQt6": true
}
},
{
"trKey": "Qt 5.15",
"value":
{
"QtQuickVersion": "2.15",
"QtQuickWindowVersion": "2.15",
"QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.15",
"IsQt6": false
}
},
{
"trKey": "Qt 5.14",
"value":
{
"QtQuickVersion": "2.14",
"QtQuickWindowVersion": "2.14",
"QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.14",
"IsQt6": false
}
},
{
"trKey": "Qt 5.13",
"value":
{
"QtQuickVersion": "2.13",
"QtQuickWindowVersion": "2.13",
"QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4",
"IsQt6": false
}
},
{
"trKey": "Qt 5.12",
"value":
{
"QtQuickVersion": "2.12",
"QtQuickWindowVersion": "2.12",
"QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4",
"IsQt6": false
}
}
]
}
},
{ {
"name": "UseVirtualKeyboard", "name": "UseVirtualKeyboard",
"trDisplayName": "Use Qt Virtual Keyboard", "trDisplayName": "Use Qt Virtual Keyboard",
@@ -116,7 +49,7 @@
"enabled": "%{JS: ! %{IsSubproject}}", "enabled": "%{JS: ! %{IsSubproject}}",
"data": { "data": {
"projectFilePath": "%{QmlProjectFileName}", "projectFilePath": "%{QmlProjectFileName}",
"requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ] "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQtQuick.6" ]
} }
}, },
{ {
@@ -137,7 +70,7 @@
"openAsProject": true "openAsProject": true
}, },
{ {
"source": "../qtquickapplication/empty/main.qml.tpl", "source": "../qtquickapplication/Main.qml.tpl",
"target": "%{ProjectDirectory}/%{MainQmlFileName}", "target": "%{ProjectDirectory}/%{MainQmlFileName}",
"openInEditor": true "openInEditor": true
}, },

View File

@@ -283,6 +283,7 @@ public:
std::function<Environment(const FilePath &)> environment; std::function<Environment(const FilePath &)> environment;
std::function<bool(const FilePath &left, const FilePath &right)> isSameDevice; std::function<bool(const FilePath &left, const FilePath &right)> isSameDevice;
std::function<expected_str<FilePath>(const FilePath &)> localSource; std::function<expected_str<FilePath>(const FilePath &)> localSource;
std::function<void(const FilePath &, const Environment &)> openTerminal;
}; };
} // Utils } // Utils

View File

@@ -1348,83 +1348,6 @@ QString QtcProcess::errorString() const
// Path utilities // Path utilities
// Locate a binary in a directory, applying all kinds of
// extensions the operating system supports.
static QString checkBinary(const QDir &dir, const QString &binary)
{
// naive UNIX approach
const QFileInfo info(dir.filePath(binary));
if (info.isFile() && info.isExecutable())
return info.absoluteFilePath();
// Does the OS have some weird extension concept or does the
// binary have a 3 letter extension?
if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost())
return {};
const int dotIndex = binary.lastIndexOf(QLatin1Char('.'));
if (dotIndex != -1 && dotIndex == binary.size() - 4)
return {};
switch (HostOsInfo::hostOs()) {
case OsTypeLinux:
case OsTypeOtherUnix:
case OsTypeOther:
break;
case OsTypeWindows: {
static const char *windowsExtensions[] = {".cmd", ".bat", ".exe", ".com"};
// Check the Windows extensions using the order
const int windowsExtensionCount = sizeof(windowsExtensions)/sizeof(const char*);
for (int e = 0; e < windowsExtensionCount; e ++) {
const QFileInfo windowsBinary(dir.filePath(binary + QLatin1String(windowsExtensions[e])));
if (windowsBinary.isFile() && windowsBinary.isExecutable())
return windowsBinary.absoluteFilePath();
}
}
break;
case OsTypeMac: {
// Check for Mac app folders
const QFileInfo appFolder(dir.filePath(binary + QLatin1String(".app")));
if (appFolder.isDir()) {
QString macBinaryPath = appFolder.absoluteFilePath();
macBinaryPath += QLatin1String("/Contents/MacOS/");
macBinaryPath += binary;
const QFileInfo macBinary(macBinaryPath);
if (macBinary.isFile() && macBinary.isExecutable())
return macBinary.absoluteFilePath();
}
}
break;
}
return {};
}
QString QtcProcess::locateBinary(const QString &path, const QString &binary)
{
// Absolute file?
const QFileInfo absInfo(binary);
if (absInfo.isAbsolute())
return checkBinary(absInfo.dir(), absInfo.fileName());
// Windows finds binaries in the current directory
if (HostOsInfo::isWindowsHost()) {
const QString currentDirBinary = checkBinary(QDir::current(), binary);
if (!currentDirBinary.isEmpty())
return currentDirBinary;
}
const QStringList paths = path.split(HostOsInfo::pathListSeparator());
if (paths.empty())
return {};
const QStringList::const_iterator cend = paths.constEnd();
for (QStringList::const_iterator it = paths.constBegin(); it != cend; ++it) {
const QDir dir(*it);
const QString rc = checkBinary(dir, binary);
if (!rc.isEmpty())
return rc;
}
return {};
}
Environment QtcProcess::systemEnvironmentForBinary(const FilePath &filePath) Environment QtcProcess::systemEnvironmentForBinary(const FilePath &filePath)
{ {
if (filePath.needsDevice()) { if (filePath.needsDevice()) {

View File

@@ -127,11 +127,8 @@ public:
// These (or some of them) may be potentially moved outside of the class. // These (or some of them) may be potentially moved outside of the class.
// For some we may aggregate in another public utils class (or subclass of QtcProcess)? // For some we may aggregate in another public utils class (or subclass of QtcProcess)?
// TODO: How below 2 methods relate to QtcProcess? // TODO: How below method relates to QtcProcess?
// Action: move/merge them somewhere else, FilePath::searchInPath() ? // Action: move/merge it somewhere else
// Helpers to find binaries. Do not use it for other path variables
// and file types.
static QString locateBinary(const QString &path, const QString &binary);
static QString normalizeNewlines(const QString &text); static QString normalizeNewlines(const QString &text);
// TODO: Unused currently? Should it serve as a compartment for contrary of remoteEnvironment? // TODO: Unused currently? Should it serve as a compartment for contrary of remoteEnvironment?

View File

@@ -154,9 +154,10 @@ public:
int currentLimit() const; int currentLimit() const;
TaskAction childDone(bool success); TaskAction childDone(bool success);
void groupDone(bool success); void groupDone(bool success);
void treeDone(bool success);
void invokeEndHandler(bool success); void invokeEndHandler(bool success);
void resetSuccessBit(); void resetSuccessBit(); // only on start
void updateSuccessBit(bool success); void updateSuccessBit(bool success); // only on childDone
void createStorages(); void createStorages();
void deleteStorages(); void deleteStorages();
@@ -233,11 +234,7 @@ public:
QTC_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't " QTC_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't "
"exist in task tree. Its handlers will never be called.")); "exist in task tree. Its handlers will never be called."));
} }
const TaskAction action = m_root->start(); m_root->start();
if (action == TaskAction::StopWithDone)
emitDone();
else if (action == TaskAction::StopWithError)
emitError();
} }
void stop() { void stop() {
QTC_ASSERT(m_root, return); QTC_ASSERT(m_root, return);
@@ -366,17 +363,17 @@ TaskAction TaskContainer::start()
const bool success = groupAction == TaskAction::StopWithDone; const bool success = groupAction == TaskAction::StopWithDone;
m_taskTreePrivate->advanceProgress(m_taskCount); m_taskTreePrivate->advanceProgress(m_taskCount);
invokeEndHandler(success); invokeEndHandler(success);
groupDone(success);
return groupAction; return groupAction;
} }
resetSuccessBit(); resetSuccessBit();
GuardLocker locker(m_startGuard);
return startChildren(0); return startChildren(0);
} }
TaskAction TaskContainer::startChildren(int nextChild) TaskAction TaskContainer::startChildren(int nextChild)
{ {
GuardLocker locker(m_startGuard);
const int childCount = m_children.size(); const int childCount = m_children.size();
for (int i = nextChild; i < childCount; ++i) { for (int i = nextChild; i < childCount; ++i) {
const int limit = currentLimit(); const int limit = currentLimit();
@@ -396,6 +393,7 @@ TaskAction TaskContainer::startChildren(int nextChild)
for (int j = i + 1; j < limit; ++j) for (int j = i + 1; j < limit; ++j)
skippedTaskCount += m_children.at(j)->taskCount(); skippedTaskCount += m_children.at(j)->taskCount();
m_taskTreePrivate->advanceProgress(skippedTaskCount); m_taskTreePrivate->advanceProgress(skippedTaskCount);
treeDone(finalizeAction == TaskAction::StopWithDone);
return finalizeAction; return finalizeAction;
} }
@@ -458,13 +456,19 @@ TaskAction TaskContainer::childDone(bool success)
void TaskContainer::groupDone(bool success) void TaskContainer::groupDone(bool success)
{ {
if (isStarting())
return;
if (m_parentContainer) { if (m_parentContainer) {
m_parentContainer->childDone(success); if (!m_parentContainer->isStarting())
m_parentContainer->childDone(success);
return; return;
} }
if (!isStarting())
treeDone(success);
}
void TaskContainer::treeDone(bool success)
{
if (m_parentContainer)
return;
if (success) if (success)
m_taskTreePrivate->emitDone(); m_taskTreePrivate->emitDone();
else else

View File

@@ -45,6 +45,7 @@ add_subdirectory(cvs)
add_subdirectory(designer) add_subdirectory(designer)
add_subdirectory(docker) add_subdirectory(docker)
add_subdirectory(fakevim) add_subdirectory(fakevim)
add_subdirectory(fossil)
add_subdirectory(genericprojectmanager) add_subdirectory(genericprojectmanager)
add_subdirectory(git) add_subdirectory(git)
add_subdirectory(mercurial) add_subdirectory(mercurial)

View File

@@ -36,7 +36,6 @@
#include <utils/persistentsettings.h> #include <utils/persistentsettings.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <QApplication> #include <QApplication>

View File

@@ -609,7 +609,7 @@ void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
QAction *action = new QAction(Tr::tr("Copy"), &menu); QAction *action = new QAction(Tr::tr("Copy"), &menu);
action->setShortcut(QKeySequence(QKeySequence::Copy)); action->setShortcut(QKeySequence(QKeySequence::Copy));
action->setEnabled(resultsAvailable && clicked.isValid()); action->setEnabled(resultsAvailable && clicked.isValid());
connect(action, &QAction::triggered, this, [this, clicked] { connect(action, &QAction::triggered, this, [this, &clicked] {
onCopyItemTriggered(clicked); onCopyItemTriggered(clicked);
}); });
menu.addAction(action); menu.addAction(action);
@@ -627,14 +627,14 @@ void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
const auto correlatingItem = (enabled && clicked.isValid()) ? clicked.findTestTreeItem() : nullptr; const auto correlatingItem = (enabled && clicked.isValid()) ? clicked.findTestTreeItem() : nullptr;
action = new QAction(Tr::tr("Run This Test"), &menu); action = new QAction(Tr::tr("Run This Test"), &menu);
action->setEnabled(correlatingItem && correlatingItem->canProvideTestConfiguration()); action->setEnabled(correlatingItem && correlatingItem->canProvideTestConfiguration());
connect(action, &QAction::triggered, this, [this, clicked] { connect(action, &QAction::triggered, this, [this, &clicked] {
onRunThisTestTriggered(TestRunMode::Run, clicked); onRunThisTestTriggered(TestRunMode::Run, clicked);
}); });
menu.addAction(action); menu.addAction(action);
action = new QAction(Tr::tr("Run This Test Without Deployment"), &menu); action = new QAction(Tr::tr("Run This Test Without Deployment"), &menu);
action->setEnabled(correlatingItem && correlatingItem->canProvideTestConfiguration()); action->setEnabled(correlatingItem && correlatingItem->canProvideTestConfiguration());
connect(action, &QAction::triggered, this, [this, clicked] { connect(action, &QAction::triggered, this, [this, &clicked] {
onRunThisTestTriggered(TestRunMode::RunWithoutDeploy, clicked); onRunThisTestTriggered(TestRunMode::RunWithoutDeploy, clicked);
}); });
menu.addAction(action); menu.addAction(action);
@@ -648,14 +648,14 @@ void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
} }
} }
action->setEnabled(debugEnabled); action->setEnabled(debugEnabled);
connect(action, &QAction::triggered, this, [this, clicked] { connect(action, &QAction::triggered, this, [this, &clicked] {
onRunThisTestTriggered(TestRunMode::Debug, clicked); onRunThisTestTriggered(TestRunMode::Debug, clicked);
}); });
menu.addAction(action); menu.addAction(action);
action = new QAction(Tr::tr("Debug This Test Without Deployment"), &menu); action = new QAction(Tr::tr("Debug This Test Without Deployment"), &menu);
action->setEnabled(debugEnabled); action->setEnabled(debugEnabled);
connect(action, &QAction::triggered, this, [this, clicked] { connect(action, &QAction::triggered, this, [this, &clicked] {
onRunThisTestTriggered(TestRunMode::DebugWithoutDeploy, clicked); onRunThisTestTriggered(TestRunMode::DebugWithoutDeploy, clicked);
}); });
menu.addAction(action); menu.addAction(action);

View File

@@ -7,7 +7,6 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>

View File

@@ -33,7 +33,6 @@
#include <utils/mimeutils.h> #include <utils/mimeutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <utils/textutils.h> #include <utils/textutils.h>

View File

@@ -25,7 +25,6 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/textutils.h> #include <utils/textutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QTextBlock> #include <QTextBlock>
#include <QWidget> #include <QWidget>

View File

@@ -38,7 +38,11 @@ void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
#else #else
style.SortIncludes = false; style.SortIncludes = false;
#endif #endif
#if LLVM_VERSION_MAJOR >= 16
style.SortUsingDeclarations = clang::format::FormatStyle::SUD_Never;
#else
style.SortUsingDeclarations = false; style.SortUsingDeclarations = false;
#endif
// This is a separate pass, don't do it unless it's the full formatting. // This is a separate pass, don't do it unless it's the full formatting.
style.FixNamespaceComments = false; style.FixNamespaceComments = false;

View File

@@ -151,7 +151,11 @@ clang::format::FormatStyle qtcStyle()
#else #else
style.SortIncludes = true; style.SortIncludes = true;
#endif #endif
#if LLVM_VERSION_MAJOR >= 16
style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
#else
style.SortUsingDeclarations = true; style.SortUsingDeclarations = true;
#endif
style.SpaceAfterCStyleCast = true; style.SpaceAfterCStyleCast = true;
style.SpaceAfterTemplateKeyword = false; style.SpaceAfterTemplateKeyword = false;
style.SpaceBeforeAssignmentOperators = true; style.SpaceBeforeAssignmentOperators = true;

View File

@@ -144,6 +144,7 @@ TaskItem clangToolTask(const AnalyzeInputData &input,
const auto onProcessSetup = [=](QtcProcess &process) { const auto onProcessSetup = [=](QtcProcess &process) {
process.setEnvironment(input.environment); process.setEnvironment(input.environment);
process.setUseCtrlCStub(true); process.setUseCtrlCStub(true);
process.setLowPriority();
process.setWorkingDirectory(input.outputDirPath); // Current clang-cl puts log file into working dir. process.setWorkingDirectory(input.outputDirPath); // Current clang-cl puts log file into working dir.
const ClangToolStorage *data = storage.activeStorage(); const ClangToolStorage *data = storage.activeStorage();

View File

@@ -27,7 +27,6 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/filesystemwatcher.h> #include <utils/filesystemwatcher.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QFileDialog> #include <QFileDialog>

View File

@@ -347,19 +347,19 @@ void CorePlugin::addToPathChooserContextMenu(Utils::PathChooser *pathChooser, QM
QList<QAction*> actions = menu->actions(); QList<QAction*> actions = menu->actions();
QAction *firstAction = actions.isEmpty() ? nullptr : actions.first(); QAction *firstAction = actions.isEmpty() ? nullptr : actions.first();
if (QDir().exists(pathChooser->filePath().toString())) { if (pathChooser->filePath().exists()) {
auto *showInGraphicalShell = new QAction(Core::FileUtils::msgGraphicalShellAction(), menu); auto showInGraphicalShell = new QAction(FileUtils::msgGraphicalShellAction(), menu);
connect(showInGraphicalShell, &QAction::triggered, pathChooser, [pathChooser] { connect(showInGraphicalShell, &QAction::triggered, pathChooser, [pathChooser] {
Core::FileUtils::showInGraphicalShell(pathChooser, pathChooser->filePath()); Core::FileUtils::showInGraphicalShell(pathChooser, pathChooser->filePath());
}); });
menu->insertAction(firstAction, showInGraphicalShell); menu->insertAction(firstAction, showInGraphicalShell);
auto *showInTerminal = new QAction(Core::FileUtils::msgTerminalHereAction(), menu); auto showInTerminal = new QAction(FileUtils::msgTerminalHereAction(), menu);
connect(showInTerminal, &QAction::triggered, pathChooser, [pathChooser] { connect(showInTerminal, &QAction::triggered, pathChooser, [pathChooser] {
if (pathChooser->openTerminalHandler()) if (pathChooser->openTerminalHandler())
pathChooser->openTerminalHandler()(); pathChooser->openTerminalHandler()();
else else
FileUtils::openTerminal(pathChooser->filePath()); FileUtils::openTerminal(pathChooser->filePath(), {});
}); });
menu->insertAction(firstAction, showInTerminal); menu->insertAction(firstAction, showInTerminal);

View File

@@ -41,6 +41,7 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/checkablemessagebox.h> #include <utils/checkablemessagebox.h>
#include <utils/environment.h>
#include <utils/executeondestruction.h> #include <utils/executeondestruction.h>
#include <utils/filepath.h> #include <utils/filepath.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
@@ -2618,7 +2619,7 @@ void EditorManagerPrivate::openTerminal()
{ {
if (!d->m_contextMenuEntry || d->m_contextMenuEntry->filePath().isEmpty()) if (!d->m_contextMenuEntry || d->m_contextMenuEntry->filePath().isEmpty())
return; return;
FileUtils::openTerminal(d->m_contextMenuEntry->filePath().parentDir()); FileUtils::openTerminal(d->m_contextMenuEntry->filePath().parentDir(), {});
} }
void EditorManagerPrivate::findInDirectory() void EditorManagerPrivate::findInDirectory()

View File

@@ -32,15 +32,6 @@
#include <QTextCodec> #include <QTextCodec>
#include <QWidget> #include <QWidget>
#ifdef Q_OS_WIN
#include <windows.h>
#include <stdlib.h>
#include <cstring>
#endif
using namespace Utils; using namespace Utils;
namespace Core { namespace Core {
@@ -111,69 +102,10 @@ void FileUtils::showInFileSystemView(const FilePath &path)
navWidget->syncWithFilePath(path); navWidget->syncWithFilePath(path);
} }
static void startTerminalEmulator(const QString &workingDir, const Environment &env)
{
#ifdef Q_OS_WIN
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pinfo;
ZeroMemory(&pinfo, sizeof(pinfo));
static const auto quoteWinCommand = [](const QString &program) {
const QChar doubleQuote = QLatin1Char('"');
// add the program as the first arg ... it works better
QString programName = program;
programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote)
&& programName.contains(QLatin1Char(' '))) {
programName.prepend(doubleQuote);
programName.append(doubleQuote);
}
return programName;
};
const QString cmdLine = quoteWinCommand(qtcEnvironmentVariable("COMSPEC"));
// cmdLine is assumed to be detached -
// https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083
const QString totalEnvironment = env.toStringList().join(QChar(QChar::Null)) + QChar(QChar::Null);
LPVOID envPtr = (env != Environment::systemEnvironment())
? (WCHAR *)(totalEnvironment.utf16()) : nullptr;
const bool success = CreateProcessW(0, (WCHAR *)cmdLine.utf16(),
0, 0, FALSE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
envPtr, workingDir.isEmpty() ? 0 : (WCHAR *)workingDir.utf16(),
&si, &pinfo);
if (success) {
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
}
#else
const TerminalCommand term = TerminalCommand::terminalEmulator();
QProcess process;
process.setProgram(term.command);
process.setArguments(ProcessArgs::splitArgs(term.openArgs));
process.setProcessEnvironment(env.toProcessEnvironment());
process.setWorkingDirectory(workingDir);
process.startDetached();
#endif
}
void FileUtils::openTerminal(const FilePath &path)
{
openTerminal(path, Environment::systemEnvironment());
}
void FileUtils::openTerminal(const FilePath &path, const Environment &env) void FileUtils::openTerminal(const FilePath &path, const Environment &env)
{ {
const QFileInfo fileInfo = path.toFileInfo(); QTC_ASSERT(DeviceFileHooks::instance().openTerminal, return);
const QString workingDir = QDir::toNativeSeparators(fileInfo.isDir() ? DeviceFileHooks::instance().openTerminal(path, env);
fileInfo.absoluteFilePath() :
fileInfo.absolutePath());
startTerminalEmulator(workingDir, env);
} }
QString FileUtils::msgFindInDirectory() QString FileUtils::msgFindInDirectory()

View File

@@ -22,7 +22,6 @@ struct CORE_EXPORT FileUtils
// Helpers for common directory browser options. // Helpers for common directory browser options.
static void showInGraphicalShell(QWidget *parent, const Utils::FilePath &path); static void showInGraphicalShell(QWidget *parent, const Utils::FilePath &path);
static void showInFileSystemView(const Utils::FilePath &path); static void showInFileSystemView(const Utils::FilePath &path);
static void openTerminal(const Utils::FilePath &path);
static void openTerminal(const Utils::FilePath &path, const Utils::Environment &env); static void openTerminal(const Utils::FilePath &path, const Utils::Environment &env);
static QString msgFindInDirectory(); static QString msgFindInDirectory();
static QString msgFileSystemAction(); static QString msgFileSystemAction();

View File

@@ -29,7 +29,6 @@
#include <utils/mimeutils.h> #include <utils/mimeutils.h>
#include <utils/minimizableinfobars.h> #include <utils/minimizableinfobars.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <QApplication> #include <QApplication>

View File

@@ -3475,7 +3475,6 @@ public:
} }
bool hasSourceFile() const { return m_headerFile != m_sourceFile; } bool hasSourceFile() const { return m_headerFile != m_sourceFile; }
bool isHeaderHeaderFile() const { return m_isHeaderHeaderFile; }
protected: protected:
void insertAndIndent(const RefactoringFilePtr &file, void insertAndIndent(const RefactoringFilePtr &file,
@@ -3671,6 +3670,7 @@ protected:
const CppRefactoringChanges m_changes; const CppRefactoringChanges m_changes;
const InsertionPointLocator m_locator; const InsertionPointLocator m_locator;
const CppRefactoringFilePtr m_headerFile; const CppRefactoringFilePtr m_headerFile;
bool m_isHeaderHeaderFile = false; // the "header" (where the class is defined) can be a source file
const CppRefactoringFilePtr m_sourceFile; const CppRefactoringFilePtr m_sourceFile;
CppQuickFixSettings *const m_settings = CppQuickFixProjectsSettings::getQuickFixSettings( CppQuickFixSettings *const m_settings = CppQuickFixProjectsSettings::getQuickFixSettings(
ProjectExplorer::ProjectTree::currentProject()); ProjectExplorer::ProjectTree::currentProject());
@@ -3683,7 +3683,6 @@ private:
InsertionLocation m_sourceFileInsertionPoint; InsertionLocation m_sourceFileInsertionPoint;
QString m_sourceFileCode; QString m_sourceFileCode;
QMap<InsertionPointLocator::AccessSpec, QString> m_headerFileCode; QMap<InsertionPointLocator::AccessSpec, QString> m_headerFileCode;
bool m_isHeaderHeaderFile; // the "header" (where the class is defined) can be a source file
}; };
class GenerateGetterSetterOp : public CppQuickFixOperation class GenerateGetterSetterOp : public CppQuickFixOperation
@@ -9018,7 +9017,7 @@ private:
addSourceFileCode(implCode); addSourceFileCode(implCode);
} else if (constructorLocation } else if (constructorLocation
== CppQuickFixSettings::FunctionLocation::OutsideClass) { == CppQuickFixSettings::FunctionLocation::OutsideClass) {
if (isHeaderHeaderFile()) if (m_isHeaderHeaderFile)
implCode.prepend("inline "); implCode.prepend("inline ");
insertAndIndent(m_headerFile, implLoc, implCode); insertAndIndent(m_headerFile, implLoc, implCode);
} }

View File

@@ -0,0 +1,22 @@
add_qtc_plugin(Fossil
PLUGIN_DEPENDS
Core TextEditor ProjectExplorer VcsBase
SOURCES
annotationhighlighter.cpp annotationhighlighter.h
branchinfo.h
commiteditor.cpp commiteditor.h
configuredialog.cpp configuredialog.h configuredialog.ui
constants.h
fossil.qrc
fossilclient.cpp fossilclient.h
fossilcommitpanel.ui
fossilcommitwidget.cpp fossilcommitwidget.h
fossileditor.cpp fossileditor.h
fossilplugin.cpp fossilplugin.h
fossilsettings.cpp fossilsettings.h
pullorpushdialog.cpp pullorpushdialog.h pullorpushdialog.ui
revertdialog.ui
revisioninfo.h
wizard/fossiljsextension.cpp wizard/fossiljsextension.h
)

View File

@@ -0,0 +1,20 @@
{
\"Name\" : \"Fossil\",
\"Version\" : \"$$QTCREATOR_VERSION\",
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
\"DisabledByDefault\" : true,
\"Vendor\" : \"Artur Shepilko\",
\"Copyright\" : \"(C) 2018 Artur Shepilko\",
\"License\" : [ \"Commercial Usage\",
\"\",
\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\",
\"\",
\"GNU General Public License Usage\",
\"\",
\"Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this plugin. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\"
],
\"Category\" : \"Version Control\",
\"Description\" : \"Fossil SCM integration.\",
\"Url\" : \"http://www.qt.io\",
$$dependencyList
}

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "annotationhighlighter.h"
#include "constants.h"
#include <utils/qtcassert.h>
namespace Fossil {
namespace Internal {
FossilAnnotationHighlighter::FossilAnnotationHighlighter(const ChangeNumbers &changeNumbers,
QTextDocument *document) :
VcsBase::BaseAnnotationHighlighter(changeNumbers, document),
m_changesetIdPattern(Constants::CHANGESET_ID)
{
QTC_CHECK(m_changesetIdPattern.isValid());
}
QString FossilAnnotationHighlighter::changeNumber(const QString &block) const
{
QRegularExpressionMatch changesetIdMatch = m_changesetIdPattern.match(block);
if (changesetIdMatch.hasMatch())
return changesetIdMatch.captured(1);
return {};
}
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,46 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <vcsbase/baseannotationhighlighter.h>
#include <QRegularExpression>
namespace Fossil {
namespace Internal {
class FossilAnnotationHighlighter : public VcsBase::BaseAnnotationHighlighter
{
public:
explicit FossilAnnotationHighlighter(const ChangeNumbers &changeNumbers,
QTextDocument *document = nullptr);
private:
QString changeNumber(const QString &block) const final;
QRegularExpression m_changesetIdPattern;
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,52 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QString>
namespace Fossil {
namespace Internal {
class BranchInfo
{
public:
enum BranchFlag {
Current = 0x01,
Closed = 0x02,
Private = 0x04
};
Q_DECLARE_FLAGS(BranchFlags, BranchFlag)
bool isCurrent() const { return flags.testFlag(Current); }
QString name;
BranchFlags flags;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(BranchInfo::BranchFlags)
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "branchinfo.h"
#include "commiteditor.h"
#include "constants.h"
#include "fossilcommitwidget.h"
#include <coreplugin/idocument.h>
#include <vcsbase/submitfilemodel.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
namespace Fossil {
namespace Internal {
CommitEditor::CommitEditor() :
VcsBase::VcsBaseSubmitEditor(new FossilCommitWidget)
{
document()->setPreferredDisplayName(tr("Commit Editor"));
}
FossilCommitWidget *CommitEditor::commitWidget()
{
return static_cast<FossilCommitWidget *>(widget());
}
void CommitEditor::setFields(const Utils::FilePath &repositoryRoot, const BranchInfo &branch,
const QStringList &tags, const QString &userName,
const QList<VcsBase::VcsBaseClient::StatusItem> &repoStatus)
{
FossilCommitWidget *fossilWidget = commitWidget();
QTC_ASSERT(fossilWidget, return);
fossilWidget->setFields(repositoryRoot, branch, tags, userName);
m_fileModel = new VcsBase::SubmitFileModel(this);
m_fileModel->setRepositoryRoot(repositoryRoot);
m_fileModel->setFileStatusQualifier([](const QString &status, const QVariant &) {
if (status == Constants::FSTATUS_ADDED
|| status == Constants::FSTATUS_ADDED_BY_MERGE
|| status == Constants::FSTATUS_ADDED_BY_INTEGRATE) {
return VcsBase::SubmitFileModel::FileAdded;
} else if (status == Constants::FSTATUS_EDITED
|| status == Constants::FSTATUS_UPDATED_BY_MERGE
|| status == Constants::FSTATUS_UPDATED_BY_INTEGRATE) {
return VcsBase::SubmitFileModel::FileModified;
} else if (status == Constants::FSTATUS_DELETED) {
return VcsBase::SubmitFileModel::FileDeleted;
} else if (status == Constants::FSTATUS_RENAMED) {
return VcsBase::SubmitFileModel::FileRenamed;
}
return VcsBase::SubmitFileModel::FileStatusUnknown;
});
const QList<VcsBase::VcsBaseClient::StatusItem> toAdd = Utils::filtered(repoStatus,
[](const VcsBase::VcsBaseClient::StatusItem &item)
{ return item.flags != Constants::FSTATUS_UNKNOWN; });
for (const VcsBase::VcsBaseClient::StatusItem &item : toAdd)
m_fileModel->addFile(item.file, item.flags);
setFileModel(m_fileModel);
}
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <vcsbase/vcsbaseclient.h>
#include <vcsbase/vcsbasesubmiteditor.h>
namespace VcsBase { class SubmitFileModel; }
namespace Fossil {
namespace Internal {
class BranchInfo;
class FossilCommitWidget;
class CommitEditor : public VcsBase::VcsBaseSubmitEditor
{
Q_OBJECT
public:
CommitEditor();
void setFields(const Utils::FilePath &repositoryRoot, const BranchInfo &branch,
const QStringList &tags, const QString &userName,
const QList<VcsBase::VcsBaseClient::StatusItem> &repoStatus);
FossilCommitWidget *commitWidget();
private:
VcsBase::SubmitFileModel *m_fileModel = nullptr;
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "configuredialog.h"
#include "ui_configuredialog.h"
#include "fossilsettings.h"
#include <utils/pathchooser.h>
#include <QDir>
namespace Fossil {
namespace Internal {
class ConfigureDialogPrivate {
public:
RepositorySettings settings() const
{
return {m_ui.userLineEdit->text().trimmed(),
m_ui.sslIdentityFilePathChooser->filePath().toString(),
m_ui.disableAutosyncCheckBox->isChecked()
? RepositorySettings::AutosyncOff : RepositorySettings::AutosyncOn};
}
void updateUi() {
m_ui.userLineEdit->setText(m_settings.user.trimmed());
m_ui.userLineEdit->selectAll();
m_ui.sslIdentityFilePathChooser->setPath(QDir::toNativeSeparators(m_settings.sslIdentityFile));
m_ui.disableAutosyncCheckBox->setChecked(m_settings.autosync == RepositorySettings::AutosyncOff);
}
Ui::ConfigureDialog m_ui;
RepositorySettings m_settings;
};
ConfigureDialog::ConfigureDialog(QWidget *parent) : QDialog(parent),
d(new ConfigureDialogPrivate)
{
d->m_ui.setupUi(this);
d->m_ui.sslIdentityFilePathChooser->setExpectedKind(Utils::PathChooser::File);
d->m_ui.sslIdentityFilePathChooser->setPromptDialogTitle(tr("SSL/TLS Identity Key"));
setWindowTitle(tr("Configure Repository"));
d->updateUi();
}
ConfigureDialog::~ConfigureDialog()
{
delete d;
}
const RepositorySettings ConfigureDialog::settings() const
{
return d->settings();
}
void ConfigureDialog::setSettings(const RepositorySettings &settings)
{
d->m_settings = settings;
d->updateUi();
}
void ConfigureDialog::changeEvent(QEvent *e)
{
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
d->m_ui.retranslateUi(this);
break;
default:
break;
}
}
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,55 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QDialog>
namespace Fossil {
namespace Internal {
struct RepositorySettings;
class ConfigureDialogPrivate;
class ConfigureDialog : public QDialog
{
Q_OBJECT
public:
explicit ConfigureDialog(QWidget *parent = nullptr);
~ConfigureDialog() final;
const RepositorySettings settings() const;
void setSettings(const RepositorySettings &settings);
protected:
void changeEvent(QEvent *e) final;
private:
ConfigureDialogPrivate *d = nullptr;
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Fossil::Internal::ConfigureDialog</class>
<widget class="QDialog" name="Fossil::Internal::ConfigureDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>385</width>
<height>202</height>
</rect>
</property>
<property name="windowTitle">
<string>Configure Repository</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="repoUserGroupBox">
<property name="title">
<string>Repository User</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="userLabel">
<property name="text">
<string>User:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="userLineEdit">
<property name="toolTip">
<string>Existing user to become an author of changes made to the repository.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="repoSettingsGroupBox">
<property name="title">
<string>Repository Settings</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="sslIdentityFileLabel">
<property name="text">
<string>SSL/TLS identity:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::PathChooser" name="sslIdentityFilePathChooser" native="true">
<property name="toolTip">
<string>SSL/TLS client identity key to use if requested by the server.</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="disableAutosyncCheckBox">
<property name="toolTip">
<string>Disable automatic pull prior to commit or update and automatic push after commit or tag or branch creation.</string>
</property>
<property name="text">
<string>Disable auto-sync</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::PathChooser</class>
<extends>QWidget</extends>
<header location="global">utils/pathchooser.h</header>
<container>1</container>
<slots>
<signal>editingFinished()</signal>
<signal>browsingFinished()</signal>
</slots>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Fossil::Internal::ConfigureDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Fossil::Internal::ConfigureDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,111 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QtGlobal>
namespace Fossil {
namespace Constants {
const char VCS_ID_FOSSIL[] = "I.Fossil";
const char FOSSIL[] = "fossil";
#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
const char FOSSILREPO[] = "_FOSSIL_";
#else
const char FOSSILREPO[] = ".fslckout";
#endif
const char FOSSILDEFAULT[] = "fossil";
const char FOSSIL_CONTEXT[] = "Fossil Context";
const char FOSSIL_FILE_SUFFIX[] = ".fossil";
const char FOSSIL_FILE_FILTER[] = "Fossil Repositories (*.fossil *.fsl);;All Files (*)";
//changeset identifiers
const char CHANGESET_ID[] = "([0-9a-f]{5,40})"; // match and capture
const char CHANGESET_ID_EXACT[] = "[0-9a-f]{5,40}"; // match
//diff chunk identifiers
const char DIFFFILE_ID_EXACT[] = "[+]{3} (.*)\\s*"; // match and capture
//BaseEditorParameters
const char FILELOG_ID[] = "Fossil File Log Editor";
const char FILELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("VCS", "Fossil File Log Editor");
const char LOGAPP[] = "text/vnd.qtcreator.fossil.log";
const char ANNOTATELOG_ID[] = "Fossil Annotation Editor";
const char ANNOTATELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("VCS", "Fossil Annotation Editor");
const char ANNOTATEAPP[] = "text/vnd.qtcreator.fossil.annotation";
const char DIFFLOG_ID[] = "Fossil Diff Editor";
const char DIFFLOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("VCS", "Fossil Diff Editor");
const char DIFFAPP[] = "text/x-patch";
//SubmitEditorParameters
const char COMMIT_ID[] = "Fossil Commit Log Editor";
const char COMMIT_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("VCS", "Fossil Commit Log Editor");
const char COMMITMIMETYPE[] = "text/vnd.qtcreator.fossil.commit";
//menu items
//File menu actions
const char ADD[] = "Fossil.AddSingleFile";
const char DELETE[] = "Fossil.DeleteSingleFile";
const char ANNOTATE[] = "Fossil.Annotate";
const char DIFF[] = "Fossil.DiffSingleFile";
const char LOG[] = "Fossil.LogSingleFile";
const char REVERT[] = "Fossil.RevertSingleFile";
const char STATUS[] = "Fossil.Status";
//directory menu Actions
const char DIFFMULTI[] = "Fossil.Action.DiffMulti";
const char REVERTMULTI[] = "Fossil.Action.RevertAll";
const char STATUSMULTI[] = "Fossil.Action.StatusMulti";
const char LOGMULTI[] = "Fossil.Action.LogMulti";
//repository menu actions
const char PULL[] = "Fossil.Action.Pull";
const char PUSH[] = "Fossil.Action.Push";
const char UPDATE[] = "Fossil.Action.Update";
const char COMMIT[] = "Fossil.Action.Commit";
const char CONFIGURE_REPOSITORY[] = "Fossil.Action.Settings";
const char CREATE_REPOSITORY[] = "Fossil.Action.CreateRepository";
// File status hint
const char FSTATUS_ADDED[] = "Added";
const char FSTATUS_ADDED_BY_MERGE[] = "Added by Merge";
const char FSTATUS_ADDED_BY_INTEGRATE[] = "Added by Integrate";
const char FSTATUS_DELETED[] = "Deleted";
const char FSTATUS_EDITED[] = "Edited";
const char FSTATUS_UPDATED_BY_MERGE[] = "Updated by Merge";
const char FSTATUS_UPDATED_BY_INTEGRATE[] = "Updated by Integrate";
const char FSTATUS_RENAMED[] = "Renamed";
const char FSTATUS_UNKNOWN[] = "Unknown";
// Fossil Json Wizards
const char WIZARD_PATH[] = ":/fossil/wizard";
} // namespace Constants
} // namespace Fossil

View File

@@ -0,0 +1,39 @@
import qbs 1.0
QtcPlugin {
name: "Fossil"
Depends { name: "Qt.widgets" }
Depends { name: "Utils" }
Depends { name: "Core" }
Depends { name: "TextEditor" }
Depends { name: "ProjectExplorer" }
Depends { name: "VcsBase" }
files: [
"constants.h",
"fossilclient.cpp", "fossilclient.h",
"fossilplugin.cpp", "fossilplugin.h",
"fossilsettings.cpp", "fossilsettings.h",
"commiteditor.cpp", "commiteditor.h",
"fossilcommitwidget.cpp", "fossilcommitwidget.h",
"fossileditor.cpp", "fossileditor.h",
"annotationhighlighter.cpp", "annotationhighlighter.h",
"pullorpushdialog.cpp", "pullorpushdialog.h", "pullorpushdialog.ui",
"branchinfo.h",
"configuredialog.cpp", "configuredialog.h", "configuredialog.ui",
"revisioninfo.h",
"fossil.qrc",
"revertdialog.ui",
"fossilcommitpanel.ui",
]
Group {
name: "Wizards"
prefix: "wizard/"
files: [
"fossiljsextension.h", "fossiljsextension.cpp",
]
}
}

View File

@@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/fossil">
<file>wizard/projects/vcs/icon.png</file>
<file>wizard/projects/vcs/icon@2x.png</file>
<file>wizard/projects/vcs/wizard.json</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "fossilsettings.h"
#include "branchinfo.h"
#include "revisioninfo.h"
#include <vcsbase/vcsbaseclient.h>
#include <QList>
namespace Fossil {
namespace Internal {
class FossilSettings;
class FossilPluginPrivate;
class FossilClient : public VcsBase::VcsBaseClient
{
Q_OBJECT
public:
enum SupportedFeature {
AnnotateBlameFeature = 0x2,
TimelineWidthFeature = 0x4,
DiffIgnoreWhiteSpaceFeature = 0x8,
TimelinePathFeature = 0x10,
AnnotateRevisionFeature = 0x20,
InfoHashFeature = 0x40,
AllSupportedFeatures = // | all defined features
AnnotateBlameFeature
| TimelineWidthFeature
| DiffIgnoreWhiteSpaceFeature
| TimelinePathFeature
| AnnotateRevisionFeature
| InfoHashFeature
};
Q_DECLARE_FLAGS(SupportedFeatures, SupportedFeature)
static unsigned makeVersionNumber(int major, int minor, int patch);
static QString makeVersionString(unsigned version);
explicit FossilClient(FossilSettings *settings);
FossilSettings &settings() const;
unsigned int synchronousBinaryVersion() const;
BranchInfo synchronousCurrentBranch(const Utils::FilePath &workingDirectory);
QList<BranchInfo> synchronousBranchQuery(const Utils::FilePath &workingDirectory);
RevisionInfo synchronousRevisionQuery(const Utils::FilePath &workingDirectory,
const QString &id = {}, bool getCommentMsg = false) const;
QStringList synchronousTagQuery(const Utils::FilePath &workingDirectory, const QString &id = {});
RepositorySettings synchronousSettingsQuery(const Utils::FilePath &workingDirectory);
bool synchronousSetSetting(const Utils::FilePath &workingDirectory, const QString &property,
const QString &value = {}, bool isGlobal = false);
bool synchronousConfigureRepository(const Utils::FilePath &workingDirectory,
const RepositorySettings &newSettings,
const RepositorySettings &currentSettings = {});
QString synchronousUserDefaultQuery(const Utils::FilePath &workingDirectory);
bool synchronousSetUserDefault(const Utils::FilePath &workingDirectory, const QString &userName);
QString synchronousGetRepositoryURL(const Utils::FilePath &workingDirectory);
QString synchronousTopic(const Utils::FilePath &workingDirectory);
bool synchronousCreateRepository(const Utils::FilePath &workingDirectory,
const QStringList &extraOptions = {}) final;
bool synchronousMove(const Utils::FilePath &workingDir, const QString &from, const QString &to,
const QStringList &extraOptions = {}) final;
bool synchronousPull(const Utils::FilePath &workingDir, const QString &srcLocation,
const QStringList &extraOptions = {}) final;
bool synchronousPush(const Utils::FilePath &workingDir, const QString &dstLocation,
const QStringList &extraOptions = {}) final;
void commit(const Utils::FilePath &repositoryRoot, const QStringList &files,
const QString &commitMessageFile, const QStringList &extraOptions = {}) final;
void annotate(const Utils::FilePath &workingDir, const QString &file,
int lineNumber = -1, const QString &revision = {},
const QStringList &extraOptions = {}, int firstLine = -1) final;
void log(const Utils::FilePath &workingDir, const QStringList &files = {},
const QStringList &extraOptions = {}, bool enableAnnotationContextMenu = false,
const std::function<void(Utils::CommandLine &)> &addAuthOptions = {}) final;
void logCurrentFile(const Utils::FilePath &workingDir, const QStringList &files = {},
const QStringList &extraOptions = {},
bool enableAnnotationContextMenu = false,
const std::function<void(Utils::CommandLine &)> &addAuthOptions = {});
void revertFile(const Utils::FilePath &workingDir, const QString &file,
const QString &revision = {}, const QStringList &extraOptions = {}) final;
void revertAll(const Utils::FilePath &workingDir, const QString &revision = {},
const QStringList &extraOptions = {}) final;
bool isVcsFileOrDirectory(const Utils::FilePath &filePath) const;
Utils::FilePath findTopLevelForFile(const Utils::FilePath &file) const final;
bool managesFile(const Utils::FilePath &workingDirectory, const QString &fileName) const;
unsigned int binaryVersion() const;
QString binaryVersionString() const;
SupportedFeatures supportedFeatures() const;
void view(const Utils::FilePath &source, const QString &id, const QStringList &extraOptions = {}) final;
private:
static QList<BranchInfo> branchListFromOutput(const QString &output,
const BranchInfo::BranchFlags defaultFlags = {});
static QStringList parseRevisionCommentLine(const QString &commentLine);
QString sanitizeFossilOutput(const QString &output) const;
QString vcsCommandString(VcsCommandTag cmd) const final;
Utils::Id vcsEditorKind(VcsCommandTag cmd) const final;
QStringList revisionSpec(const QString &revision) const final;
StatusItem parseStatusLine(const QString &line) const final;
VcsBase::VcsBaseEditorConfig *createAnnotateEditor(VcsBase::VcsBaseEditorWidget *editor);
VcsBase::VcsBaseEditorConfig *createLogCurrentFileEditor(VcsBase::VcsBaseEditorWidget *editor);
VcsBase::VcsBaseEditorConfig *createLogEditor(VcsBase::VcsBaseEditorWidget *editor);
friend class FossilPluginPrivate;
FossilSettings *m_settings = nullptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(FossilClient::SupportedFeatures)
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Fossil::Internal::FossilCommitPanel</class>
<widget class="QWidget" name="Fossil::Internal::FossilCommitPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>374</width>
<height>270</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="infoGroup">
<property name="title">
<string>Current Information</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="1" column="0">
<widget class="QLabel" name="localRootLabel">
<property name="text">
<string>Local root:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="localRootLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="currentBranchLabel">
<property name="text">
<string>Branch:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="currentBranchLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="currentTagsLabel">
<property name="text">
<string>Tags:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="currentTagsLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="editGroup">
<property name="title">
<string>Commit Information</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="branchLabel">
<property name="text">
<string>New branch:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="branchLineEdit"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="invalidBranchLabel">
<property name="minimumSize">
<size>
<width>50</width>
<height>20</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>:/projectexplorer/images/compile_error.png</pixmap>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QCheckBox" name="isPrivateCheckBox">
<property name="toolTip">
<string>Create a private check-in that is never synced.
Children of private check-ins are automatically private.
Private check-ins are not pushed to the remote repository by default.</string>
</property>
<property name="text">
<string>Private</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="tagsLabel">
<property name="text">
<string>Tags:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="tagsLineEdit">
<property name="toolTip">
<string>Tag names to apply; comma-separated.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="authorLabel">
<property name="text">
<string>Author:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="authorLineEdit"/>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>160</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,163 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "fossilcommitwidget.h"
#include "branchinfo.h"
#include <texteditor/texteditorsettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorconstants.h>
#include <utils/completingtextedit.h>
#include <utils/filepath.h>
#include <utils/qtcassert.h>
#include <QDir>
#include <QRegularExpression>
#include <QSyntaxHighlighter>
namespace Fossil {
namespace Internal {
// Retrieve the comment char format from the text editor.
static QTextCharFormat commentFormat()
{
const TextEditor::FontSettings settings = TextEditor::TextEditorSettings::instance()->fontSettings();
return settings.toTextCharFormat(TextEditor::C_COMMENT);
}
// Highlighter for Fossil submit messages.
// Marks up [ticket-id] fields in the message.
class FossilSubmitHighlighter : QSyntaxHighlighter
{
public:
explicit FossilSubmitHighlighter(Utils::CompletingTextEdit *parent);
void highlightBlock(const QString &text) final;
private:
const QTextCharFormat m_commentFormat;
const QRegularExpression m_keywordPattern;
};
FossilSubmitHighlighter::FossilSubmitHighlighter(Utils::CompletingTextEdit *parent) : QSyntaxHighlighter(parent),
m_commentFormat(commentFormat()),
m_keywordPattern("\\[([0-9a-f]{5,40})\\]")
{
QTC_CHECK(m_keywordPattern.isValid());
}
void FossilSubmitHighlighter::highlightBlock(const QString &text)
{
// Fossil commit message allows listing of [ticket-id],
// where ticket-id is a partial SHA1.
// Match the ticket-ids and highlight them for convenience.
// Format keywords
QRegularExpressionMatchIterator i = m_keywordPattern.globalMatch(text);
while (i.hasNext()) {
const QRegularExpressionMatch keywordMatch = i.next();
QTextCharFormat charFormat = format(0);
charFormat.setFontItalic(true);
setFormat(keywordMatch.capturedStart(0), keywordMatch.capturedLength(0), charFormat);
}
}
FossilCommitWidget::FossilCommitWidget() : m_commitPanel(new QWidget)
{
m_commitPanelUi.setupUi(m_commitPanel);
insertTopWidget(m_commitPanel);
new FossilSubmitHighlighter(descriptionEdit());
m_branchValidator = new QRegularExpressionValidator(QRegularExpression("[^\\n]*"), this);
connect(m_commitPanelUi.branchLineEdit, &QLineEdit::textChanged,
this, &FossilCommitWidget::branchChanged);
}
void FossilCommitWidget::setFields(const Utils::FilePath &repoPath, const BranchInfo &branch,
const QStringList &tags, const QString &userName)
{
m_commitPanelUi.localRootLineEdit->setText(repoPath.toUserOutput());
m_commitPanelUi.currentBranchLineEdit->setText(branch.name);
const QString tagsText = tags.join(", ");
m_commitPanelUi.currentTagsLineEdit->setText(tagsText);
m_commitPanelUi.authorLineEdit->setText(userName);
branchChanged();
}
QString FossilCommitWidget::newBranch() const
{
return m_commitPanelUi.branchLineEdit->text().trimmed();
}
QStringList FossilCommitWidget::tags() const
{
QString tagsText = m_commitPanelUi.tagsLineEdit->text().trimmed();
if (tagsText.isEmpty())
return {};
return tagsText.replace(',', ' ').split(' ', Qt::SkipEmptyParts);
}
QString FossilCommitWidget::committer() const
{
return m_commitPanelUi.authorLineEdit->text();
}
bool FossilCommitWidget::isPrivateOptionEnabled() const
{
return m_commitPanelUi.isPrivateCheckBox->isChecked();
}
bool FossilCommitWidget::canSubmit(QString *whyNot) const
{
QString message = cleanupDescription(descriptionText()).trimmed();
if (m_commitPanelUi.invalidBranchLabel->isVisible() || message.isEmpty()) {
if (whyNot)
*whyNot = tr("Message check failed.");
return false;
}
return VcsBase::SubmitEditorWidget::canSubmit();
}
void FossilCommitWidget::branchChanged()
{
m_commitPanelUi.invalidBranchLabel->setVisible(!isValidBranch());
updateSubmitAction();
}
bool FossilCommitWidget::isValidBranch() const
{
int pos = m_commitPanelUi.branchLineEdit->cursorPosition();
QString text = m_commitPanelUi.branchLineEdit->text();
return m_branchValidator->validate(text, pos) == QValidator::Acceptable;
}
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "ui_fossilcommitpanel.h"
#include <vcsbase/submiteditorwidget.h>
QT_BEGIN_NAMESPACE
class QValidator;
QT_END_NAMESPACE
namespace Utils { class FilePath; }
namespace Fossil {
namespace Internal {
class BranchInfo;
/*submit editor widget based on git SubmitEditor
Some extra fields have been added to the standard SubmitEditorWidget,
to help to conform to the commit style that is used by both git and Fossil*/
class FossilCommitWidget : public VcsBase::SubmitEditorWidget
{
Q_OBJECT
public:
FossilCommitWidget();
void setFields(const Utils::FilePath &repoPath, const BranchInfo &newBranch,
const QStringList &tags, const QString &userName);
QString newBranch() const;
QStringList tags() const;
QString committer() const;
bool isPrivateOptionEnabled() const;
protected:
bool canSubmit(QString *whyNot = nullptr) const;
private slots:
void branchChanged();
private:
bool isValidBranch() const;
QWidget *m_commitPanel;
Ui::FossilCommitPanel m_commitPanelUi;
QValidator *m_branchValidator;
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,123 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "fossileditor.h"
#include "annotationhighlighter.h"
#include "constants.h"
#include "fossilplugin.h"
#include "fossilclient.h"
#include <utils/qtcassert.h>
#include <QRegularExpression>
#include <QTextCursor>
namespace Fossil {
namespace Internal {
class FossilEditorWidgetPrivate
{
public:
FossilEditorWidgetPrivate() :
m_exactChangesetId(Constants::CHANGESET_ID_EXACT)
{
QTC_ASSERT(m_exactChangesetId.isValid(), return);
}
const QRegularExpression m_exactChangesetId;
};
FossilEditorWidget::FossilEditorWidget() :
d(new FossilEditorWidgetPrivate)
{
setAnnotateRevisionTextFormat(tr("&Annotate %1"));
setAnnotatePreviousRevisionTextFormat(tr("Annotate &Parent Revision %1"));
setDiffFilePattern(Constants::DIFFFILE_ID_EXACT);
setLogEntryPattern("^.*\\[([0-9a-f]{5,40})\\]");
setAnnotationEntryPattern(QString("^") + Constants::CHANGESET_ID + " ");
}
FossilEditorWidget::~FossilEditorWidget()
{
delete d;
}
QString FossilEditorWidget::changeUnderCursor(const QTextCursor &cursorIn) const
{
QTextCursor cursor = cursorIn;
cursor.select(QTextCursor::WordUnderCursor);
if (cursor.hasSelection()) {
const QString change = cursor.selectedText();
const QRegularExpressionMatch exactChangesetIdMatch = d->m_exactChangesetId.match(change);
if (exactChangesetIdMatch.hasMatch())
return change;
}
return {};
}
QString FossilEditorWidget::decorateVersion(const QString &revision) const
{
static const int shortChangesetIdSize(10);
static const int maxTextSize(120);
const Utils::FilePath workingDirectory = source().parentDir();
const FossilClient *client = FossilPlugin::client();
const RevisionInfo revisionInfo = client->synchronousRevisionQuery(workingDirectory, revision,
true);
// format: 'revision (committer "comment...")'
QString output = revision.left(shortChangesetIdSize)
+ " (" + revisionInfo.committer
+ " \"" + revisionInfo.commentMsg.left(maxTextSize);
if (output.size() > maxTextSize) {
output.truncate(maxTextSize - 3);
output.append("...");
}
output.append("\")");
return output;
}
QStringList FossilEditorWidget::annotationPreviousVersions(const QString &revision) const
{
const Utils::FilePath workingDirectory = source().parentDir();
const FossilClient *client = FossilPlugin::client();
const RevisionInfo revisionInfo = client->synchronousRevisionQuery(workingDirectory, revision);
if (revisionInfo.parentId.isEmpty())
return {};
QStringList revisions{revisionInfo.parentId};
revisions.append(revisionInfo.mergeParentIds);
return revisions;
}
VcsBase::BaseAnnotationHighlighter *FossilEditorWidget::createAnnotationHighlighter(
const QSet<QString> &changes) const
{
return new FossilAnnotationHighlighter(changes);
}
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,54 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <vcsbase/vcsbaseeditor.h>
namespace Fossil {
namespace Internal {
class FossilEditorWidgetPrivate;
class FossilEditorWidget final : public VcsBase::VcsBaseEditorWidget
{
Q_OBJECT
public:
FossilEditorWidget();
~FossilEditorWidget() final;
private:
QString changeUnderCursor(const QTextCursor &cursor) const final;
QString decorateVersion(const QString &revision) const final;
QStringList annotationPreviousVersions(const QString &revision) const final;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(
const QSet<QString> &changes) const final;
FossilEditorWidgetPrivate *d;
};
} // namespace Internal
} // namespace Fossil

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "fossilsettings.h"
#include <vcsbase/vcsbaseclient.h>
#include <vcsbase/vcsbaseplugin.h>
#include <coreplugin/icontext.h>
namespace Fossil {
namespace Internal {
class FossilClient;
class FossilPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Fossil.json")
~FossilPlugin() final;
bool initialize(const QStringList &arguments, QString *errorMessage) final;
void extensionsInitialized() final;
public:
static const FossilSettings &settings();
static FossilClient *client();
#ifdef WITH_TESTS
private slots:
void testDiffFileResolving_data();
void testDiffFileResolving();
void testLogResolving();
#endif
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,197 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "fossilsettings.h"
#include "constants.h"
#include <coreplugin/icore.h>
#include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
#include <vcsbase/vcsbaseconstants.h>
using namespace Utils;
namespace Fossil {
namespace Internal {
FossilSettings::FossilSettings()
{
setSettingsGroup(Constants::FOSSIL);
setAutoApply(false);
registerAspect(&binaryPath);
binaryPath.setDisplayStyle(StringAspect::PathChooserDisplay);
binaryPath.setExpectedKind(PathChooser::ExistingCommand);
binaryPath.setDefaultValue(Constants::FOSSILDEFAULT);
binaryPath.setDisplayName(tr("Fossil Command"));
binaryPath.setHistoryCompleter("Fossil.Command.History");
binaryPath.setLabelText(tr("Command:"));
registerAspect(&defaultRepoPath);
defaultRepoPath.setSettingsKey("defaultRepoPath");
defaultRepoPath.setDisplayStyle(StringAspect::PathChooserDisplay);
defaultRepoPath.setExpectedKind(PathChooser::Directory);
defaultRepoPath.setDisplayName(tr("Fossil Repositories"));
defaultRepoPath.setLabelText(tr("Default path:"));
defaultRepoPath.setToolTip(tr("Directory to store local repositories by default."));
registerAspect(&userName);
userName.setDisplayStyle(StringAspect::LineEditDisplay);
userName.setLabelText(tr("Default user:"));
userName.setToolTip(tr("Existing user to become an author of changes made to the repository."));
registerAspect(&sslIdentityFile);
sslIdentityFile.setSettingsKey("sslIdentityFile");
sslIdentityFile.setDisplayStyle(StringAspect::PathChooserDisplay);
sslIdentityFile.setExpectedKind(PathChooser::File);
sslIdentityFile.setDisplayName(tr("SSL/TLS Identity Key"));
sslIdentityFile.setLabelText(tr("SSL/TLS identity:"));
sslIdentityFile.setToolTip(tr("SSL/TLS client identity key to use if requested by the server."));
registerAspect(&diffIgnoreAllWhiteSpace);
diffIgnoreAllWhiteSpace.setSettingsKey("diffIgnoreAllWhiteSpace");
registerAspect(&diffStripTrailingCR);
diffStripTrailingCR.setSettingsKey("diffStripTrailingCR");
registerAspect(&annotateShowCommitters);
annotateShowCommitters.setSettingsKey("annotateShowCommitters");
registerAspect(&annotateListVersions);
annotateListVersions.setSettingsKey("annotateListVersions");
registerAspect(&timelineWidth);
timelineWidth.setSettingsKey("timelineWidth");
timelineWidth.setLabelText(tr("Log width:"));
timelineWidth.setToolTip(tr("The width of log entry line (>20). "
"Choose 0 to see a single line per entry."));
registerAspect(&timelineLineageFilter);
timelineLineageFilter.setSettingsKey("timelineLineageFilter");
registerAspect(&timelineVerbose);
timelineVerbose.setSettingsKey("timelineVerbose");
registerAspect(&timelineItemType);
timelineItemType.setDefaultValue("all");
timelineItemType.setSettingsKey("timelineItemType");
registerAspect(&disableAutosync);
disableAutosync.setSettingsKey("disableAutosync");
disableAutosync.setDefaultValue(true);
disableAutosync.setLabelText(tr("Disable auto-sync"));
disableAutosync.setToolTip(tr("Disable automatic pull prior to commit or update and "
"automatic push after commit or tag or branch creation."));
registerAspect(&timeout);
timeout.setLabelText(tr("Timeout:"));
timeout.setSuffix(tr("s"));
registerAspect(&logCount);
logCount.setLabelText(tr("Log count:"));
logCount.setToolTip(tr("The number of recent commit log entries to show. "
"Choose 0 to see all entries."));
};
// OptionsPage
class OptionsPageWidget final : public Core::IOptionsPageWidget
{
Q_DECLARE_TR_FUNCTIONS(Fossil::Internal::OptionsPageWidget)
public:
OptionsPageWidget(const std::function<void()> &onApply, FossilSettings *settings);
void apply() final;
private:
const std::function<void()> m_onApply;
FossilSettings *m_settings;
};
void OptionsPageWidget::apply()
{
if (!m_settings->isDirty())
return;
m_settings->apply();
m_onApply();
}
OptionsPageWidget::OptionsPageWidget(const std::function<void()> &onApply, FossilSettings *settings) :
m_onApply(onApply),
m_settings(settings)
{
FossilSettings &s = *m_settings;
using namespace Layouting;
Column {
Group {
title(tr("Configuration")),
Row { s.binaryPath }
},
Group {
title(tr("Local Repositories")),
Row { s.defaultRepoPath }
},
Group {
title(tr("User")),
Form {
s.userName, br,
s.sslIdentityFile
}
},
Group {
title(tr("Miscellaneous")),
Column {
Row {
s.logCount,
s.timelineWidth,
s.timeout,
st
},
s.disableAutosync
},
},
st
}.attachTo(this);
}
OptionsPage::OptionsPage(const std::function<void()> &onApply, FossilSettings *settings)
{
setId(Constants::VCS_ID_FOSSIL);
setDisplayName(OptionsPageWidget::tr("Fossil"));
setWidgetCreator([onApply, settings]() { return new OptionsPageWidget(onApply, settings); });
setCategory(VcsBase::Constants::VCS_SETTINGS_CATEGORY);
}
} // Internal
} // Fossil

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <coreplugin/dialogs/ioptionspage.h>
#include <vcsbase/vcsbaseclientsettings.h>
namespace Fossil {
namespace Internal {
class FossilSettings : public VcsBase::VcsBaseSettings
{
public:
Utils::StringAspect defaultRepoPath;
Utils::StringAspect sslIdentityFile;
Utils::BoolAspect diffIgnoreAllWhiteSpace;
Utils::BoolAspect diffStripTrailingCR;
Utils::BoolAspect annotateShowCommitters;
Utils::BoolAspect annotateListVersions;
Utils::IntegerAspect timelineWidth;
Utils::StringAspect timelineLineageFilter;
Utils::BoolAspect timelineVerbose;
Utils::StringAspect timelineItemType;
Utils::BoolAspect disableAutosync;
FossilSettings();
};
struct RepositorySettings
{
enum AutosyncMode {AutosyncOff, AutosyncOn, AutosyncPullOnly};
QString user;
QString sslIdentityFile;
AutosyncMode autosync = AutosyncOn;
};
inline bool operator==(const RepositorySettings &lh, const RepositorySettings &rh)
{
return (lh.user == rh.user &&
lh.sslIdentityFile == rh.sslIdentityFile &&
lh.autosync == rh.autosync);
}
class OptionsPage : public Core::IOptionsPage
{
public:
OptionsPage(const std::function<void()> &onApply, FossilSettings *settings);
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,110 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "pullorpushdialog.h"
#include "ui_pullorpushdialog.h"
#include "constants.h"
#include <utils/qtcassert.h>
namespace Fossil {
namespace Internal {
PullOrPushDialog::PullOrPushDialog(Mode mode, QWidget *parent) : QDialog(parent),
m_mode(mode),
m_ui(new Ui::PullOrPushDialog)
{
m_ui->setupUi(this);
m_ui->localPathChooser->setExpectedKind(Utils::PathChooser::File);
m_ui->localPathChooser->setPromptDialogFilter(tr(Constants::FOSSIL_FILE_FILTER));
switch (m_mode) {
case PullMode:
this->setWindowTitle(tr("Pull Source"));
break;
case PushMode:
this->setWindowTitle(tr("Push Destination"));
break;
}
// select URL text in line edit when clicking the radio button
m_ui->localButton->setFocusProxy(m_ui->localPathChooser);
m_ui->urlButton->setFocusProxy(m_ui->urlLineEdit);
connect(m_ui->urlButton, &QRadioButton::clicked, m_ui->urlLineEdit, &QLineEdit::selectAll);
this->adjustSize();
}
PullOrPushDialog::~PullOrPushDialog()
{
delete m_ui;
}
QString PullOrPushDialog::remoteLocation() const
{
if (m_ui->defaultButton->isChecked())
return QString();
if (m_ui->localButton->isChecked())
return m_ui->localPathChooser->filePath().toString();
return m_ui->urlLineEdit->text();
}
bool PullOrPushDialog::isRememberOptionEnabled() const
{
if (m_ui->defaultButton->isChecked())
return false;
return m_ui->rememberCheckBox->isChecked();
}
bool PullOrPushDialog::isPrivateOptionEnabled() const
{
return m_ui->privateCheckBox->isChecked();
}
void PullOrPushDialog::setDefaultRemoteLocation(const QString &url)
{
m_ui->urlLineEdit->setText(url);
}
void PullOrPushDialog::setLocalBaseDirectory(const QString &dir)
{
m_ui->localPathChooser->setBaseDirectory(Utils::FilePath::fromString(dir));
}
void PullOrPushDialog::changeEvent(QEvent *e)
{
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
}
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QDialog>
namespace Fossil {
namespace Internal {
namespace Ui { class PullOrPushDialog; }
class PullOrPushDialog : public QDialog
{
Q_OBJECT
public:
enum Mode {
PullMode,
PushMode
};
explicit PullOrPushDialog(Mode mode, QWidget *parent = nullptr);
~PullOrPushDialog() final;
// Common parameters and options
QString remoteLocation() const;
bool isRememberOptionEnabled() const;
bool isPrivateOptionEnabled() const;
void setDefaultRemoteLocation(const QString &url);
void setLocalBaseDirectory(const QString &dir);
// Pull-specific options
// Push-specific options
protected:
void changeEvent(QEvent *e) final;
private:
Mode m_mode;
Ui::PullOrPushDialog *m_ui;
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Fossil::Internal::PullOrPushDialog</class>
<widget class="QDialog" name="Fossil::Internal::PullOrPushDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>477</width>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Remote Location</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="defaultButton">
<property name="text">
<string>Default location</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="localButton">
<property name="text">
<string>Local filesystem:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Utils::PathChooser" name="localPathChooser" native="true">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="urlButton">
<property name="toolTip">
<string>For example: https://[user[:pass]@]host[:port]/[path]</string>
</property>
<property name="text">
<string>Specify URL:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="urlLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>For example: https://[user[:pass]@]host[:port]/[path]</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Options</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="rememberCheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remember specified location as default</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="privateCheckBox">
<property name="toolTip">
<string>Allow transfer of private branches.</string>
</property>
<property name="text">
<string>Include private branches</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>4</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::PathChooser</class>
<extends>QWidget</extends>
<header location="global">utils/pathchooser.h</header>
<container>1</container>
<slots>
<signal>editingFinished()</signal>
<signal>browsingFinished()</signal>
</slots>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Fossil::Internal::PullOrPushDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>177</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Fossil::Internal::PullOrPushDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>325</x>
<y>177</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>urlButton</sender>
<signal>toggled(bool)</signal>
<receiver>urlLineEdit</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>80</x>
<y>121</y>
</hint>
<hint type="destinationlabel">
<x>332</x>
<y>123</y>
</hint>
</hints>
</connection>
<connection>
<sender>localButton</sender>
<signal>toggled(bool)</signal>
<receiver>localPathChooser</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>112</x>
<y>81</y>
</hint>
<hint type="destinationlabel">
<x>346</x>
<y>81</y>
</hint>
</hints>
</connection>
<connection>
<sender>urlButton</sender>
<signal>toggled(bool)</signal>
<receiver>rememberCheckBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>71</x>
<y>92</y>
</hint>
<hint type="destinationlabel">
<x>163</x>
<y>153</y>
</hint>
</hints>
</connection>
<connection>
<sender>localButton</sender>
<signal>toggled(bool)</signal>
<receiver>rememberCheckBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>71</x>
<y>67</y>
</hint>
<hint type="destinationlabel">
<x>163</x>
<y>153</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Fossil::Internal::RevertDialog</class>
<widget class="QDialog" name="Fossil::Internal::RevertDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>120</height>
</rect>
</property>
<property name="windowTitle">
<string>Revert</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Specify a revision other than the default?</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>361</width>
<height>31</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="revisionLabel">
<property name="toolTip">
<string>Checkout revision, can also be a branch or a tag name.</string>
</property>
<property name="text">
<string>Revision:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="revisionLineEdit">
<property name="toolTip">
<string>Checkout revision, can also be a branch or a tag name.</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Fossil::Internal::RevertDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Fossil::Internal::RevertDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QString>
#include <QStringList>
namespace Fossil {
namespace Internal {
class RevisionInfo
{
public:
const QString id;
const QString parentId;
const QStringList mergeParentIds;
const QString commentMsg;
const QString committer;
};
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "fossiljsextension.h"
#include "../constants.h"
#include "../fossilclient.h"
#include "../fossilplugin.h"
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <vcsbase/vcsbaseclientsettings.h>
#include <vcsbase/vcsbaseconstants.h>
using namespace Core;
namespace Fossil {
namespace Internal {
class FossilJsExtensionPrivate {
public:
FossilJsExtensionPrivate(FossilSettings *settings) :
m_vscId(Constants::VCS_ID_FOSSIL),
m_settings(settings)
{
}
Utils::Id m_vscId;
FossilSettings *m_settings;
};
QMap<QString, QString> FossilJsExtension::parseArgOptions(const QStringList &args)
{
QMap<QString, QString> options;
for (const QString &arg : args) {
if (arg.isEmpty())
continue;
const QStringList opt = arg.split('|', Qt::KeepEmptyParts);
options.insert(opt[0], opt.size() > 1 ? opt[1] : QString());
}
return options;
}
FossilJsExtension::FossilJsExtension(FossilSettings *settings) :
d(new FossilJsExtensionPrivate(settings))
{ }
FossilJsExtension::~FossilJsExtension()
{
delete d;
}
bool FossilJsExtension::isConfigured() const
{
IVersionControl *vc = VcsManager::versionControl(d->m_vscId);
return vc && vc->isConfigured();
}
QString FossilJsExtension::displayName() const
{
IVersionControl *vc = VcsManager::versionControl(d->m_vscId);
return vc ? vc->displayName() : QString();
}
QString FossilJsExtension::defaultAdminUser() const
{
if (!isConfigured())
return QString();
return d->m_settings->userName.value();
}
QString FossilJsExtension::defaultSslIdentityFile() const
{
if (!isConfigured())
return QString();
return d->m_settings->sslIdentityFile.value();
}
QString FossilJsExtension::defaultLocalRepoPath() const
{
if (!isConfigured())
return QString();
return d->m_settings->defaultRepoPath.value();
}
bool FossilJsExtension::defaultDisableAutosync() const
{
if (!isConfigured())
return false;
return d->m_settings->disableAutosync.value();
}
} // namespace Internal
} // namespace Fossil

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (c) 2018 Artur Shepilko
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <vcsbase/wizard/vcsjsextension.h>
#include <QStringList>
#include <QMap>
#include <QObject>
namespace Fossil {
namespace Internal {
class FossilJsExtensionPrivate;
class FossilSettings;
class FossilJsExtension : public QObject
{
Q_OBJECT
public:
static QMap<QString, QString> parseArgOptions(const QStringList &args);
FossilJsExtension(FossilSettings *settings);
~FossilJsExtension();
Q_INVOKABLE bool isConfigured() const;
Q_INVOKABLE QString displayName() const;
Q_INVOKABLE QString defaultAdminUser() const;
Q_INVOKABLE QString defaultSslIdentityFile() const;
Q_INVOKABLE QString defaultLocalRepoPath() const;
Q_INVOKABLE bool defaultDisableAutosync() const;
private:
FossilJsExtensionPrivate *d = nullptr;
};
} // namespace Internal
} // namespace Fossil

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,255 @@
{
"version": 1,
"supportedProjectTypes": [ "UNKNOWN_PROJECT" ],
"id": "I.Fossil",
"category": "T.Import",
"trDescription": "Clones a Fossil repository and tries to load the contained project.",
"trDisplayName": "Fossil Clone",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('Fossil') >= 0}",
"options":
[
{ "key": "vcsId", "value": "I.Fossil" },
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
{ "key": "isCloneRepo", "value": "%{JS: '%{RepoType}' === 'cloneRepo' }" },
{ "key": "isLocalRepo", "value": "%{JS: '%{RepoType}' === 'localRepo' }" },
{ "key": "SR", "value": "%{JS: '%{Repo}'.substr('%{Repo}'.indexOf(':') + 1).replace(/[^/@]+@/,'').replace(/:[0-9]+$/,'').replace(/[.](fossil|fsl)$/, '') }"},
{ "key": "defaultDir", "value": "%{JS: %{isCloneRepo} ? '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/[.:\"]+/g, '-') : %{isLocalRepo} ? Util.baseName('%{LocalRepo}') : '' }"},
{ "key": "defaultFossilName", "value": "%{JS: %{isCloneRepo} ? '%{defaultDir}' : %{isLocalRepo} ? Util.completeBaseName('%{LocalRepo}') : '' }" },
{ "key": "defaultLocalRepoPath", "value": "%{JS: Fossil.defaultLocalRepoPath() }" },
{ "key": "defaultSslIdentityFile", "value": "%{JS: Fossil.defaultSslIdentityFile() }" },
{ "key": "defaultDisableAutosync", "value": "%{JS: Fossil.defaultDisableAutosync() }" },
{ "key": "SourceRepo", "value": "%{JS: %{isCloneRepo} ? '%{Repo}' : %{isLocalRepo} ? '%{LocalRepo}' : '' }" },
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" },
{ "key": "FossilFile", "value": "%{defaultLocalRepoPath}/%{FossilName}.fossil" },
{ "key": "argRepoType", "value": "repository-type|%{RepoType}" },
{ "key": "argBranchTag", "value": "%{JS: '%{Branch}' ? 'branch-tag|%{Branch}' : '' }" },
{ "key": "argAdminUser", "value": "%{JS: '%{AdminUser}' ? 'admin-user|%{AdminUser}' : '' }" },
{ "key": "argSslIdentity", "value": "%{JS: '%{SslIdentity}' ? 'ssl-identity|%{SslIdentity}' : '' }" },
{ "key": "argIncludePrivate", "value": "%{JS: '%{IncludePrivate}' ? 'include-private|%{IncludePrivate}' : '' }" },
{ "key": "argDisableAutosync", "value": "%{JS: '%{DisableAutosync}' ? 'settings-autosync|%{DisableAutosync}' : '' }" },
{ "key": "argFossilFile", "value": "fossil-file|%{FossilFile}" }
],
"pages":
[
{
"trDisplayName": "Configuration",
"trShortTitle": "Configuration",
"trSubTitle": "Please configure <b>%{vcsName}</b> now.",
"typeId": "VcsConfiguration",
"enabled": "%{JS: !Vcs.isConfigured('%{vcsId}')}",
"data": { "vcsId": "%{vcsId}" }
},
{
"trDisplayName": "Select repository location type",
"trShortTitle": "Repository",
"typeId": "Fields",
"data":
[
{
"name": "RepoType",
"type": "ComboBox",
"data":
{
"index": 0,
"items":
[
{ "trKey": "Remote repository clone", "value": "cloneRepo" },
{ "trKey": "Local repository checkout", "value": "localRepo" }
]
}
}
]
},
{
"trDisplayName": "Location",
"trShortTitle": "Location",
"trSubTitle": "Specify repository location, branch, checkout destination, and options.",
"typeId": "Fields",
"data" :
[
{
"name": "GotSource",
"type": "LineEdit",
"visible": false,
"mandatory": true,
"isComplete": "%{JS: '%{FossilName}' === '' || (%{isCloneRepo} && !Util.exists('%{FossilFile}')) }",
"trIncompleteMessage": "The clone fossil already exists in local repositories path.",
"data":
{
"trText": "%{JS: (%{isCloneRepo} && '%{Repo}' !== '' && '%{FossilName}' !== '') || (%{isLocalRepo} && '%{LocalRepo}' !== '') ? 'true' : '' }"
}
},
{
"name": "Repo",
"trDisplayName": "Remote repository:",
"trToolTip": "For example: https://[user[:pass]@]host[:port]/[path]",
"type": "LineEdit",
"enabled": "%{isCloneRepo}",
"mandatory": false
},
{
"name": "FossilName",
"trDisplayName": "Local clone:",
"trToolTip": "Base name of a new local fossil file to clone into.",
"type": "LineEdit",
"enabled": "%{isCloneRepo}",
"mandatory": false,
"data":
{
"trText": "%{defaultFossilName}"
}
},
{
"name": "LocalRepo",
"trDisplayName": "Local repository:",
"trToolTip": "Path of an existing local fossil file to check out from.",
"type": "PathChooser",
"enabled": "%{isLocalRepo}",
"mandatory": false,
"data":
{
"kind": "file",
"basePath": "%{defaultLocalRepoPath}"
}
},
{
"name": "Branch",
"trDisplayName": "Branch:",
"type": "LineEdit",
"mandatory": false,
"data":
{
"trPlaceholder": "<default branch>"
}
},
{
"name": "Sp1",
"type": "Spacer",
"data": { "factor": 2 }
},
{
"name": "Dir",
"trDisplayName": "Checkout directory:",
"type": "LineEdit",
"isComplete": "%{JS: '%{Dir}' === '' || !Util.exists('%{TargetPath}')}",
"trIncompleteMessage": "The checkout directory already exists in the filesystem.",
"data":
{
"trText": "%{defaultDir}"
}
},
{
"name": "Path",
"trDisplayName": "Create in:",
"type": "PathChooser",
"data":
{
"kind": "existingDirectory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
},
{
"name": "Sp2",
"type": "Spacer",
"data": { "factor": 2 }
},
{
"name": "AdminUser",
"trDisplayName": "Admin user:",
"trToolTip": "Privileged user added automatically to the created local repository.",
"type": "LineEdit",
"mandatory": false,
"enabled": "%{isCloneRepo}",
"data":
{
"trText": "%{JS: Fossil.defaultAdminUser()}"
}
},
{
"name": "SslIdentity",
"trDisplayName": "SSL/TLS identity:",
"trToolTip": "SSL/TLS client identity key to use if requested by the server.",
"type": "PathChooser",
"mandatory": false,
"enabled": "%{isCloneRepo}",
"data":
{
"kind": "file",
"path": "%{defaultSslIdentityFile}"
}
},
{
"name": "IncludePrivate",
"trDisplayName": "Include private branches",
"trToolTip": "Allow transfer of private branches.",
"type": "CheckBox",
"enabled": "%{isCloneRepo}",
"data":
{
"checkedValue": "true",
"uncheckedValue": ""
}
},
{
"name": "DisableAutosync",
"trDisplayName": "Disable auto-sync",
"trToolTip": "Disable automatic pull prior to commit or update and automatic push after commit or tag or branch creation.",
"type": "CheckBox",
"enabled": "%{isCloneRepo}",
"data":
{
"checkedValue": "off",
"uncheckedValue": "",
"checked": "%{defaultDisableAutosync}"
}
}
]
},
{
"trDisplayName": "Checkout",
"trShortTitle": "Checkout",
"typeId": "VcsCommand",
"data" :
{
"vcsId": "%{vcsId}",
"trRunMessage": "Running Fossil clone...",
"repository": "%{SourceRepo}",
"baseDirectory": "%{Path}",
"checkoutName": "%{Dir}",
"extraArguments":
[
"%{argRepoType}",
"%{argBranchTag}",
"%{argAdminUser}",
"%{argSslIdentity}",
"%{argIncludePrivate}",
"%{argDisableAutosync}",
"%{argFossilFile}"
],
"extraJobs" :
[
{
"command": "fossil",
"arguments": [ "version" ]
}
]
}
}
],
"generators":
[
{
"typeId": "Scanner",
"data": {
"subdirectoryPatterns": [ "^src$" ]
}
}
]
}

View File

@@ -322,7 +322,7 @@ ShowController::ShowController(IDocument *document, const QString &id)
}; };
const auto setupDescription = [this, id](QtcProcess &process) { const auto setupDescription = [this, id](QtcProcess &process) {
process.setCodec(m_instance->encoding(workingDirectory(), "i18n.commitEncoding")); process.setCodec(m_instance->encoding(GitClient::EncodingCommit, workingDirectory()));
setupCommand(process, {"show", "-s", noColorOption, showFormatC, id}); setupCommand(process, {"show", "-s", noColorOption, showFormatC, id});
VcsOutputWindow::appendCommand(process.workingDirectory(), process.commandLine()); VcsOutputWindow::appendCommand(process.workingDirectory(), process.commandLine());
setDescription(Tr::tr("Waiting for data...")); setDescription(Tr::tr("Waiting for data..."));
@@ -821,13 +821,27 @@ FilePaths GitClient::unmanagedFiles(const FilePaths &filePaths) const
return res; return res;
} }
QTextCodec *GitClient::codecFor(GitClient::CodecType codecType, const FilePath &source) const QTextCodec *GitClient::encoding(GitClient::EncodingType encodingType, const FilePath &source) const
{ {
if (codecType == CodecSource) auto codec = [this](const FilePath &workingDirectory, const QString &configVar) {
return source.isFile() ? VcsBaseEditor::getCodec(source) : encoding(source, "gui.encoding"); const QString codecName = readConfigValue(workingDirectory, configVar).trimmed();
if (codecType == CodecLogOutput) // Set default commit encoding to 'UTF-8', when it's not set,
return encoding(source, "i18n.logOutputEncoding"); // to solve displaying error of commit log with non-latin characters.
return nullptr; if (codecName.isEmpty())
return QTextCodec::codecForName("UTF-8");
return QTextCodec::codecForName(codecName.toUtf8());
};
switch (encodingType) {
case EncodingSource:
return source.isFile() ? VcsBaseEditor::getCodec(source) : codec(source, "gui.encoding");
case EncodingLogOutput:
return codec(source, "i18n.logOutputEncoding");
case EncodingCommit:
return codec(source, "i18n.commitEncoding");
default:
return nullptr;
}
} }
void GitClient::chunkActionsRequested(DiffEditor::DiffEditorController *controller, void GitClient::chunkActionsRequested(DiffEditor::DiffEditorController *controller,
@@ -1057,7 +1071,7 @@ void GitClient::log(const FilePath &workingDirectory, const QString &fileName,
const FilePath sourceFile = VcsBaseEditor::getSource(workingDir, fileName); const FilePath sourceFile = VcsBaseEditor::getSource(workingDir, fileName);
GitEditorWidget *editor = static_cast<GitEditorWidget *>( GitEditorWidget *editor = static_cast<GitEditorWidget *>(
createVcsEditor(editorId, title, sourceFile, createVcsEditor(editorId, title, sourceFile,
codecFor(CodecLogOutput), "logTitle", msgArg)); encoding(EncodingLogOutput), "logTitle", msgArg));
VcsBaseEditorConfig *argWidget = editor->editorConfig(); VcsBaseEditorConfig *argWidget = editor->editorConfig();
if (!argWidget) { if (!argWidget) {
argWidget = new GitLogArgumentsWidget(settings(), !fileName.isEmpty(), editor); argWidget = new GitLogArgumentsWidget(settings(), !fileName.isEmpty(), editor);
@@ -1112,7 +1126,7 @@ void GitClient::reflog(const FilePath &workingDirectory, const QString &ref)
// Creating document might change the referenced workingDirectory. Store a copy and use it. // Creating document might change the referenced workingDirectory. Store a copy and use it.
const FilePath workingDir = workingDirectory; const FilePath workingDir = workingDirectory;
GitEditorWidget *editor = static_cast<GitEditorWidget *>( GitEditorWidget *editor = static_cast<GitEditorWidget *>(
createVcsEditor(editorId, title, workingDir, codecFor(CodecLogOutput), createVcsEditor(editorId, title, workingDir, encoding(EncodingLogOutput),
"reflogRepository", workingDir.toString())); "reflogRepository", workingDir.toString()));
VcsBaseEditorConfig *argWidget = editor->editorConfig(); VcsBaseEditorConfig *argWidget = editor->editorConfig();
if (!argWidget) { if (!argWidget) {
@@ -1225,7 +1239,7 @@ void GitClient::annotate(const Utils::FilePath &workingDir, const QString &file,
const FilePath sourceFile = VcsBaseEditor::getSource(workingDir, file); const FilePath sourceFile = VcsBaseEditor::getSource(workingDir, file);
VcsBaseEditorWidget *editor = createVcsEditor(editorId, title, sourceFile, VcsBaseEditorWidget *editor = createVcsEditor(editorId, title, sourceFile,
codecFor(CodecSource, sourceFile), "blameFileName", id); encoding(EncodingSource, sourceFile), "blameFileName", id);
VcsBaseEditorConfig *argWidget = editor->editorConfig(); VcsBaseEditorConfig *argWidget = editor->editorConfig();
if (!argWidget) { if (!argWidget) {
argWidget = new GitBlameArgumentsWidget(settings(), editor->toolBar()); argWidget = new GitBlameArgumentsWidget(settings(), editor->toolBar());
@@ -1403,7 +1417,7 @@ bool GitClient::synchronousLog(const FilePath &workingDirectory, const QStringLi
allArguments.append(arguments); allArguments.append(arguments);
const CommandResult result = vcsSynchronousExec(workingDirectory, allArguments, flags, const CommandResult result = vcsSynchronousExec(workingDirectory, allArguments, flags,
vcsTimeoutS(), encoding(workingDirectory, "i18n.logOutputEncoding")); vcsTimeoutS(), encoding(EncodingLogOutput, workingDirectory));
if (result.result() == ProcessResult::FinishedWithSuccess) { if (result.result() == ProcessResult::FinishedWithSuccess) {
*output = result.cleanedStdOut(); *output = result.cleanedStdOut();
return true; return true;
@@ -2566,16 +2580,6 @@ FilePath GitClient::vcsBinary() const
return binary; return binary;
} }
QTextCodec *GitClient::encoding(const FilePath &workingDirectory, const QString &configVar) const
{
const QString codecName = readConfigValue(workingDirectory, configVar).trimmed();
// Set default commit encoding to 'UTF-8', when it's not set,
// to solve displaying error of commit log with non-latin characters.
if (codecName.isEmpty())
return QTextCodec::codecForName("UTF-8");
return QTextCodec::codecForName(codecName.toUtf8());
}
// returns first line from log and removes it // returns first line from log and removes it
static QByteArray shiftLogLine(QByteArray &logText) static QByteArray shiftLogLine(QByteArray &logText)
{ {
@@ -2709,7 +2713,7 @@ bool GitClient::getCommitData(const FilePath &workingDirectory,
} }
} }
commitData.commitEncoding = encoding(workingDirectory, "i18n.commitEncoding"); commitData.commitEncoding = encoding(EncodingCommit, workingDirectory);
// Get the commit template or the last commit message // Get the commit template or the last commit message
switch (commitData.commitType) { switch (commitData.commitType) {
@@ -3124,7 +3128,7 @@ void GitClient::subversionLog(const FilePath &workingDirectory) const
const QString title = Tr::tr("Git SVN Log"); const QString title = Tr::tr("Git SVN Log");
const Id editorId = Git::Constants::GIT_SVN_LOG_EDITOR_ID; const Id editorId = Git::Constants::GIT_SVN_LOG_EDITOR_ID;
const FilePath sourceFile = VcsBaseEditor::getSource(workingDirectory, QStringList()); const FilePath sourceFile = VcsBaseEditor::getSource(workingDirectory, QStringList());
VcsBaseEditorWidget *editor = createVcsEditor(editorId, title, sourceFile, codecFor(CodecNone), VcsBaseEditorWidget *editor = createVcsEditor(editorId, title, sourceFile, encoding(EncodingDefault),
"svnLog", sourceFile.toString()); "svnLog", sourceFile.toString());
editor->setWorkingDirectory(workingDirectory); editor->setWorkingDirectory(workingDirectory);
vcsExecWithEditor(workingDirectory, arguments, editor); vcsExecWithEditor(workingDirectory, arguments, editor);

View File

@@ -284,7 +284,6 @@ public:
void setConfigValue(const Utils::FilePath &workingDirectory, const QString &configVar, void setConfigValue(const Utils::FilePath &workingDirectory, const QString &configVar,
const QString &value) const; const QString &value) const;
QTextCodec *encoding(const Utils::FilePath &workingDirectory, const QString &configVar) const;
bool readDataFromCommit(const Utils::FilePath &repoDirectory, const QString &commit, bool readDataFromCommit(const Utils::FilePath &repoDirectory, const QString &commit,
CommitData &commitData, QString *errorMessage = nullptr, CommitData &commitData, QString *errorMessage = nullptr,
QString *commitTemplate = nullptr); QString *commitTemplate = nullptr);
@@ -345,6 +344,10 @@ public:
const Utils::FilePath &path, ShowEditor showSetting = ShowEditor::Always); const Utils::FilePath &path, ShowEditor showSetting = ShowEditor::Always);
Author getAuthor(const Utils::FilePath &workingDirectory); Author getAuthor(const Utils::FilePath &workingDirectory);
enum EncodingType { EncodingSource, EncodingLogOutput, EncodingCommit, EncodingDefault };
QTextCodec *encoding(EncodingType encodingType, const Utils::FilePath &source = {}) const;
private: private:
void finishSubmoduleUpdate(); void finishSubmoduleUpdate();
void chunkActionsRequested(DiffEditor::DiffEditorController *controller, void chunkActionsRequested(DiffEditor::DiffEditorController *controller,
@@ -354,9 +357,6 @@ private:
void stage(DiffEditor::DiffEditorController *diffController, void stage(DiffEditor::DiffEditorController *diffController,
const QString &patch, bool revert) const; const QString &patch, bool revert) const;
enum CodecType { CodecSource, CodecLogOutput, CodecNone };
QTextCodec *codecFor(CodecType codecType, const Utils::FilePath &source = {}) const;
void requestReload(const QString &documentId, const Utils::FilePath &source, void requestReload(const QString &documentId, const Utils::FilePath &source,
const QString &title, const Utils::FilePath &workingDirectory, const QString &title, const Utils::FilePath &workingDirectory,
std::function<GitBaseDiffEditorController *(Core::IDocument *)> factory) const; std::function<GitBaseDiffEditorController *(Core::IDocument *)> factory) const;

View File

@@ -274,8 +274,7 @@ void GitEditorWidget::aboutToOpen(const FilePath &filePath, const FilePath &real
|| editorId == Git::Constants::GIT_REBASE_EDITOR_ID) { || editorId == Git::Constants::GIT_REBASE_EDITOR_ID) {
const FilePath gitPath = filePath.absolutePath(); const FilePath gitPath = filePath.absolutePath();
setSource(gitPath); setSource(gitPath);
textDocument()->setCodec( textDocument()->setCodec(GitClient::instance()->encoding(GitClient::EncodingCommit, gitPath));
GitClient::instance()->encoding(gitPath, "i18n.commitEncoding"));
} }
} }

View File

@@ -1581,9 +1581,10 @@ void GitPluginPrivate::instantBlame()
const CommitInfo info = parseBlameOutput(output.split('\n'), filePath, m_author); const CommitInfo info = parseBlameOutput(output.split('\n'), filePath, m_author);
m_blameMark.reset(new BlameMark(filePath, line, info)); m_blameMark.reset(new BlameMark(filePath, line, info));
}; };
QTextCodec *codec = GitClient::instance()->encoding(GitClient::EncodingCommit, workingDirectory);
GitClient::instance()->vcsExecWithHandler(workingDirectory, GitClient::instance()->vcsExecWithHandler(workingDirectory,
{"blame", "-p", "-L", lineString, "--", filePath.toString()}, {"blame", "-p", "-L", lineString, "--", filePath.toString()},
this, commandHandler, RunFlags::NoOutput); this, commandHandler, RunFlags::NoOutput, codec);
} }
void GitPluginPrivate::stopInstantBlame() void GitPluginPrivate::stopInstantBlame()

View File

@@ -173,7 +173,7 @@ void SectionedProducts::onFetchSingleCollectionFinished(QNetworkReply *reply)
product->handle = handle; product->handle = handle;
const QJsonArray tags = obj.value("tags").toArray(); const QJsonArray tags = obj.value("tags").toArray();
for (auto val : tags) for (const auto &val : tags)
product->tags.append(val.toString()); product->tags.append(val.toString());
const auto images = obj.value("images").toArray(); const auto images = obj.value("images").toArray();

View File

@@ -8,7 +8,6 @@
#include <tracing/timelinemodelaggregator.h> #include <tracing/timelinemodelaggregator.h>
#include <tracing/timelinezoomcontrol.h> #include <tracing/timelinezoomcontrol.h>
#include <utils/runextensions.h>
#include <QPointer> #include <QPointer>
#include <unordered_map> #include <unordered_map>

View File

@@ -37,6 +37,7 @@ Project {
"diffeditor/diffeditor.qbs", "diffeditor/diffeditor.qbs",
"docker/docker.qbs", "docker/docker.qbs",
"fakevim/fakevim.qbs", "fakevim/fakevim.qbs",
"fossil/fossil.qbs",
"emacskeys/emacskeys.qbs", "emacskeys/emacskeys.qbs",
"genericprojectmanager/genericprojectmanager.qbs", "genericprojectmanager/genericprojectmanager.qbs",
"git/git.qbs", "git/git.qbs",

View File

@@ -246,7 +246,7 @@ void AbstractProcessStep::runTaskTree(const Tasking::Group &recipe)
d->m_taskTree.reset(new TaskTree(recipe)); d->m_taskTree.reset(new TaskTree(recipe));
connect(d->m_taskTree.get(), &TaskTree::progressValueChanged, this, [this](int value) { connect(d->m_taskTree.get(), &TaskTree::progressValueChanged, this, [this](int value) {
emit progress(qRound(double(value) * 100 / d->m_taskTree->progressMaximum()), {}); emit progress(qRound(double(value) * 100 / std::max(d->m_taskTree->progressMaximum(), 1)), {});
}); });
connect(d->m_taskTree.get(), &TaskTree::done, this, [this] { connect(d->m_taskTree.get(), &TaskTree::done, this, [this] {
emit finished(true); emit finished(true);

View File

@@ -31,7 +31,6 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/outputformatter.h> #include <utils/outputformatter.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <QApplication> #include <QApplication>

View File

@@ -9,7 +9,6 @@
#include "deployconfiguration.h" #include "deployconfiguration.h"
#include "kitinformation.h" #include "kitinformation.h"
#include "project.h" #include "project.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h" #include "projectexplorerconstants.h"
#include "sanitizerparser.h" #include "sanitizerparser.h"
#include "target.h" #include "target.h"
@@ -19,7 +18,6 @@
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/outputformatter.h> #include <utils/outputformatter.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <utils/variablechooser.h> #include <utils/variablechooser.h>
#include <QFormLayout> #include <QFormLayout>

View File

@@ -17,16 +17,74 @@
#include <utils/portlist.h> #include <utils/portlist.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/terminalcommand.h>
#include <utils/url.h> #include <utils/url.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDateTime> #include <QDateTime>
#ifdef Q_OS_WIN
#include <windows.h>
#include <stdlib.h>
#include <cstring>
#endif
using namespace ProjectExplorer::Constants; using namespace ProjectExplorer::Constants;
using namespace Utils; using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
static void startTerminalEmulator(const QString &workingDir, const Environment &env)
{
#ifdef Q_OS_WIN
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pinfo;
ZeroMemory(&pinfo, sizeof(pinfo));
static const auto quoteWinCommand = [](const QString &program) {
const QChar doubleQuote = QLatin1Char('"');
// add the program as the first arg ... it works better
QString programName = program;
programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote)
&& programName.contains(QLatin1Char(' '))) {
programName.prepend(doubleQuote);
programName.append(doubleQuote);
}
return programName;
};
const QString cmdLine = quoteWinCommand(qtcEnvironmentVariable("COMSPEC"));
// cmdLine is assumed to be detached -
// https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083
const QString totalEnvironment = env.toStringList().join(QChar(QChar::Null)) + QChar(QChar::Null);
LPVOID envPtr = (env != Environment::systemEnvironment())
? (WCHAR *)(totalEnvironment.utf16()) : nullptr;
const bool success = CreateProcessW(0, (WCHAR *)cmdLine.utf16(),
0, 0, FALSE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
envPtr, workingDir.isEmpty() ? 0 : (WCHAR *)workingDir.utf16(),
&si, &pinfo);
if (success) {
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
}
#else
const TerminalCommand term = TerminalCommand::terminalEmulator();
QProcess process;
process.setProgram(term.command);
process.setArguments(ProcessArgs::splitArgs(term.openArgs));
process.setProcessEnvironment(env.toProcessEnvironment());
process.setWorkingDirectory(workingDir);
process.startDetached();
#endif
}
DesktopDevice::DesktopDevice() DesktopDevice::DesktopDevice()
{ {
setFileAccess(DesktopDeviceFileAccess::instance()); setFileAccess(DesktopDeviceFileAccess::instance());
@@ -43,8 +101,14 @@ DesktopDevice::DesktopDevice()
const QString portRange = const QString portRange =
QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END); QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END);
setFreePorts(Utils::PortList::fromString(portRange)); setFreePorts(Utils::PortList::fromString(portRange));
setOpenTerminal([](const Environment &env, const FilePath &workingDir) {
Core::FileUtils::openTerminal(workingDir, env); setOpenTerminal([](const Environment &env, const FilePath &path) {
const QFileInfo fileInfo = path.toFileInfo();
const QString workingDir = QDir::toNativeSeparators(fileInfo.isDir() ?
fileInfo.absoluteFilePath() :
fileInfo.absolutePath());
const Environment realEnv = env.hasChanges() ? env : Environment::systemEnvironment();
startTerminalEmulator(workingDir, realEnv);
}); });
} }

View File

@@ -436,6 +436,12 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
return device->ensureReachable(other); return device->ensureReachable(other);
}; };
deviceHooks.openTerminal = [](const FilePath &filePath, const Environment &env) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return);
device->openTerminal(env, filePath);
};
DeviceProcessHooks processHooks; DeviceProcessHooks processHooks;
processHooks.processImplHook = [](const FilePath &filePath) -> ProcessInterface * { processHooks.processImplHook = [](const FilePath &filePath) -> ProcessInterface * {

View File

@@ -3,15 +3,12 @@
#include "treescanner.h" #include "treescanner.h"
#include "projectexplorerconstants.h"
#include "projectnodeshelper.h" #include "projectnodeshelper.h"
#include "projecttree.h" #include "projecttree.h"
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h> #include <coreplugin/vcsmanager.h>
#include <cppeditor/cppeditorconstants.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/runextensions.h> #include <utils/runextensions.h>

View File

@@ -1,7 +1,6 @@
// Copyright (C) 2020 The Qt Company Ltd. // Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "assetexporter.h" #include "assetexporter.h"
#include "assetexportpluginconstants.h"
#include "componentexporter.h" #include "componentexporter.h"
#include "exportnotification.h" #include "exportnotification.h"
@@ -14,7 +13,6 @@
#include "coreplugin/editormanager/editormanager.h" #include "coreplugin/editormanager/editormanager.h"
#include "utils/qtcassert.h" #include "utils/qtcassert.h"
#include "utils/runextensions.h" #include "utils/runextensions.h"
#include "variantproperty.h"
#include "projectexplorer/session.h" #include "projectexplorer/session.h"
#include "projectexplorer/project.h" #include "projectexplorer/project.h"

View File

@@ -38,13 +38,12 @@
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <utils/runextensions.h> #include <QLibraryInfo>
#include <QTextDocument> #include <QTextDocument>
#include <QTextStream> #include <QTextStream>
#include <QTimer> #include <QTimer>
#include <QSet> #include <QSet>
#include <QString> #include <QString>
#include <QLibraryInfo>
#include <qglobal.h> #include <qglobal.h>
using namespace Utils; using namespace Utils;

View File

@@ -1,7 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmlprofilerconstants.h"
#include "qmlprofilerdetailsrewriter.h" #include "qmlprofilerdetailsrewriter.h"
#include "qmlprofilermodelmanager.h" #include "qmlprofilermodelmanager.h"
#include "qmlprofilernotesmodel.h" #include "qmlprofilernotesmodel.h"
@@ -10,7 +9,6 @@
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
#include <tracing/tracestashfile.h> #include <tracing/tracestashfile.h>
#include <utils/runextensions.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QDebug> #include <QDebug>

View File

@@ -34,7 +34,6 @@
#include <utils/macroexpander.h> #include <utils/macroexpander.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <utils/winutils.h> #include <utils/winutils.h>

View File

@@ -39,6 +39,83 @@ struct Tr {
Q_DECLARE_TR_FUNCTIONS(::QmakeProjectManager) Q_DECLARE_TR_FUNCTIONS(::QmakeProjectManager)
}; };
// Locate a binary in a directory, applying all kinds of
// extensions the operating system supports.
static QString checkBinary(const QDir &dir, const QString &binary)
{
// naive UNIX approach
const QFileInfo info(dir.filePath(binary));
if (info.isFile() && info.isExecutable())
return info.absoluteFilePath();
// Does the OS have some weird extension concept or does the
// binary have a 3 letter extension?
if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost())
return {};
const int dotIndex = binary.lastIndexOf(QLatin1Char('.'));
if (dotIndex != -1 && dotIndex == binary.size() - 4)
return {};
switch (HostOsInfo::hostOs()) {
case OsTypeLinux:
case OsTypeOtherUnix:
case OsTypeOther:
break;
case OsTypeWindows: {
static const char *windowsExtensions[] = {".cmd", ".bat", ".exe", ".com"};
// Check the Windows extensions using the order
const int windowsExtensionCount = sizeof(windowsExtensions)/sizeof(const char*);
for (int e = 0; e < windowsExtensionCount; e ++) {
const QFileInfo windowsBinary(dir.filePath(binary + QLatin1String(windowsExtensions[e])));
if (windowsBinary.isFile() && windowsBinary.isExecutable())
return windowsBinary.absoluteFilePath();
}
}
break;
case OsTypeMac: {
// Check for Mac app folders
const QFileInfo appFolder(dir.filePath(binary + QLatin1String(".app")));
if (appFolder.isDir()) {
QString macBinaryPath = appFolder.absoluteFilePath();
macBinaryPath += QLatin1String("/Contents/MacOS/");
macBinaryPath += binary;
const QFileInfo macBinary(macBinaryPath);
if (macBinary.isFile() && macBinary.isExecutable())
return macBinary.absoluteFilePath();
}
}
break;
}
return {};
}
static QString locateBinary(const QString &path, const QString &binary)
{
// Absolute file?
const QFileInfo absInfo(binary);
if (absInfo.isAbsolute())
return checkBinary(absInfo.dir(), absInfo.fileName());
// Windows finds binaries in the current directory
if (HostOsInfo::isWindowsHost()) {
const QString currentDirBinary = checkBinary(QDir::current(), binary);
if (!currentDirBinary.isEmpty())
return currentDirBinary;
}
const QStringList paths = path.split(HostOsInfo::pathListSeparator());
if (paths.empty())
return {};
const QStringList::const_iterator cend = paths.constEnd();
for (QStringList::const_iterator it = paths.constBegin(); it != cend; ++it) {
const QDir dir(*it);
const QString rc = checkBinary(dir, binary);
if (!rc.isEmpty())
return rc;
}
return {};
}
static QString msgStartFailed(const QString &binary, QStringList arguments) static QString msgStartFailed(const QString &binary, QStringList arguments)
{ {
arguments.push_front(binary); arguments.push_front(binary);
@@ -122,7 +199,7 @@ static bool getEditorLaunchData(const CommandForQtVersion &commandForQtVersion,
// fallback // fallback
if (data->binary.isEmpty()) { if (data->binary.isEmpty()) {
const QString path = qtcEnvironmentVariable("PATH"); const QString path = qtcEnvironmentVariable("PATH");
data->binary = QtcProcess::locateBinary(path, commandForQtVersion(nullptr)); data->binary = locateBinary(path, commandForQtVersion(nullptr));
} }
if (data->binary.isEmpty()) { if (data->binary.isEmpty()) {

View File

@@ -29,7 +29,6 @@
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <utils/treemodel.h> #include <utils/treemodel.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <utils/variablechooser.h> #include <utils/variablechooser.h>

View File

@@ -96,11 +96,6 @@ void AbstractRemoteLinuxDeployService::setTarget(Target *target)
d->deviceConfiguration = DeviceKitAspect::device(kit()); d->deviceConfiguration = DeviceKitAspect::device(kit());
} }
void AbstractRemoteLinuxDeployService::setDevice(const IDevice::ConstPtr &device)
{
d->deviceConfiguration = device;
}
void AbstractRemoteLinuxDeployService::start() void AbstractRemoteLinuxDeployService::start()
{ {
QTC_ASSERT(!d->m_taskTree, return); QTC_ASSERT(!d->m_taskTree, return);

View File

@@ -83,8 +83,7 @@ public:
~AbstractRemoteLinuxDeployService() override; ~AbstractRemoteLinuxDeployService() override;
void setTarget(ProjectExplorer::Target *bc); void setTarget(ProjectExplorer::Target *bc);
// Only use setDevice() as fallback if no target is available
void setDevice(const ProjectExplorer::IDeviceConstPtr &device);
void start(); void start();
void stop(); void stop();

View File

@@ -103,7 +103,7 @@ bool ObjectsMapDocument::buildObjectsMapTree(const QByteArray &contents)
continue; continue;
const int tabPosition = line.indexOf(kPropertySeparator); const int tabPosition = line.indexOf(kPropertySeparator);
const QString objectName = QLatin1String(line.left(tabPosition).trimmed()); const QString objectName = QString::fromUtf8(line.left(tabPosition).trimmed());
if (!objectName.startsWith(ObjectsMapTreeItem::COLON)) { if (!objectName.startsWith(ObjectsMapTreeItem::COLON)) {
qDeleteAll(itemForName); qDeleteAll(itemForName);
return false; return false;

View File

@@ -29,10 +29,9 @@ enum class RunnerState {
RunRequested, RunRequested,
Interrupted, Interrupted,
InterruptRequested, InterruptRequested,
Canceling,
Canceled,
CancelRequested, CancelRequested,
CancelRequestedWhileInterrupted, CancelRequestedWhileInterrupted,
Canceled,
Finished Finished
}; };

View File

@@ -396,6 +396,7 @@ void SquishPerspective::setPerspectiveMode(PerspectiveMode mode)
m_stepOutAction->setEnabled(true); m_stepOutAction->setEnabled(true);
m_stopAction->setEnabled(true); m_stopAction->setEnabled(true);
break; break;
case Configuring:
case Querying: case Querying:
case NoMode: case NoMode:
m_pausePlayAction->setIcon(iconForType(IconType::Pause)); m_pausePlayAction->setIcon(iconForType(IconType::Pause));

View File

@@ -30,7 +30,7 @@ class SquishPerspective : public Utils::Perspective
{ {
Q_OBJECT Q_OBJECT
public: public:
enum PerspectiveMode { NoMode, Interrupted, Running, Recording, Querying }; enum PerspectiveMode { NoMode, Interrupted, Running, Recording, Querying, Configuring };
SquishPerspective(); SquishPerspective();
void initPerspective(); void initPerspective();

View File

@@ -143,7 +143,6 @@ static QString cmdToString(SquishRunnerProcess::RunnerCommand cmd)
case SquishRunnerProcess::Exit: return "exit\n"; case SquishRunnerProcess::Exit: return "exit\n";
case SquishRunnerProcess::Next: return "next\n"; case SquishRunnerProcess::Next: return "next\n";
case SquishRunnerProcess::PrintVariables: return "print variables\n"; case SquishRunnerProcess::PrintVariables: return "print variables\n";
case SquishRunnerProcess::Quit: return "quit\n";
case SquishRunnerProcess::Return: return "return\n"; case SquishRunnerProcess::Return: return "return\n";
case SquishRunnerProcess::Step: return "step\n"; case SquishRunnerProcess::Step: return "step\n";
} }

View File

@@ -15,7 +15,7 @@ class SquishRunnerProcess : public SquishProcessBase
{ {
Q_OBJECT Q_OBJECT
public: public:
enum RunnerCommand { Continue, EndRecord, Exit, Next, PrintVariables, Quit, Return, Step }; enum RunnerCommand { Continue, EndRecord, Exit, Next, PrintVariables, Return, Step };
enum RunnerMode { Run, StartAut, QueryServer, Record }; enum RunnerMode { Run, StartAut, QueryServer, Record };
enum RunnerError { InvalidSocket, MappedAutMissing }; enum RunnerError { InvalidSocket, MappedAutMissing };

View File

@@ -50,10 +50,9 @@ static QString runnerStateName(RunnerState state)
case RunnerState::RunRequested: return "RunRequested"; case RunnerState::RunRequested: return "RunRequested";
case RunnerState::Interrupted: return "Interrupted"; case RunnerState::Interrupted: return "Interrupted";
case RunnerState::InterruptRequested: return "InterruptedRequested"; case RunnerState::InterruptRequested: return "InterruptedRequested";
case RunnerState::Canceling: return "Canceling";
case RunnerState::Canceled: return "Canceled";
case RunnerState::CancelRequested: return "CancelRequested"; case RunnerState::CancelRequested: return "CancelRequested";
case RunnerState::CancelRequestedWhileInterrupted: return "CancelRequestedWhileInterrupted"; case RunnerState::CancelRequestedWhileInterrupted: return "CancelRequestedWhileInterrupted";
case RunnerState::Canceled: return "Canceled";
case RunnerState::Finished: return "Finished"; case RunnerState::Finished: return "Finished";
} }
return "ThouShallNotBeHere"; return "ThouShallNotBeHere";
@@ -297,6 +296,7 @@ void SquishTools::writeServerSettingsChanges(const QList<QStringList> &changes)
return; return;
} }
m_serverConfigChanges = changes; m_serverConfigChanges = changes;
m_perspective.setPerspectiveMode(SquishPerspective::Configuring);
startSquishServer(ServerConfigChangeRequested); startSquishServer(ServerConfigChangeRequested);
} }
@@ -363,10 +363,12 @@ void SquishTools::onServerStopped()
} }
m_serverConfigChanges.removeFirst(); m_serverConfigChanges.removeFirst();
if (!m_serverConfigChanges.isEmpty()) if (!m_serverConfigChanges.isEmpty()) {
startSquishServer(ServerConfigChangeRequested); startSquishServer(ServerConfigChangeRequested);
else return;
emit configChangesWritten(); }
emit configChangesWritten();
m_perspective.setPerspectiveMode(SquishPerspective::NoMode);
} else if (m_request == ServerStopRequested) { } else if (m_request == ServerStopRequested) {
m_request = None; m_request = None;
if (m_perspective.perspectiveMode() == SquishPerspective::Running) if (m_perspective.perspectiveMode() == SquishPerspective::Running)
@@ -603,7 +605,7 @@ void SquishTools::setupAndStartRecorder()
void SquishTools::stopRecorder() void SquishTools::stopRecorder()
{ {
QTC_ASSERT(m_secondaryRunner && m_secondaryRunner->isRunning(), return); QTC_ASSERT(m_secondaryRunner && m_secondaryRunner->isRunning(), return);
if (m_squishRunnerState == RunnerState::CancelRequested) { if (m_squishRunnerState == RunnerState::Canceled) {
qCDebug(LOG) << "Stopping recorder (exit)"; qCDebug(LOG) << "Stopping recorder (exit)";
m_secondaryRunner->writeCommand(SquishRunnerProcess::Exit); m_secondaryRunner->writeCommand(SquishRunnerProcess::Exit);
} else { } else {
@@ -663,7 +665,12 @@ void SquishTools::onRunnerFinished()
{ {
qCDebug(LOG) << "Runner finished"; qCDebug(LOG) << "Runner finished";
if (!m_shutdownInitiated) { if (!m_shutdownInitiated) {
logAndChangeRunnerState(RunnerState::Finished); if (m_squishRunnerState == RunnerState::CancelRequested
|| m_squishRunnerState == RunnerState::CancelRequestedWhileInterrupted) {
logAndChangeRunnerState(RunnerState::Canceled);
} else {
logAndChangeRunnerState(RunnerState::Finished);
}
if (m_request == RunTestRequested) if (m_request == RunTestRequested)
m_perspective.updateStatus(Tr::tr("Test run finished.")); m_perspective.updateStatus(Tr::tr("Test run finished."));
else if (m_request == RecordTestRequested) else if (m_request == RecordTestRequested)
@@ -814,8 +821,8 @@ void SquishTools::handlePrompt(const QString &fileName, int line, int column)
break; break;
case RunnerState::CancelRequested: case RunnerState::CancelRequested:
case RunnerState::CancelRequestedWhileInterrupted: case RunnerState::CancelRequestedWhileInterrupted:
logAndChangeRunnerState(RunnerState::Canceled);
stopRecorder(); stopRecorder();
logAndChangeRunnerState(RunnerState::Canceling);
break; break;
case RunnerState::Canceled: case RunnerState::Canceled:
QTC_CHECK(false); QTC_CHECK(false);
@@ -846,13 +853,9 @@ void SquishTools::handlePrompt(const QString &fileName, int line, int column)
} }
case RunnerState::CancelRequested: case RunnerState::CancelRequested:
case RunnerState::CancelRequestedWhileInterrupted: case RunnerState::CancelRequestedWhileInterrupted:
logAndChangeRunnerState(RunnerState::Canceled);
m_primaryRunner->writeCommand(SquishRunnerProcess::Exit); m_primaryRunner->writeCommand(SquishRunnerProcess::Exit);
clearLocationMarker(); clearLocationMarker();
logAndChangeRunnerState(RunnerState::Canceling);
break;
case RunnerState::Canceling:
m_primaryRunner->writeCommand(SquishRunnerProcess::Quit);
logAndChangeRunnerState(RunnerState::Canceled);
break; break;
case RunnerState::Canceled: case RunnerState::Canceled:
QTC_CHECK(false); QTC_CHECK(false);

View File

@@ -13,7 +13,6 @@
#include "../texteditorsettings.h" #include "../texteditorsettings.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/runextensions.h>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QRegularExpression> #include <QRegularExpression>

View File

@@ -157,10 +157,11 @@ void VcsBaseClientImpl::vcsExecWithHandler(const FilePath &workingDirectory,
const QStringList &arguments, const QStringList &arguments,
const QObject *context, const QObject *context,
const CommandHandler &handler, const CommandHandler &handler,
RunFlags additionalFlags) const RunFlags additionalFlags, QTextCodec *codec) const
{ {
VcsCommand *command = createCommand(workingDirectory); VcsCommand *command = createCommand(workingDirectory);
command->addFlags(additionalFlags); command->addFlags(additionalFlags);
command->setCodec(codec);
command->addJob({vcsBinary(), arguments}, vcsTimeoutS()); command->addJob({vcsBinary(), arguments}, vcsTimeoutS());
if (handler) { if (handler) {
const QObject *actualContext = context ? context : this; const QObject *actualContext = context ? context : this;

View File

@@ -83,7 +83,8 @@ public:
const QStringList &arguments, const QStringList &arguments,
const QObject *context, const QObject *context,
const CommandHandler &handler, const CommandHandler &handler,
RunFlags additionalFlags = RunFlags::None) const; RunFlags additionalFlags = RunFlags::None,
QTextCodec *codec = nullptr) const;
void vcsExec(const Utils::FilePath &workingDirectory, void vcsExec(const Utils::FilePath &workingDirectory,
const QStringList &arguments, const QStringList &arguments,
RunFlags additionalFlags = RunFlags::None) const; RunFlags additionalFlags = RunFlags::None) const;

View File

@@ -17,6 +17,7 @@
#include <cplusplus/TranslationUnit.h> #include <cplusplus/TranslationUnit.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/filepath.h>
#include "utils.h" #include "utils.h"
@@ -425,7 +426,7 @@ static Document::Ptr parse(const QString &fileName, const QByteArray &source,
if (verbose) if (verbose)
std::cout << "Parsing as " << qPrintable(parseModeToString(parseMode)) << "..."; std::cout << "Parsing as " << qPrintable(parseModeToString(parseMode)) << "...";
Document::Ptr doc = Document::create(fileName); Document::Ptr doc = Document::create(Utils::FilePath::fromString(fileName));
doc->control()->setDiagnosticClient(errorHandler); doc->control()->setDiagnosticClient(errorHandler);
doc->setUtf8Source(source); doc->setUtf8Source(source);
const bool parsed = doc->parse(parseMode); const bool parsed = doc->parse(parseMode);

View File

@@ -14,6 +14,8 @@
#include <cplusplus/Symbols.h> #include <cplusplus/Symbols.h>
#include <cplusplus/TranslationUnit.h> #include <cplusplus/TranslationUnit.h>
#include <utils/filepath.h>
#include "utils.h" #include "utils.h"
#include <QFile> #include <QFile>
@@ -74,7 +76,7 @@ int main(int argc, char *argv[])
const QByteArray source = file.readAll(); const QByteArray source = file.readAll();
file.close(); file.close();
Document::Ptr doc = Document::create(fileName); Document::Ptr doc = Document::create(Utils::FilePath::fromString(fileName));
doc->control()->setDiagnosticClient(0); doc->control()->setDiagnosticClient(0);
doc->setUtf8Source(source); doc->setUtf8Source(source);
doc->parse(); doc->parse();

View File

@@ -18,6 +18,8 @@
#include <cplusplus/Overview.h> #include <cplusplus/Overview.h>
#include <cplusplus/LookupContext.h> #include <cplusplus/LookupContext.h>
#include <utils/filepath.h>
#include "utils.h" #include "utils.h"
#include <QFile> #include <QFile>
@@ -450,7 +452,7 @@ int main(int argc, char *argv[])
const QByteArray source = file.readAll(); const QByteArray source = file.readAll();
file.close(); file.close();
Document::Ptr doc = Document::create(fileName); Document::Ptr doc = Document::create(Utils::FilePath::fromString(fileName));
//doc->control()->setDiagnosticClient(0); //doc->control()->setDiagnosticClient(0);
doc->setUtf8Source(source); doc->setUtf8Source(source);
doc->parse(); doc->parse();

File diff suppressed because it is too large Load Diff