aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/utils')
-rw-r--r--src/libs/utils/CMakeLists.txt204
-rw-r--r--src/libs/utils/algorithm.h409
-rw-r--r--src/libs/utils/basetreeview.cpp9
-rw-r--r--src/libs/utils/buildablehelperlibrary.cpp76
-rw-r--r--src/libs/utils/buildablehelperlibrary.h7
-rw-r--r--src/libs/utils/checkablemessagebox.cpp60
-rw-r--r--src/libs/utils/checkablemessagebox.h7
-rw-r--r--src/libs/utils/completingtextedit.cpp2
-rw-r--r--src/libs/utils/consoleprocess.h4
-rw-r--r--src/libs/utils/consoleprocess_unix.cpp12
-rw-r--r--src/libs/utils/consoleprocess_win.cpp4
-rw-r--r--src/libs/utils/cpplanguage_details.h3
-rw-r--r--src/libs/utils/delegates.cpp2
-rw-r--r--src/libs/utils/detailsbutton.cpp2
-rw-r--r--src/libs/utils/elidinglabel.cpp2
-rw-r--r--src/libs/utils/environment.cpp49
-rw-r--r--src/libs/utils/environment.h13
-rw-r--r--src/libs/utils/filecrumblabel.cpp10
-rw-r--r--src/libs/utils/filecrumblabel.h4
-rw-r--r--src/libs/utils/fileinprojectfinder.cpp193
-rw-r--r--src/libs/utils/fileinprojectfinder.h47
-rw-r--r--src/libs/utils/filesearch.cpp2
-rw-r--r--src/libs/utils/fileutils.cpp424
-rw-r--r--src/libs/utils/fileutils.h137
-rw-r--r--src/libs/utils/genericconstants.h37
-rw-r--r--src/libs/utils/highlightingitemdelegate.cpp3
-rw-r--r--src/libs/utils/images/dir.pngbin0 -> 862 bytes
-rw-r--r--src/libs/utils/images/pinned.pngbin0 -> 168 bytes
-rw-r--r--src/libs/utils/images/pinned@2x.pngbin0 -> 267 bytes
-rw-r--r--src/libs/utils/images/settings.pngbin0 -> 177 bytes
-rw-r--r--src/libs/utils/images/settings@2x.pngbin0 -> 316 bytes
-rw-r--r--src/libs/utils/images/sort_alphabetically.pngbin0 -> 139 bytes
-rw-r--r--src/libs/utils/images/sort_alphabetically@2x.pngbin0 -> 205 bytes
-rw-r--r--src/libs/utils/images/toggleprogressdetails.pngbin0 -> 167 bytes
-rw-r--r--src/libs/utils/images/toggleprogressdetails@2x.pngbin0 -> 216 bytes
-rw-r--r--src/libs/utils/images/unknownfile.pngbin0 -> 345 bytes
-rw-r--r--src/libs/utils/listmodel.h183
-rw-r--r--src/libs/utils/macroexpander.cpp30
-rw-r--r--src/libs/utils/macroexpander.h3
-rw-r--r--src/libs/utils/mimetypes/mimeprovider.cpp4
-rw-r--r--src/libs/utils/newclasswidget.cpp2
-rw-r--r--src/libs/utils/outputformatter.cpp3
-rw-r--r--src/libs/utils/outputformatter.h3
-rw-r--r--src/libs/utils/pathchooser.cpp20
-rw-r--r--src/libs/utils/pathchooser.h14
-rw-r--r--src/libs/utils/persistentsettings.cpp6
-rw-r--r--src/libs/utils/persistentsettings.h8
-rw-r--r--src/libs/utils/projectintropage.cpp2
-rw-r--r--src/libs/utils/qrcparser.cpp556
-rw-r--r--src/libs/utils/qrcparser.h85
-rw-r--r--src/libs/utils/qtcprocess.cpp11
-rw-r--r--src/libs/utils/qtcprocess.h13
-rw-r--r--src/libs/utils/reloadpromptutils.cpp7
-rw-r--r--src/libs/utils/reloadpromptutils.h4
-rw-r--r--src/libs/utils/runextensions.h57
-rw-r--r--src/libs/utils/savedaction.cpp2
-rw-r--r--src/libs/utils/savefile.cpp2
-rw-r--r--src/libs/utils/settingsaccessor.cpp59
-rw-r--r--src/libs/utils/settingsaccessor.h46
-rw-r--r--src/libs/utils/settingsselector.cpp2
-rw-r--r--src/libs/utils/shellcommand.cpp16
-rw-r--r--src/libs/utils/shellcommand.h14
-rw-r--r--src/libs/utils/smallstringlayout.h7
-rw-r--r--src/libs/utils/stringutils.cpp2
-rw-r--r--src/libs/utils/stylehelper.cpp14
-rw-r--r--src/libs/utils/synchronousprocess.cpp3
-rw-r--r--src/libs/utils/textfieldcombobox.cpp2
-rw-r--r--src/libs/utils/touchbar/touchbar.pri1
-rw-r--r--src/libs/utils/touchbar/touchbar_mac.mm10
-rw-r--r--src/libs/utils/unixutils.cpp2
-rw-r--r--src/libs/utils/utils-lib.pri8
-rw-r--r--src/libs/utils/utils.qbs5
-rw-r--r--src/libs/utils/utils.qrc10
-rw-r--r--src/libs/utils/utilsicons.cpp19
-rw-r--r--src/libs/utils/utilsicons.h7
-rw-r--r--src/libs/utils/variant.h19
-rw-r--r--src/libs/utils/wizardpage.h36
77 files changed, 2464 insertions, 555 deletions
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
new file mode 100644
index 0000000000..00307728a6
--- /dev/null
+++ b/src/libs/utils/CMakeLists.txt
@@ -0,0 +1,204 @@
+if (IDE_LIBEXEC_PATH AND IDE_BIN_PATH)
+ file(RELATIVE_PATH RELATIVE_TOOLS_PATH
+ "${CMAKE_INSTALL_PREFIX}/${IDE_BIN_PATH}" "${CMAKE_INSTALL_PREFIX}/${IDE_LIBEXEC_PATH}")
+else()
+ message(WARNING "IDE_LIBEXEC_PATH or IDE_BIN_PATH undefined when calculating tools path")
+ set(RELATIVE_TOOLS_PATH "")
+endif()
+
+add_qtc_library(Utils
+ DEPENDS Qt5::Xml
+ PUBLIC_DEPENDS Qt5::Concurrent Qt5::Core Qt5::Network Qt5::Qml Qt5::Gui Qt5::Widgets
+ DEFINES
+ "QTC_REL_TOOLS_PATH=\"${RELATIVE_TOOLS_PATH}\""
+ SOURCES
+ ../3rdparty/optional/optional.hpp
+ ../3rdparty/variant/variant.hpp
+ QtConcurrentTools
+ algorithm.h
+ ansiescapecodehandler.cpp ansiescapecodehandler.h
+ appmainwindow.cpp appmainwindow.h
+ basetreeview.cpp basetreeview.h
+ benchmarker.cpp benchmarker.h
+ buildablehelperlibrary.cpp buildablehelperlibrary.h
+ categorysortfiltermodel.cpp categorysortfiltermodel.h
+ changeset.cpp changeset.h
+ checkablemessagebox.cpp checkablemessagebox.h
+ classnamevalidatinglineedit.cpp classnamevalidatinglineedit.h
+ codegeneration.cpp codegeneration.h
+ completinglineedit.cpp completinglineedit.h
+ completingtextedit.cpp completingtextedit.h
+ consoleprocess.cpp consoleprocess.h consoleprocess_p.h
+ cpplanguage_details.h
+ crumblepath.cpp crumblepath.h
+ delegates.cpp delegates.h
+ declarationmacros.h
+ detailsbutton.cpp detailsbutton.h
+ detailswidget.cpp detailswidget.h
+ differ.cpp differ.h
+ dropsupport.cpp dropsupport.h
+ elfreader.cpp elfreader.h
+ elidinglabel.cpp elidinglabel.h
+ environment.cpp environment.h
+ environmentdialog.cpp environmentdialog.h
+ environmentmodel.cpp environmentmodel.h
+ execmenu.cpp execmenu.h
+ executeondestruction.h
+ fadingindicator.cpp fadingindicator.h
+ faketooltip.cpp faketooltip.h
+ fancylineedit.cpp fancylineedit.h
+ fancymainwindow.cpp fancymainwindow.h
+ filecrumblabel.cpp filecrumblabel.h
+ fileinprojectfinder.cpp fileinprojectfinder.h
+ filenamevalidatinglineedit.cpp filenamevalidatinglineedit.h
+ filesearch.cpp filesearch.h
+ filesystemwatcher.cpp filesystemwatcher.h
+ fileutils.cpp fileutils.h
+ filewizardpage.cpp filewizardpage.h
+ fixedsizeclicklabel.cpp fixedsizeclicklabel.h
+ flowlayout.cpp flowlayout.h
+ functiontraits.h
+ fuzzymatcher.cpp fuzzymatcher.h
+ genericconstants.h
+ globalfilechangeblocker.cpp globalfilechangeblocker.h
+ guard.cpp guard.h
+ headerviewstretcher.cpp headerviewstretcher.h
+ highlightingitemdelegate.cpp highlightingitemdelegate.h
+ historycompleter.cpp historycompleter.h
+ hostosinfo.cpp hostosinfo.h
+ htmldocextractor.cpp htmldocextractor.h
+ icon.cpp icon.h
+ itemviews.cpp itemviews.h
+ json.cpp json.h
+ jsontreeitem.cpp jsontreeitem.h
+ linecolumn.h
+ link.h
+ listmodel.h
+ listutils.h
+ macroexpander.cpp macroexpander.h
+ mapreduce.h
+ mimetypes/mimedatabase.cpp mimetypes/mimedatabase.h mimetypes/mimedatabase_p.h
+ mimetypes/mimeglobpattern.cpp mimetypes/mimeglobpattern_p.h
+ mimetypes/mimemagicrule.cpp mimetypes/mimemagicrule_p.h
+ mimetypes/mimemagicrulematcher.cpp mimetypes/mimemagicrulematcher_p.h
+ mimetypes/mimeprovider.cpp mimetypes/mimeprovider_p.h
+ mimetypes/mimetype.cpp mimetypes/mimetype.h mimetypes/mimetype_p.h
+ mimetypes/mimetypeparser.cpp mimetypes/mimetypeparser_p.h
+ navigationtreeview.cpp navigationtreeview.h
+ networkaccessmanager.cpp networkaccessmanager.h
+ newclasswidget.cpp newclasswidget.h newclasswidget.ui
+ optional.h
+ osspecificaspects.h
+ outputformat.h
+ outputformatter.cpp outputformatter.h
+ overridecursor.cpp overridecursor.h
+ parameteraction.cpp parameteraction.h
+ pathchooser.cpp pathchooser.h
+ pathlisteditor.cpp pathlisteditor.h
+ persistentsettings.cpp persistentsettings.h
+ pointeralgorithm.h
+ port.cpp port.h
+ portlist.cpp portlist.h
+ predicates.h
+ processhandle.cpp processhandle.h
+ progressindicator.cpp progressindicator.h
+ projectintropage.cpp projectintropage.h projectintropage.ui
+ proxyaction.cpp proxyaction.h
+ proxycredentialsdialog.cpp proxycredentialsdialog.h proxycredentialsdialog.ui
+ qrcparser.cpp qrcparser.h
+ qtcassert.cpp qtcassert.h
+ qtcolorbutton.cpp qtcolorbutton.h
+ qtcprocess.cpp qtcprocess.h
+ reloadpromptutils.cpp reloadpromptutils.h
+ removefiledialog.cpp removefiledialog.h removefiledialog.ui
+ runextensions.cpp runextensions.h
+ savedaction.cpp savedaction.h
+ savefile.cpp savefile.h
+ scopedswap.h
+ settingsaccessor.cpp settingsaccessor.h
+ settingsselector.cpp settingsselector.h
+ settingsutils.h
+ shellcommand.cpp shellcommand.h
+ shellcommandpage.cpp shellcommandpage.h
+ sizedarray.h
+ smallstring.h
+ smallstringfwd.h
+ smallstringio.h
+ smallstringiterator.h
+ smallstringlayout.h
+ smallstringliteral.h
+ smallstringmemory.h
+ smallstringvector.h
+ smallstringview.h
+ statuslabel.cpp statuslabel.h
+ stringutils.cpp stringutils.h
+ styledbar.cpp styledbar.h
+ stylehelper.cpp stylehelper.h
+ synchronousprocess.cpp synchronousprocess.h
+ templateengine.cpp templateengine.h
+ temporarydirectory.cpp temporarydirectory.h
+ temporaryfile.cpp temporaryfile.h
+ textfieldcheckbox.cpp textfieldcheckbox.h
+ textfieldcombobox.cpp textfieldcombobox.h
+ textfileformat.cpp textfileformat.h
+ textutils.cpp textutils.h
+ theme/theme.cpp theme/theme.h theme/theme_p.h
+ tooltip/effects.h
+ tooltip/reuse.h
+ tooltip/tips.cpp tooltip/tips.h
+ tooltip/tooltip.cpp tooltip/tooltip.h
+ touchbar/touchbar.h
+ treemodel.cpp treemodel.h
+ treeviewcombobox.cpp treeviewcombobox.h
+ uncommentselection.cpp uncommentselection.h
+ unixutils.cpp unixutils.h
+ url.cpp url.h
+ utils.qrc
+ utils_global.h
+ utilsicons.cpp utilsicons.h
+ variant.h
+ winutils.cpp winutils.h
+ wizard.cpp wizard.h
+ wizardpage.cpp wizardpage.h
+)
+
+extend_qtc_target(Utils CONDITION WIN32
+ SOURCES
+ consoleprocess_win.cpp
+ process_ctrlc_stub.cpp
+ touchbar/touchbar.cpp
+ DEPENDS
+ user32 iphlpapi ws2_32 shell32
+ DEFINES
+ _UNICODE UNICODE
+ PUBLIC_DEFINES
+ _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS
+)
+
+extend_qtc_target(Utils CONDITION APPLE
+ SOURCES
+ consoleprocess_unix.cpp
+ fileutils_mac.mm fileutils_mac.h
+ processhandle_mac.mm
+ theme/theme_mac.mm theme/theme_mac.h
+ touchbar/touchbar_appdelegate_mac.mm touchbar/touchbar_appdelegate_mac_p.h
+ touchbar/touchbar_mac.mm touchbar/touchbar_mac_p.h
+ DEPENDS
+ ${FWFoundation} ${FWAppKit}
+)
+
+extend_qtc_target(Utils CONDITION UNIX AND NOT APPLE
+ SOURCES
+ consoleprocess_unix.cpp
+ touchbar/touchbar.cpp
+)
+
+if (WIN32)
+ add_qtc_executable(qtcreator_process_stub
+ SOURCES process_stub_win.c
+ DEPENDS shell32
+ DEFINES _UNICODE UNICODE _CRT_SECURE_NO_WARNINGS
+ )
+else()
+ add_qtc_executable(qtcreator_process_stub SOURCES process_stub_unix.c)
+endif()
diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h
index bae78aacda..9e80755a3a 100644
--- a/src/libs/utils/algorithm.h
+++ b/src/libs/utils/algorithm.h
@@ -48,6 +48,323 @@
namespace Utils
{
+/////////////////////////
+// anyOf
+/////////////////////////
+template<typename T, typename F>
+bool anyOf(const T &container, F predicate);
+template<typename T, typename R, typename S>
+bool anyOf(const T &container, R (S::*predicate)() const);
+template<typename T, typename R, typename S>
+bool anyOf(const T &container, R S::*member);
+
+/////////////////////////
+// count
+/////////////////////////
+template<typename T, typename F>
+int count(const T &container, F predicate);
+
+/////////////////////////
+// allOf
+/////////////////////////
+template<typename T, typename F>
+bool allOf(const T &container, F predicate);
+
+/////////////////////////
+// erase
+/////////////////////////
+template<typename T, typename F>
+void erase(T &container, F predicate);
+
+/////////////////////////
+// contains
+/////////////////////////
+template<typename T, typename F>
+bool contains(const T &container, F function);
+template<typename T, typename R, typename S>
+bool contains(const T &container, R (S::*function)() const);
+template<typename C, typename R, typename S>
+bool contains(const C &container, R S::*member);
+
+/////////////////////////
+// findOr
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT typename C::value_type findOr(const C &container,
+ typename C::value_type other,
+ F function);
+template<typename T, typename R, typename S>
+Q_REQUIRED_RESULT typename T::value_type findOr(const T &container,
+ typename T::value_type other,
+ R (S::*function)() const);
+template<typename T, typename R, typename S>
+Q_REQUIRED_RESULT typename T::value_type findOr(const T &container,
+ typename T::value_type other,
+ R S::*member);
+
+/////////////////////////
+// findOrDefault
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
+ typename C::value_type>
+findOrDefault(const C &container, F function);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
+ typename C::value_type>
+findOrDefault(const C &container, R (S::*function)() const);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
+ typename C::value_type>
+findOrDefault(const C &container, R S::*member);
+
+/////////////////////////
+// indexOf
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT int indexOf(const C &container, F function);
+
+/////////////////////////
+// maxElementOr
+/////////////////////////
+template<typename T>
+typename T::value_type maxElementOr(const T &container, typename T::value_type other);
+
+/////////////////////////
+// filtered
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT C filtered(const C &container, F predicate);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT C filtered(const C &container, R (S::*predicate)() const);
+
+/////////////////////////
+// partition
+/////////////////////////
+// Recommended usage:
+// C hit;
+// C miss;
+// std::tie(hit, miss) = Utils::partition(container, predicate);
+template<typename C, typename F>
+Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, F predicate);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, R (S::*predicate)() const);
+
+/////////////////////////
+// filteredUnique
+/////////////////////////
+template<typename C>
+Q_REQUIRED_RESULT C filteredUnique(const C &container);
+
+/////////////////////////
+// qobject_container_cast
+/////////////////////////
+template<class T, template<typename> class Container, typename Base>
+Container<T> qobject_container_cast(const Container<Base> &container);
+
+/////////////////////////
+// static_container_cast
+/////////////////////////
+template<class T, template<typename> class Container, typename Base>
+Container<T> static_container_cast(const Container<Base> &container);
+
+/////////////////////////
+// sort
+/////////////////////////
+template<typename Container>
+inline void sort(Container &container);
+template<typename Container, typename Predicate>
+inline void sort(Container &container, Predicate p);
+template<typename Container, typename R, typename S>
+inline void sort(Container &container, R S::*member);
+template<typename Container, typename R, typename S>
+inline void sort(Container &container, R (S::*function)() const);
+
+/////////////////////////
+// reverseForeach
+/////////////////////////
+template<typename Container, typename Op>
+inline void reverseForeach(const Container &c, const Op &operation);
+
+/////////////////////////
+// toReferences
+/////////////////////////
+template<template<typename...> class ResultContainer, typename SourceContainer>
+auto toReferences(SourceContainer &sources);
+template<typename SourceContainer>
+auto toReferences(SourceContainer &sources);
+
+/////////////////////////
+// toConstReferences
+/////////////////////////
+template<template<typename...> class ResultContainer, typename SourceContainer>
+auto toConstReferences(const SourceContainer &sources);
+template<typename SourceContainer>
+auto toConstReferences(const SourceContainer &sources);
+
+/////////////////////////
+// take
+/////////////////////////
+template<class C, typename P>
+Q_REQUIRED_RESULT optional<typename C::value_type> take(C &container, P predicate);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT decltype(auto) take(C &container, R S::*member);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT decltype(auto) take(C &container, R (S::*function)() const);
+
+/////////////////////////
+// setUnionMerge
+/////////////////////////
+// Works like std::set_union but provides a merge function for items that match
+// !(a > b) && !(b > a) which normally means that there is an "equal" match.
+// It uses iterators to support move_iterators.
+template<class InputIt1, class InputIt2, class OutputIt, class Merge, class Compare>
+OutputIt setUnionMerge(InputIt1 first1,
+ InputIt1 last1,
+ InputIt2 first2,
+ InputIt2 last2,
+ OutputIt d_first,
+ Merge merge,
+ Compare comp);
+template<class InputIt1, class InputIt2, class OutputIt, class Merge>
+OutputIt setUnionMerge(
+ InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge);
+template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge, class Compare>
+OutputContainer setUnionMerge(InputContainer1 &&input1,
+ InputContainer2 &&input2,
+ Merge merge,
+ Compare comp);
+template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge>
+OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge);
+
+/////////////////////////
+// usize / ssize
+/////////////////////////
+template<typename Container>
+std::make_unsigned_t<typename Container::size_type> usize(Container container);
+template<typename Container>
+std::make_signed_t<typename Container::size_type> ssize(Container container);
+
+/////////////////////////
+// setUnion
+/////////////////////////
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp);
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result);
+
+/////////////////////////
+// transform
+/////////////////////////
+// function without result type deduction:
+template<typename ResultContainer, // complete result container type
+ typename SC, // input container type
+ typename F> // function type
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
+
+// function with result type deduction:
+template<template<typename> class C, // result container type
+ typename SC, // input container type
+ typename F, // function type
+ typename Value = typename std::decay_t<SC>::value_type,
+ typename Result = std::decay_t<std::result_of_t<F(Value &)>>,
+ typename ResultContainer = C<Result>>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
+template<template<typename, typename> class C, // result container type
+ typename SC, // input container type
+ typename F, // function type
+ typename Value = typename std::decay_t<SC>::value_type,
+ typename Result = std::decay_t<std::result_of_t<F(Value &)>>,
+ typename ResultContainer = C<Result, std::allocator<Result>>>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
+
+// member function without result type deduction:
+template<template<typename...> class C, // result container type
+ typename SC, // input container type
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const);
+
+// member function with result type deduction:
+template<typename ResultContainer, // complete result container type
+ typename SC, // input container type
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const);
+
+// member without result type deduction:
+template<typename ResultContainer, // complete result container type
+ typename SC, // input container
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p);
+
+// member with result type deduction:
+template<template<typename...> class C, // result container
+ typename SC, // input container
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p);
+
+// same container types for input and output, const input
+// function:
+template<template<typename...> class C, // container type
+ typename F, // function type
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, F function);
+
+// same container types for input and output, const input
+// member function:
+template<template<typename...> class C, // container type
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R (S::*p)() const);
+
+// same container types for input and output, const input
+// members:
+template<template<typename...> class C, // container
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R S::*p);
+
+// same container types for input and output, non-const input
+// function:
+template<template<typename...> class C, // container type
+ typename F, // function type
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, F function);
+
+// same container types for input and output, non-const input
+// member function:
+template<template<typename...> class C, // container type
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R (S::*p)() const);
+
+// same container types for input and output, non-const input
+// members:
+template<template<typename...> class C, // container
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R S::*p);
+
+/////////////////////////////////////////////////////////////////////////////
+//////// Implementations //////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
//////////////////
// anyOf
/////////////////
@@ -367,25 +684,23 @@ decltype(auto) transform(SC &&container, F function)
// function with result type deduction:
template<template<typename> class C, // result container type
- typename SC, // input container type
- typename F, // function type
- typename Value = typename std::decay_t<SC>::value_type,
- typename Result = std::decay_t<std::result_of_t<F(Value&)>>,
- typename ResultContainer = C<Result>>
-Q_REQUIRED_RESULT
-decltype(auto) transform(SC &&container, F function)
+ typename SC, // input container type
+ typename F, // function type
+ typename Value,
+ typename Result,
+ typename ResultContainer>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function)
{
return transform<ResultContainer>(std::forward<SC>(container), function);
}
template<template<typename, typename> class C, // result container type
- typename SC, // input container type
- typename F, // function type
- typename Value = typename std::decay_t<SC>::value_type,
- typename Result = std::decay_t<std::result_of_t<F(Value&)>>,
- typename ResultContainer = C<Result, std::allocator<Result>>>
-Q_REQUIRED_RESULT
-decltype(auto) transform(SC &&container, F function)
+ typename SC, // input container type
+ typename F, // function type
+ typename Value,
+ typename Result,
+ typename ResultContainer>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function)
{
return transform<ResultContainer>(std::forward<SC>(container), function);
}
@@ -862,4 +1177,70 @@ std::make_signed_t<typename Container::size_type> ssize(Container container)
{
return static_cast<std::make_signed_t<typename Container::size_type>>(container.size());
}
+
+template<typename Compare>
+struct CompareIter
+{
+ Compare compare;
+
+ explicit constexpr CompareIter(Compare compare)
+ : compare(std::move(compare))
+ {}
+
+ template<typename Iterator1, typename Iterator2>
+ constexpr bool operator()(Iterator1 it1, Iterator2 it2)
+ {
+ return bool(compare(*it1, *it2));
+ }
+};
+
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
+OutputIterator set_union_impl(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp)
+{
+ auto compare = CompareIter<Compare>(comp);
+
+ while (first1 != last1 && first2 != last2) {
+ if (compare(first1, first2)) {
+ *result = *first1;
+ ++first1;
+ } else if (compare(first2, first1)) {
+ *result = *first2;
+ ++first2;
+ } else {
+ *result = *first1;
+ ++first1;
+ ++first2;
+ }
+ ++result;
+ }
+
+ return std::copy(first2, last2, std::copy(first1, last1, result));
+}
+
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp)
+{
+ return Utils::set_union_impl(first1, last1, first2, last2, result, comp);
+}
+
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result)
+{
+ return Utils::set_union_impl(
+ first1, last1, first2, last2, result, std::less<typename InputIterator1::value_type>{});
+}
} // namespace Utils
diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp
index d77b8d4d55..352b17bb4b 100644
--- a/src/libs/utils/basetreeview.cpp
+++ b/src/libs/utils/basetreeview.cpp
@@ -183,7 +183,7 @@ public:
QAbstractItemModel *m = q->model();
for (int i = 0; i < 100 && a.isValid(); ++i) {
const QString s = m->data(a).toString();
- int w = fm.width(s) + 10;
+ int w = fm.horizontalAdvance(s) + 10;
if (column == 0) {
for (QModelIndex b = a.parent(); b.isValid(); b = b.parent())
w += ind;
@@ -204,7 +204,8 @@ public:
QTC_ASSERT(m, return -1);
QFontMetrics fm = q->fontMetrics();
- int minimum = fm.width(m->headerData(column, Qt::Horizontal).toString()) + 2 * fm.width(QLatin1Char('m'));
+ int minimum = fm.horizontalAdvance(m->headerData(column, Qt::Horizontal).toString())
+ + 2 * fm.horizontalAdvance(QLatin1Char('m'));
considerItems(column, q->indexAt(QPoint(1, 1)), &minimum, false);
QVariant extraIndices = m->data(QModelIndex(), BaseTreeView::ExtraIndicesForColumnWidth);
@@ -254,8 +255,8 @@ public:
// when we have that size already, in that case minimize.
if (currentSize == suggestedSize) {
QFontMetrics fm = q->fontMetrics();
- int headerSize = fm.width(q->model()->headerData(logicalIndex, Qt::Horizontal).toString());
- int minSize = 10 * fm.width(QLatin1Char('x'));
+ int headerSize = fm.horizontalAdvance(q->model()->headerData(logicalIndex, Qt::Horizontal).toString());
+ int minSize = 10 * fm.horizontalAdvance(QLatin1Char('x'));
targetSize = qMax(minSize, headerSize);
}
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index 3c53e09b2a..33ba624dc4 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -27,11 +27,13 @@
#include "hostosinfo.h"
#include "synchronousprocess.h"
-#include <QDir>
#include <QDateTime>
#include <QDebug>
+#include <QDir>
#include <QRegExp>
+#include <set>
+
namespace Utils {
bool BuildableHelperLibrary::isQtChooser(const QFileInfo &info)
@@ -71,32 +73,54 @@ static bool isQmake(const QString &path)
return !BuildableHelperLibrary::qtVersionForQMake(fi.absoluteFilePath()).isEmpty();
}
-FileName BuildableHelperLibrary::findSystemQt(const Environment &env)
+static FilePath findQmakeInDir(const FilePath &path)
{
- const QString qmake = QLatin1String("qmake");
- FileNameList paths = env.path();
- foreach (const FileName &path, paths) {
- if (path.isEmpty())
- continue;
-
- QDir dir(path.toString());
+ if (path.isEmpty())
+ return FilePath();
+
+ const QString qmake = "qmake";
+ QDir dir(path.toString());
+ if (dir.exists(qmake)) {
+ const QString qmakePath = dir.absoluteFilePath(qmake);
+ if (isQmake(qmakePath))
+ return FilePath::fromString(qmakePath);
+ }
- if (dir.exists(qmake)) {
- const QString qmakePath = dir.absoluteFilePath(qmake);
- if (isQmake(qmakePath))
- return FileName::fromString(qmakePath);
- }
+ // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order.
+ const QFileInfoList candidates = dir.entryInfoList(
+ BuildableHelperLibrary::possibleQMakeCommands(),
+ QDir::Files, QDir::Name | QDir::Reversed);
+ for (const QFileInfo &fi : candidates) {
+ if (fi.fileName() == qmake)
+ continue;
+ if (isQmake(fi.absoluteFilePath()))
+ return FilePath::fromFileInfo(fi);
+ }
+ return FilePath();
+}
- // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order.
- foreach (const QFileInfo &fi, dir.entryInfoList(possibleQMakeCommands(), QDir::Files, QDir::Name | QDir::Reversed)) {
- if (fi.fileName() == qmake)
- continue;
+FilePath BuildableHelperLibrary::findSystemQt(const Environment &env)
+{
+ const FilePathList list = findQtsInEnvironment(env, 1);
+ return list.size() == 1 ? list.first() : FilePath();
+}
- if (isQmake(fi.absoluteFilePath()))
- return FileName(fi);
- }
+FilePathList BuildableHelperLibrary::findQtsInEnvironment(const Environment &env, int maxCount)
+{
+ FilePathList qmakeList;
+ std::set<QString> canonicalEnvPaths;
+ const FilePathList paths = env.path();
+ for (const FilePath &path : paths) {
+ if (!canonicalEnvPaths.insert(path.toFileInfo().canonicalFilePath()).second)
+ continue;
+ const FilePath qmake = findQmakeInDir(path);
+ if (qmake.isEmpty())
+ continue;
+ qmakeList << qmake;
+ if (maxCount != -1 && qmakeList.size() == maxCount)
+ break;
}
- return FileName();
+ return qmakeList;
}
QString BuildableHelperLibrary::qtVersionForQMake(const QString &qmakePath)
@@ -165,7 +189,7 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath,
QString *errorMessage)
{
// try remove the directory
- if (!FileUtils::removeRecursively(FileName::fromString(targetDirectory), errorMessage))
+ if (!FileUtils::removeRecursively(FilePath::fromString(targetDirectory), errorMessage))
return false;
if (!QDir().mkpath(targetDirectory)) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The target directory %1 could not be created.").arg(targetDirectory);
@@ -196,7 +220,7 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath,
// Helper: Run a build process with merged stdout/stderr
static inline bool runBuildProcessI(QProcess &proc,
- const FileName &binary,
+ const FilePath &binary,
const QStringList &args,
int timeoutS,
bool ignoreNonNullExitCode,
@@ -237,7 +261,7 @@ static inline bool runBuildProcessI(QProcess &proc,
// Run a build process with merged stdout/stderr and qWarn about errors.
static bool runBuildProcess(QProcess &proc,
- const FileName &binary,
+ const FilePath &binary,
const QStringList &args,
int timeoutS,
bool ignoreNonNullExitCode,
@@ -276,7 +300,7 @@ bool BuildableHelperLibrary::buildHelper(const BuildHelperArguments &arguments,
arguments.directory));
log->append(newline);
- const FileName makeFullPath = arguments.environment.searchInPath(arguments.makeCommand);
+ const FilePath makeFullPath = arguments.environment.searchInPath(arguments.makeCommand);
if (QFileInfo::exists(arguments.directory + QLatin1String("/Makefile"))) {
if (makeFullPath.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary",
diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h
index c818749f2b..45d37d65c4 100644
--- a/src/libs/utils/buildablehelperlibrary.h
+++ b/src/libs/utils/buildablehelperlibrary.h
@@ -37,7 +37,8 @@ class QTCREATOR_UTILS_EXPORT BuildableHelperLibrary
public:
// returns the full path to the first qmake, qmake-qt4, qmake4 that has
// at least version 2.0.0 and thus is a qt4 qmake
- static FileName findSystemQt(const Environment &env);
+ static FilePath findSystemQt(const Environment &env);
+ static FilePathList findQtsInEnvironment(const Environment &env, int maxCount = -1);
static bool isQtChooser(const QFileInfo &info);
static QString qtChooserToQmakePath(const QString &path);
// return true if the qmake at qmakePath is a Qt (used by QtVersion)
@@ -60,9 +61,9 @@ public:
QString directory;
Environment environment;
- FileName qmakeCommand;
+ FilePath qmakeCommand;
QString targetMode;
- FileName mkspec;
+ FilePath mkspec;
QString proFilename;
QStringList qmakeArguments;
diff --git a/src/libs/utils/checkablemessagebox.cpp b/src/libs/utils/checkablemessagebox.cpp
index 857711fd8a..3ec411cfb3 100644
--- a/src/libs/utils/checkablemessagebox.cpp
+++ b/src/libs/utils/checkablemessagebox.cpp
@@ -32,6 +32,7 @@
#include <QLabel>
#include <QPushButton>
#include <QSettings>
+#include <QStyle>
/*!
\class Utils::CheckableMessageBox
@@ -107,6 +108,7 @@ public:
QCheckBox *checkBox = nullptr;
QDialogButtonBox *buttonBox = nullptr;
QAbstractButton *clickedButton = nullptr;
+ QMessageBox::Icon icon = QMessageBox::NoIcon;
};
CheckableMessageBox::CheckableMessageBox(QWidget *parent) :
@@ -148,17 +150,53 @@ void CheckableMessageBox::setText(const QString &t)
d->messageLabel->setText(t);
}
-QPixmap CheckableMessageBox::iconPixmap() const
-{
- if (const QPixmap *p = d->pixmapLabel->pixmap())
- return QPixmap(*p);
+QMessageBox::Icon CheckableMessageBox::icon() const
+{
+ return d->icon;
+}
+
+// See QMessageBoxPrivate::standardIcon
+static QPixmap pixmapForIcon(QMessageBox::Icon icon, QWidget *w)
+{
+ const QStyle *style = w ? w->style() : QApplication::style();
+ const int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, w);
+ QIcon tmpIcon;
+ switch (icon) {
+ case QMessageBox::Information:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, w);
+ break;
+ case QMessageBox::Warning:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, w);
+ break;
+ case QMessageBox::Critical:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, w);
+ break;
+ case QMessageBox::Question:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, w);
+ break;
+ default:
+ break;
+ }
+ if (!tmpIcon.isNull()) {
+ QWindow *window = nullptr;
+ if (w) {
+ window = w->windowHandle();
+ if (!window) {
+ if (const QWidget *nativeParent = w->nativeParentWidget())
+ window = nativeParent->windowHandle();
+ }
+ }
+ return tmpIcon.pixmap(window, QSize(iconSize, iconSize));
+ }
return QPixmap();
}
-void CheckableMessageBox::setIconPixmap(const QPixmap &p)
+void CheckableMessageBox::setIcon(QMessageBox::Icon icon)
{
- d->pixmapLabel->setPixmap(p);
- d->pixmapLabel->setVisible(!p.isNull());
+ d->icon = icon;
+ const QPixmap pixmap = pixmapForIcon(icon, this);
+ d->pixmapLabel->setPixmap(pixmap);
+ d->pixmapLabel->setVisible(!pixmap.isNull());
}
bool CheckableMessageBox::isChecked() const
@@ -239,7 +277,7 @@ CheckableMessageBox::question(QWidget *parent,
{
CheckableMessageBox mb(parent);
mb.setWindowTitle(title);
- mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question));
+ mb.setIcon(QMessageBox::Question);
mb.setText(question);
mb.setCheckBoxText(checkBoxText);
mb.setChecked(*checkBoxSetting);
@@ -261,7 +299,7 @@ CheckableMessageBox::information(QWidget *parent,
{
CheckableMessageBox mb(parent);
mb.setWindowTitle(title);
- mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Information));
+ mb.setIcon(QMessageBox::Information);
mb.setText(text);
mb.setCheckBoxText(checkBoxText);
mb.setChecked(*checkBoxSetting);
@@ -297,9 +335,7 @@ void initDoNotAskAgainMessageBox(CheckableMessageBox &messageBox, const QString
DoNotAskAgainType type)
{
messageBox.setWindowTitle(title);
- messageBox.setIconPixmap(QMessageBox::standardIcon(type == Information
- ? QMessageBox::Information
- : QMessageBox::Question));
+ messageBox.setIcon(type == Information ? QMessageBox::Information : QMessageBox::Question);
messageBox.setText(text);
messageBox.setCheckBoxVisible(true);
messageBox.setCheckBoxText(type == Information ? CheckableMessageBox::msgDoNotShowAgain()
diff --git a/src/libs/utils/checkablemessagebox.h b/src/libs/utils/checkablemessagebox.h
index c6359f72cd..042e88aa96 100644
--- a/src/libs/utils/checkablemessagebox.h
+++ b/src/libs/utils/checkablemessagebox.h
@@ -42,7 +42,7 @@ class QTCREATOR_UTILS_EXPORT CheckableMessageBox : public QDialog
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
- Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
+ Q_PROPERTY(QMessageBox::Icon icon READ icon WRITE setIcon)
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText)
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
@@ -109,9 +109,8 @@ public:
QDialogButtonBox::StandardButton defaultButton() const;
void setDefaultButton(QDialogButtonBox::StandardButton s);
- // See static QMessageBox::standardPixmap()
- QPixmap iconPixmap() const;
- void setIconPixmap (const QPixmap &p);
+ QMessageBox::Icon icon() const;
+ void setIcon(QMessageBox::Icon icon);
// Query the result
QAbstractButton *clickedButton() const;
diff --git a/src/libs/utils/completingtextedit.cpp b/src/libs/utils/completingtextedit.cpp
index f4d7b0441c..3a34973c00 100644
--- a/src/libs/utils/completingtextedit.cpp
+++ b/src/libs/utils/completingtextedit.cpp
@@ -114,7 +114,7 @@ void CompletingTextEdit::setCompleter(QCompleter *c)
completer()->setWidget(this);
completer()->setCompletionMode(QCompleter::PopupCompletion);
- connect(completer(), static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::activated),
+ connect(completer(), QOverload<const QString &>::of(&QCompleter::activated),
this, [this](const QString &str) { d->insertCompletion(str); });
}
diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h
index 28be67f0bf..3dec9838c3 100644
--- a/src/libs/utils/consoleprocess.h
+++ b/src/libs/utils/consoleprocess.h
@@ -70,7 +70,9 @@ public:
QProcess::ProcessError error() const;
QString errorString() const;
- bool start(const QString &program, const QString &args);
+ enum class MetaCharMode { Abort, Ignore };
+ bool start(const QString &program, const QString &args,
+ MetaCharMode metaCharMode = MetaCharMode::Abort);
public slots:
void stop();
diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp
index 92b69952f6..43afffa0a2 100644
--- a/src/libs/utils/consoleprocess_unix.cpp
+++ b/src/libs/utils/consoleprocess_unix.cpp
@@ -65,7 +65,7 @@ void ConsoleProcess::setSettings(QSettings *settings)
d->m_settings = settings;
}
-bool ConsoleProcess::start(const QString &program, const QString &args)
+bool ConsoleProcess::start(const QString &program, const QString &args, MetaCharMode metaCharMode)
{
if (isRunning())
return false;
@@ -75,7 +75,8 @@ bool ConsoleProcess::start(const QString &program, const QString &args)
QtcProcess::SplitError perr;
QtcProcess::Arguments pargs = QtcProcess::prepareArgs(args, &perr, HostOsInfo::hostOs(),
- &d->m_environment, &d->m_workingDir);
+ &d->m_environment, &d->m_workingDir,
+ metaCharMode == MetaCharMode::Abort);
QString pcmd;
if (perr == QtcProcess::SplitOk) {
pcmd = program;
@@ -436,12 +437,6 @@ bool ConsoleProcess::startTerminalEmulator(QSettings *settings, const QString &w
const Utils::Environment &env)
{
const TerminalCommand term = terminalEmulator(settings);
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- // for 5.9 and below we cannot set the environment
- Q_UNUSED(env);
- return QProcess::startDetached(term.command, QtcProcess::splitArgs(term.openArgs),
- workingDir);
-#else
QProcess process;
process.setProgram(term.command);
process.setArguments(QtcProcess::splitArgs(term.openArgs));
@@ -449,7 +444,6 @@ bool ConsoleProcess::startTerminalEmulator(QSettings *settings, const QString &w
process.setWorkingDirectory(workingDir);
return process.startDetached();
-#endif
}
} // namespace Utils
diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp
index 2a68ddaba8..be65c42cc8 100644
--- a/src/libs/utils/consoleprocess_win.cpp
+++ b/src/libs/utils/consoleprocess_win.cpp
@@ -51,8 +51,10 @@ qint64 ConsoleProcess::applicationMainThreadID() const
return d->m_appMainThreadId;
}
-bool ConsoleProcess::start(const QString &program, const QString &args)
+bool ConsoleProcess::start(const QString &program, const QString &args, MetaCharMode metaCharMode)
{
+ Q_UNUSED(metaCharMode);
+
if (isRunning())
return false;
diff --git a/src/libs/utils/cpplanguage_details.h b/src/libs/utils/cpplanguage_details.h
index 43474d03cb..e9c9a5aa40 100644
--- a/src/libs/utils/cpplanguage_details.h
+++ b/src/libs/utils/cpplanguage_details.h
@@ -29,9 +29,10 @@
namespace Utils {
-enum class Language : unsigned char { C, Cxx };
+enum class Language : unsigned char { None, C, Cxx };
enum class LanguageVersion : unsigned char {
+ None,
C89,
C99,
C11,
diff --git a/src/libs/utils/delegates.cpp b/src/libs/utils/delegates.cpp
index a677c8c992..2240e8a6a4 100644
--- a/src/libs/utils/delegates.cpp
+++ b/src/libs/utils/delegates.cpp
@@ -84,7 +84,7 @@ void AnnotatedItemDelegate::paint(QPainter *painter,
painter->save();
painter->setPen(disabled.color(QPalette::WindowText));
- static int extra = opt.fontMetrics.width(m_delimiter) + 10;
+ static int extra = opt.fontMetrics.horizontalAdvance(m_delimiter) + 10;
const QPixmap &pixmap = opt.icon.pixmap(opt.decorationSize);
const QRect &iconRect = style->itemPixmapRect(opt.rect, opt.decorationAlignment, pixmap);
const QRect &displayRect = style->itemTextRect(opt.fontMetrics, opt.rect,
diff --git a/src/libs/utils/detailsbutton.cpp b/src/libs/utils/detailsbutton.cpp
index 5f2c88eca3..329975afdb 100644
--- a/src/libs/utils/detailsbutton.cpp
+++ b/src/libs/utils/detailsbutton.cpp
@@ -79,7 +79,7 @@ DetailsButton::DetailsButton(QWidget *parent) : QAbstractButton(parent), m_fader
QSize DetailsButton::sizeHint() const
{
// TODO: Adjust this when icons become available!
- const int w = fontMetrics().width(text()) + 32;
+ const int w = fontMetrics().horizontalAdvance(text()) + 32;
if (HostOsInfo::isMacHost())
return QSize(w, 34);
return QSize(w, 22);
diff --git a/src/libs/utils/elidinglabel.cpp b/src/libs/utils/elidinglabel.cpp
index e584bd8bb6..1d90665af5 100644
--- a/src/libs/utils/elidinglabel.cpp
+++ b/src/libs/utils/elidinglabel.cpp
@@ -66,7 +66,7 @@ void ElidingLabel::paintEvent(QPaintEvent *)
QRect contents = contentsRect().adjusted(m, m, -m, -m);
QFontMetrics fm = fontMetrics();
QString txt = text();
- if (txt.length() > 4 && fm.width(txt) > contents.width()) {
+ if (txt.length() > 4 && fm.horizontalAdvance(txt) > contents.width()) {
setToolTip(txt);
txt = fm.elidedText(txt, m_elideMode, contents.width());
} else {
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index a82d6c27f0..d61a75ebf7 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -392,14 +392,14 @@ void Environment::clear()
m_values.clear();
}
-FileName Environment::searchInDirectory(const QStringList &execs, const FileName &directory,
- QSet<FileName> &alreadyChecked) const
+FilePath Environment::searchInDirectory(const QStringList &execs, const FilePath &directory,
+ QSet<FilePath> &alreadyChecked) const
{
const int checkedCount = alreadyChecked.count();
alreadyChecked.insert(directory);
if (directory.isEmpty() || alreadyChecked.count() == checkedCount)
- return FileName();
+ return FilePath();
const QString dir = directory.toString();
@@ -407,9 +407,9 @@ FileName Environment::searchInDirectory(const QStringList &execs, const FileName
for (const QString &exec : execs) {
fi.setFile(dir, exec);
if (fi.isFile() && fi.isExecutable())
- return FileName::fromString(fi.absoluteFilePath());
+ return FilePath::fromString(fi.absoluteFilePath());
}
- return FileName();
+ return FilePath();
}
QStringList Environment::appendExeExtensions(const QString &executable) const
@@ -435,23 +435,25 @@ bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) con
const QStringList exe2List = appendExeExtensions(exe2);
for (const QString &i1 : exe1List) {
for (const QString &i2 : exe2List) {
- const FileName f1 = FileName::fromString(i1);
- const FileName f2 = FileName::fromString(i2);
+ const FilePath f1 = FilePath::fromString(i1);
+ const FilePath f2 = FilePath::fromString(i2);
if (f1 == f2)
return true;
if (FileUtils::resolveSymlinks(f1) == FileUtils::resolveSymlinks(f2))
return true;
+ if (FileUtils::fileId(f1) == FileUtils::fileId(f2))
+ return true;
}
}
return false;
}
-FileName Environment::searchInPath(const QString &executable,
- const FileNameList &additionalDirs,
+FilePath Environment::searchInPath(const QString &executable,
+ const FilePathList &additionalDirs,
const PathFilter &func) const
{
if (executable.isEmpty())
- return FileName();
+ return FilePath();
const QString exec = QDir::cleanPath(expandVariables(executable));
const QFileInfo fi(exec);
@@ -462,34 +464,34 @@ FileName Environment::searchInPath(const QString &executable,
for (const QString &path : execs) {
QFileInfo pfi = QFileInfo(path);
if (pfi.isFile() && pfi.isExecutable())
- return FileName::fromString(path);
+ return FilePath::fromString(path);
}
- return FileName::fromString(exec);
+ return FilePath::fromString(exec);
}
- QSet<FileName> alreadyChecked;
- for (const FileName &dir : additionalDirs) {
- FileName tmp = searchInDirectory(execs, dir, alreadyChecked);
+ QSet<FilePath> alreadyChecked;
+ for (const FilePath &dir : additionalDirs) {
+ FilePath tmp = searchInDirectory(execs, dir, alreadyChecked);
if (!tmp.isEmpty() && (!func || func(tmp)))
return tmp;
}
if (executable.contains('/'))
- return FileName();
+ return FilePath();
- for (const FileName &p : path()) {
- FileName tmp = searchInDirectory(execs, p, alreadyChecked);
+ for (const FilePath &p : path()) {
+ FilePath tmp = searchInDirectory(execs, p, alreadyChecked);
if (!tmp.isEmpty() && (!func || func(tmp)))
return tmp;
}
- return FileName();
+ return FilePath();
}
-FileNameList Environment::path() const
+FilePathList Environment::path() const
{
const QStringList pathComponents = value("PATH")
.split(OsSpecificAspects::pathListSeparator(m_osType), QString::SkipEmptyParts);
- return Utils::transform(pathComponents, &FileName::fromUserInput);
+ return Utils::transform(pathComponents, &FilePath::fromUserInput);
}
QString Environment::value(const QString &key) const
@@ -688,6 +690,11 @@ QString Environment::expandVariables(const QString &input) const
return result;
}
+FilePath Environment::expandVariables(const FilePath &variables) const
+{
+ return FilePath::fromString(expandVariables(variables.toString()));
+}
+
QStringList Environment::expandVariables(const QStringList &variables) const
{
return Utils::transform(variables, [this](const QString &i) { return expandVariables(i); });
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index cab78a082b..f1e957ab6d 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -124,17 +124,18 @@ public:
Environment::const_iterator constEnd() const;
Environment::const_iterator constFind(const QString &name) const;
- using PathFilter = std::function<bool(const FileName &)>;
- FileName searchInPath(const QString &executable,
- const FileNameList &additionalDirs = FileNameList(),
+ using PathFilter = std::function<bool(const FilePath &)>;
+ FilePath searchInPath(const QString &executable,
+ const FilePathList &additionalDirs = FilePathList(),
const PathFilter &func = PathFilter()) const;
- FileNameList path() const;
+ FilePathList path() const;
QStringList appendExeExtensions(const QString &executable) const;
bool isSameExecutable(const QString &exe1, const QString &exe2) const;
QString expandVariables(const QString &input) const;
+ FilePath expandVariables(const FilePath &input) const;
QStringList expandVariables(const QStringList &input) const;
bool operator!=(const Environment &other) const;
@@ -143,8 +144,8 @@ public:
static void modifySystemEnvironment(const QList<EnvironmentItem> &list); // use with care!!!
private:
- FileName searchInDirectory(const QStringList &execs, const FileName &directory,
- QSet<FileName> &alreadyChecked) const;
+ FilePath searchInDirectory(const QStringList &execs, const FilePath &directory,
+ QSet<FilePath> &alreadyChecked) const;
QMap<QString, QString> m_values;
OsType m_osType;
};
diff --git a/src/libs/utils/filecrumblabel.cpp b/src/libs/utils/filecrumblabel.cpp
index a4bbe37c44..cf03af553c 100644
--- a/src/libs/utils/filecrumblabel.cpp
+++ b/src/libs/utils/filecrumblabel.cpp
@@ -38,22 +38,22 @@ FileCrumbLabel::FileCrumbLabel(QWidget *parent)
setTextFormat(Qt::RichText);
setWordWrap(true);
connect(this, &QLabel::linkActivated, this, [this](const QString &url) {
- emit pathClicked(FileName::fromString(QUrl(url).toLocalFile()));
+ emit pathClicked(FilePath::fromString(QUrl(url).toLocalFile()));
});
- setPath(FileName());
+ setPath(FilePath());
}
-static QString linkForPath(const FileName &path, const QString &display)
+static QString linkForPath(const FilePath &path, const QString &display)
{
return "<a href=\""
+ QUrl::fromLocalFile(path.toString()).toString(QUrl::FullyEncoded) + "\">"
+ display + "</a>";
}
-void FileCrumbLabel::setPath(const FileName &path)
+void FileCrumbLabel::setPath(const FilePath &path)
{
QStringList links;
- FileName current = path;
+ FilePath current = path;
while (!current.isEmpty()) {
const QString fileName = current.fileName();
if (!fileName.isEmpty()) {
diff --git a/src/libs/utils/filecrumblabel.h b/src/libs/utils/filecrumblabel.h
index 6320b115c0..05dd050812 100644
--- a/src/libs/utils/filecrumblabel.h
+++ b/src/libs/utils/filecrumblabel.h
@@ -38,10 +38,10 @@ class QTCREATOR_UTILS_EXPORT FileCrumbLabel : public QLabel
public:
FileCrumbLabel(QWidget *parent = nullptr);
- void setPath(const FileName &path);
+ void setPath(const FilePath &path);
signals:
- void pathClicked(const FileName &path);
+ void pathClicked(const FilePath &path);
};
} // Utils
diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp
index 2be64260e8..3dbde17792 100644
--- a/src/libs/utils/fileinprojectfinder.cpp
+++ b/src/libs/utils/fileinprojectfinder.cpp
@@ -24,15 +24,20 @@
****************************************************************************/
#include "fileinprojectfinder.h"
+
+#include "algorithm.h"
#include "fileutils.h"
#include "hostosinfo.h"
+#include "qrcparser.h"
#include "qtcassert.h"
+#include <QCursor>
#include <QDebug>
+#include <QDir>
#include <QFileInfo>
#include <QLoggingCategory>
+#include <QMenu>
#include <QUrl>
-#include <QDir>
#include <algorithm>
@@ -77,7 +82,7 @@ static bool checkPath(const QString &candidate, int matchLength,
FileInProjectFinder::FileInProjectFinder() = default;
FileInProjectFinder::~FileInProjectFinder() = default;
-void FileInProjectFinder::setProjectDirectory(const FileName &absoluteProjectPath)
+void FileInProjectFinder::setProjectDirectory(const FilePath &absoluteProjectPath)
{
if (absoluteProjectPath == m_projectDir)
return;
@@ -90,21 +95,22 @@ void FileInProjectFinder::setProjectDirectory(const FileName &absoluteProjectPat
m_cache.clear();
}
-FileName FileInProjectFinder::projectDirectory() const
+FilePath FileInProjectFinder::projectDirectory() const
{
return m_projectDir;
}
-void FileInProjectFinder::setProjectFiles(const FileNameList &projectFiles)
+void FileInProjectFinder::setProjectFiles(const FilePathList &projectFiles)
{
if (m_projectFiles == projectFiles)
return;
m_projectFiles = projectFiles;
m_cache.clear();
+ m_qrcUrlFinder.setProjectFiles(projectFiles);
}
-void FileInProjectFinder::setSysroot(const FileName &sysroot)
+void FileInProjectFinder::setSysroot(const FilePath &sysroot)
{
if (m_sysroot == sysroot)
return;
@@ -113,7 +119,7 @@ void FileInProjectFinder::setSysroot(const FileName &sysroot)
m_cache.clear();
}
-void FileInProjectFinder::addMappedPath(const FileName &localFilePath, const QString &remoteFilePath)
+void FileInProjectFinder::addMappedPath(const FilePath &localFilePath, const QString &remoteFilePath)
{
const QStringList segments = remoteFilePath.split('/', QString::SkipEmptyParts);
@@ -136,18 +142,29 @@ void FileInProjectFinder::addMappedPath(const FileName &localFilePath, const QSt
folder specified. Third, we walk the list of project files, and search for a file name match
there. If all fails, it returns the original path from the file URL.
*/
-QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
+FilePathList FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
{
qCDebug(finderLog) << "FileInProjectFinder: trying to find file" << fileUrl.toString() << "...";
+ if (fileUrl.scheme() == "qrc" || fileUrl.toString().startsWith(':')) {
+ const FilePathList result = m_qrcUrlFinder.find(fileUrl);
+ if (!result.isEmpty()) {
+ if (success)
+ *success = true;
+ return result;
+ }
+ }
+
QString originalPath = fileUrl.toLocalFile();
if (originalPath.isEmpty()) // e.g. qrc://
originalPath = fileUrl.path();
- QString result = originalPath;
+ FilePathList result;
bool found = findFileOrDirectory(originalPath, [&](const QString &fileName, int) {
- result = fileName;
+ result << FilePath::fromString(fileName);
});
+ if (!found)
+ result << FilePath::fromString(originalPath);
if (success)
*success = found;
@@ -155,12 +172,12 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
return result;
}
-bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QString &found,
+bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QStringList &found,
int matchLength, const char *where) const
{
qCDebug(finderLog) << "FileInProjectFinder: found" << found << where;
CacheEntry entry;
- entry.path = found;
+ entry.paths = found;
entry.matchLength = matchLength;
m_cache.insert(originalPath, entry);
return true;
@@ -189,8 +206,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (node) {
if (!node->localPath.isEmpty()) {
const QString localPath = node->localPath.toString();
- if (checkPath(localPath, origLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, localPath, origLength, "in mapped paths");
+ if (checkPath(localPath, origLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(localPath), origLength,
+ "in mapped paths");
+ }
} else if (directoryHandler) {
directoryHandler(node->children.keys(), origLength);
qCDebug(finderLog) << "FileInProjectFinder: found virtual directory" << originalPath
@@ -203,13 +222,18 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (it != m_cache.end()) {
qCDebug(finderLog) << "FileInProjectFinder: checking cache ...";
// check if cached path is still there
- const CacheEntry &candidate = it.value();
- if (checkPath(candidate.path, candidate.matchLength, fileHandler, directoryHandler)) {
- qCDebug(finderLog) << "FileInProjectFinder: found" << candidate.path << "in the cache";
- return true;
- } else {
- m_cache.erase(it);
+ CacheEntry &candidate = it.value();
+ for (auto pathIt = candidate.paths.begin(); pathIt != candidate.paths.end();) {
+ if (checkPath(*pathIt, candidate.matchLength, fileHandler, directoryHandler)) {
+ qCDebug(finderLog) << "FileInProjectFinder: found" << *pathIt << "in the cache";
+ ++pathIt;
+ } else {
+ pathIt = candidate.paths.erase(pathIt);
+ }
}
+ if (!candidate.paths.empty())
+ return true;
+ m_cache.erase(it);
}
if (!m_projectDir.isEmpty()) {
@@ -231,7 +255,7 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (prefixToIgnore == -1
&& checkPath(originalPath, origLength, fileHandler, directoryHandler)) {
- return handleSuccess(originalPath, originalPath, origLength,
+ return handleSuccess(originalPath, QStringList(originalPath), origLength,
"in project directory");
}
}
@@ -254,8 +278,11 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
candidate.remove(0, prefixToIgnore);
candidate.prepend(m_projectDir.toString());
const int matchLength = origLength - prefixToIgnore;
- if (checkPath(candidate, matchLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, candidate, matchLength, "in project directory");
+ // FIXME: This might be a worse match than what we find later.
+ if (checkPath(candidate, matchLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(candidate), matchLength,
+ "in project directory");
+ }
prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1);
}
}
@@ -264,31 +291,38 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
qCDebug(finderLog) << "FileInProjectFinder: checking project files ...";
QStringList matches;
- const QString lastSegment = FileName::fromString(originalPath).fileName();
+ const QString lastSegment = FilePath::fromString(originalPath).fileName();
if (fileHandler)
matches.append(filesWithSameFileName(lastSegment));
if (directoryHandler)
matches.append(pathSegmentsWithSameName(lastSegment));
- const QString matchedFilePath = bestMatch(matches, originalPath);
- const int matchLength = commonPostFixLength(matchedFilePath, originalPath);
- if (!matchedFilePath.isEmpty()
- && checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler)) {
- return handleSuccess(originalPath, matchedFilePath, matchLength,
- "when matching project files");
+ const QStringList matchedFilePaths = bestMatches(matches, originalPath);
+ if (!matchedFilePaths.empty()) {
+ const int matchLength = commonPostFixLength(matchedFilePaths.first(), originalPath);
+ QStringList hits;
+ for (const QString &matchedFilePath : matchedFilePaths) {
+ if (checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler))
+ hits << matchedFilePath;
+ }
+ if (!hits.empty())
+ return handleSuccess(originalPath, hits, matchLength, "when matching project files");
}
CacheEntry foundPath = findInSearchPaths(originalPath, fileHandler, directoryHandler);
- if (!foundPath.path.isEmpty())
- return handleSuccess(originalPath, foundPath.path, foundPath.matchLength, "in search path");
+ if (!foundPath.paths.isEmpty()) {
+ return handleSuccess(originalPath, foundPath.paths, foundPath.matchLength,
+ "in search path");
+ }
qCDebug(finderLog) << "FileInProjectFinder: checking absolute path in sysroot ...";
// check if absolute path is found in sysroot
if (!m_sysroot.isEmpty()) {
- FileName sysrootPath = m_sysroot;
- sysrootPath.appendPath(originalPath);
- if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, sysrootPath.toString(), origLength, "in sysroot");
+ const FilePath sysrootPath = m_sysroot.pathAppended(originalPath);
+ if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(sysrootPath.toString()), origLength,
+ "in sysroot");
+ }
}
qCDebug(finderLog) << "FileInProjectFinder: couldn't find file!";
@@ -299,10 +333,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPaths(
const QString &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const
{
- for (const FileName &dirPath : m_searchDirectories) {
+ for (const FilePath &dirPath : m_searchDirectories) {
const CacheEntry found = findInSearchPath(dirPath.toString(), filePath,
fileHandler, directoryHandler);
- if (!found.path.isEmpty())
+ if (!found.paths.isEmpty())
return found;
}
@@ -327,17 +361,17 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath(
QString s = filePath;
while (!s.isEmpty()) {
CacheEntry result;
- result.path = searchPath + QLatin1Char('/') + s;
+ result.paths << searchPath + '/' + s;
result.matchLength = s.length() + 1;
- qCDebug(finderLog) << "FileInProjectFinder: trying" << result.path;
+ qCDebug(finderLog) << "FileInProjectFinder: trying" << result.paths.first();
- if (checkPath(result.path, result.matchLength, fileHandler, directoryHandler))
+ if (checkPath(result.paths.first(), result.matchLength, fileHandler, directoryHandler))
return result;
QString next = chopFirstDir(s);
if (next.isEmpty()) {
if (directoryHandler && QFileInfo(searchPath).fileName() == s) {
- result.path = searchPath;
+ result.paths = QStringList{searchPath};
directoryHandler(QDir(searchPath).entryList(), result.matchLength);
return result;
}
@@ -352,7 +386,7 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath(
QStringList FileInProjectFinder::filesWithSameFileName(const QString &fileName) const
{
QStringList result;
- foreach (const FileName &f, m_projectFiles) {
+ foreach (const FilePath &f, m_projectFiles) {
if (f.fileName() == fileName)
result << f.toString();
}
@@ -362,8 +396,8 @@ QStringList FileInProjectFinder::filesWithSameFileName(const QString &fileName)
QStringList FileInProjectFinder::pathSegmentsWithSameName(const QString &pathSegment) const
{
QStringList result;
- for (const FileName &f : m_projectFiles) {
- FileName currentPath = f.parentDir();
+ for (const FilePath &f : m_projectFiles) {
+ FilePath currentPath = f.parentDir();
do {
if (currentPath.fileName() == pathSegment) {
if (result.isEmpty() || result.last() != currentPath.toString())
@@ -386,32 +420,38 @@ int FileInProjectFinder::commonPostFixLength(const QString &candidatePath,
return rank;
}
-QString FileInProjectFinder::bestMatch(const QStringList &filePaths, const QString &filePathToFind)
+QStringList FileInProjectFinder::bestMatches(const QStringList &filePaths,
+ const QString &filePathToFind)
{
if (filePaths.isEmpty())
- return QString();
+ return {};
if (filePaths.length() == 1) {
qCDebug(finderLog) << "FileInProjectFinder: found" << filePaths.first()
<< "in project files";
- return filePaths.first();
+ return filePaths;
}
- auto it = std::max_element(filePaths.constBegin(), filePaths.constEnd(),
- [&filePathToFind] (const QString &a, const QString &b) -> bool {
- return commonPostFixLength(a, filePathToFind) < commonPostFixLength(b, filePathToFind);
- });
- if (it != filePaths.cend()) {
- qCDebug(finderLog) << "FileInProjectFinder: found best match" << *it << "in project files";
- return *it;
+ int bestRank = -1;
+ QStringList bestFilePaths;
+ for (const QString &fp : filePaths) {
+ const int currentRank = commonPostFixLength(fp, filePathToFind);
+ if (currentRank < bestRank)
+ continue;
+ if (currentRank > bestRank) {
+ bestRank = currentRank;
+ bestFilePaths.clear();
+ }
+ bestFilePaths << fp;
}
- return QString();
+ QTC_CHECK(!bestFilePaths.empty());
+ return bestFilePaths;
}
-FileNameList FileInProjectFinder::searchDirectories() const
+FilePathList FileInProjectFinder::searchDirectories() const
{
return m_searchDirectories;
}
-void FileInProjectFinder::setAdditionalSearchDirectories(const FileNameList &searchDirectories)
+void FileInProjectFinder::setAdditionalSearchDirectories(const FilePathList &searchDirectories)
{
m_searchDirectories = searchDirectories;
}
@@ -421,4 +461,43 @@ FileInProjectFinder::PathMappingNode::~PathMappingNode()
qDeleteAll(children);
}
+FilePathList FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const
+{
+ const auto fileIt = m_fileCache.constFind(fileUrl);
+ if (fileIt != m_fileCache.cend())
+ return fileIt.value();
+ QStringList hits;
+ for (const FilePath &f : m_allQrcFiles) {
+ QrcParser::Ptr &qrcParser = m_parserCache[f];
+ if (!qrcParser)
+ qrcParser = QrcParser::parseQrcFile(f.toString(), QString());
+ if (!qrcParser->isValid())
+ continue;
+ qrcParser->collectFilesAtPath(QrcParser::normalizedQrcFilePath(fileUrl.toString()), &hits);
+ }
+ hits.removeDuplicates();
+ const FilePathList result = transform(hits, &FilePath::fromString);
+ m_fileCache.insert(fileUrl, result);
+ return result;
+}
+
+void FileInProjectFinder::QrcUrlFinder::setProjectFiles(const FilePathList &projectFiles)
+{
+ m_allQrcFiles = filtered(projectFiles, [](const FilePath &f) { return f.endsWith(".qrc"); });
+ m_fileCache.clear();
+ m_parserCache.clear();
+}
+
+FilePath chooseFileFromList(const FilePathList &candidates)
+{
+ if (candidates.length() == 1)
+ return candidates.first();
+ QMenu filesMenu;
+ for (const FilePath &candidate : candidates)
+ filesMenu.addAction(candidate.toUserOutput());
+ if (const QAction * const action = filesMenu.exec(QCursor::pos()))
+ return FilePath::fromUserInput(action->text());
+ return FilePath();
+}
+
} // namespace Utils
diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h
index 43a954ff93..66b5317235 100644
--- a/src/libs/utils/fileinprojectfinder.h
+++ b/src/libs/utils/fileinprojectfinder.h
@@ -29,11 +29,13 @@
#include <utils/fileutils.h>
#include <QHash>
+#include <QSharedPointer>
#include <QStringList>
QT_FORWARD_DECLARE_CLASS(QUrl)
namespace Utils {
+class QrcParser;
class QTCREATOR_UTILS_EXPORT FileInProjectFinder
{
@@ -45,34 +47,44 @@ public:
FileInProjectFinder();
~FileInProjectFinder();
- void setProjectDirectory(const FileName &absoluteProjectPath);
- FileName projectDirectory() const;
+ void setProjectDirectory(const FilePath &absoluteProjectPath);
+ FilePath projectDirectory() const;
- void setProjectFiles(const FileNameList &projectFiles);
- void setSysroot(const FileName &sysroot);
+ void setProjectFiles(const FilePathList &projectFiles);
+ void setSysroot(const FilePath &sysroot);
- void addMappedPath(const FileName &localFilePath, const QString &remoteFilePath);
+ void addMappedPath(const FilePath &localFilePath, const QString &remoteFilePath);
- QString findFile(const QUrl &fileUrl, bool *success = nullptr) const;
+ FilePathList findFile(const QUrl &fileUrl, bool *success = nullptr) const;
bool findFileOrDirectory(const QString &originalPath, FileHandler fileHandler = nullptr,
DirectoryHandler directoryHandler = nullptr) const;
- FileNameList searchDirectories() const;
- void setAdditionalSearchDirectories(const FileNameList &searchDirectories);
+ FilePathList searchDirectories() const;
+ void setAdditionalSearchDirectories(const FilePathList &searchDirectories);
private:
struct PathMappingNode
{
~PathMappingNode();
- FileName localPath;
+ FilePath localPath;
QHash<QString, PathMappingNode *> children;
};
struct CacheEntry {
- QString path;
+ QStringList paths;
int matchLength = 0;
};
+ class QrcUrlFinder {
+ public:
+ FilePathList find(const QUrl &fileUrl) const;
+ void setProjectFiles(const FilePathList &projectFiles);
+ private:
+ FilePathList m_allQrcFiles;
+ mutable QHash<QUrl, FilePathList> m_fileCache;
+ mutable QHash<FilePath, QSharedPointer<QrcParser>> m_parserCache;
+ };
+
CacheEntry findInSearchPaths(const QString &filePath, FileHandler fileHandler,
DirectoryHandler directoryHandler) const;
static CacheEntry findInSearchPath(const QString &searchPath, const QString &filePath,
@@ -80,19 +92,22 @@ private:
QStringList filesWithSameFileName(const QString &fileName) const;
QStringList pathSegmentsWithSameName(const QString &path) const;
- bool handleSuccess(const QString &originalPath, const QString &found, int confidence,
+ bool handleSuccess(const QString &originalPath, const QStringList &found, int confidence,
const char *where) const;
static int commonPostFixLength(const QString &candidatePath, const QString &filePathToFind);
- static QString bestMatch(const QStringList &filePaths, const QString &filePathToFind);
+ static QStringList bestMatches(const QStringList &filePaths, const QString &filePathToFind);
- FileName m_projectDir;
- FileName m_sysroot;
- FileNameList m_projectFiles;
- FileNameList m_searchDirectories;
+ FilePath m_projectDir;
+ FilePath m_sysroot;
+ FilePathList m_projectFiles;
+ FilePathList m_searchDirectories;
PathMappingNode m_pathMapRoot;
mutable QHash<QString, CacheEntry> m_cache;
+ QrcUrlFinder m_qrcUrlFinder;
};
+QTCREATOR_UTILS_EXPORT FilePath chooseFileFromList(const FilePathList &candidates);
+
} // namespace Utils
diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index c34532a1de..0bdf3991c5 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -482,7 +482,7 @@ static bool matches(const QList<QRegExp> &exprList, const QString &filePath)
{
return Utils::anyOf(exprList, [&filePath](QRegExp reg) {
return (reg.exactMatch(filePath)
- || reg.exactMatch(FileName::fromString(filePath).fileName()));
+ || reg.exactMatch(FilePath::fromString(filePath).fileName()));
});
}
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index a476cd8d89..acf9c6190d 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -28,20 +28,27 @@
#include "algorithm.h"
#include "qtcassert.h"
+#include "qtcprocess.h"
#include <QDataStream>
#include <QDir>
#include <QDebug>
#include <QDateTime>
+#include <QOperatingSystemVersion>
#include <QRegExp>
#include <QTimer>
#include <QUrl>
+#include <qplatformdefs.h>
#ifdef QT_GUI_LIB
#include <QMessageBox>
#endif
#ifdef Q_OS_WIN
+// We need defines for Windows 8
+#undef _WIN32_WINNT
+#define _WIN32_WINNT _WIN32_WINNT_WIN8
+
#include <qt_windows.h>
#include <shlobj.h>
#endif
@@ -51,7 +58,7 @@
#endif
QT_BEGIN_NAMESPACE
-QDebug operator<<(QDebug dbg, const Utils::FileName &c)
+QDebug operator<<(QDebug dbg, const Utils::FilePath &c)
{
return dbg << c.toString();
}
@@ -60,6 +67,34 @@ QT_END_NAMESPACE
namespace Utils {
+/*! \class Utils::CommandLine
+
+ \brief The CommandLine class represents a command line of a QProcess
+ or similar utility.
+
+*/
+
+void CommandLine::addArg(const QString &arg, OsType osType)
+{
+ QtcProcess::addArg(&m_arguments, arg, osType);
+}
+
+void CommandLine::addArgs(const QStringList &inArgs, OsType osType)
+{
+ for (const QString &arg : inArgs)
+ addArg(arg, osType);
+}
+
+void CommandLine::addArgs(const QString &inArgs)
+{
+ QtcProcess::addArgs(&m_arguments, inArgs);
+}
+
+QString CommandLine::toUserOutput() const
+{
+ return m_executable.toUserOutput() + ' ' + m_arguments;
+}
+
/*! \class Utils::FileUtils
\brief The FileUtils class contains file and directory related convenience
@@ -74,7 +109,7 @@ namespace Utils {
Returns whether the operation succeeded.
*/
-bool FileUtils::removeRecursively(const FileName &filePath, QString *error)
+bool FileUtils::removeRecursively(const FilePath &filePath, QString *error)
{
QFileInfo fileInfo = filePath.toFileInfo();
if (!fileInfo.exists() && !fileInfo.isSymLink())
@@ -101,7 +136,7 @@ bool FileUtils::removeRecursively(const FileName &filePath, QString *error)
QStringList fileNames = dir.entryList(QDir::Files | QDir::Hidden
| QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
foreach (const QString &fileName, fileNames) {
- if (!removeRecursively(FileName(filePath).appendPath(fileName), error))
+ if (!removeRecursively(filePath.pathAppended(fileName), error))
return false;
}
if (!QDir::root().rmdir(dir.path())) {
@@ -140,7 +175,7 @@ bool FileUtils::removeRecursively(const FileName &filePath, QString *error)
Returns whether the operation succeeded.
*/
-bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgtFilePath,
+bool FileUtils::copyRecursively(const FilePath &srcFilePath, const FilePath &tgtFilePath,
QString *error, const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper)
{
QFileInfo srcFileInfo = srcFilePath.toFileInfo();
@@ -160,10 +195,8 @@ bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgt
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot
| QDir::Hidden | QDir::System);
foreach (const QString &fileName, fileNames) {
- FileName newSrcFilePath = srcFilePath;
- newSrcFilePath.appendPath(fileName);
- FileName newTgtFilePath = tgtFilePath;
- newTgtFilePath.appendPath(fileName);
+ const FilePath newSrcFilePath = srcFilePath.pathAppended(fileName);
+ const FilePath newTgtFilePath = tgtFilePath.pathAppended(fileName);
if (!copyRecursively(newSrcFilePath, newTgtFilePath, error, copyHelper))
return false;
}
@@ -185,23 +218,23 @@ bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgt
}
/*!
- If \a filePath is a directory, the function will recursively check all files and return
- true if one of them is newer than \a timeStamp. If \a filePath is a single file, true will
+ If this is a directory, the function will recursively check all files and return
+ true if one of them is newer than \a timeStamp. If this is a single file, true will
be returned if the file is newer than \a timeStamp.
Returns whether at least one file in \a filePath has a newer date than
\a timeStamp.
*/
-bool FileUtils::isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp)
+bool FilePath::isNewerThan(const QDateTime &timeStamp) const
{
- QFileInfo fileInfo = filePath.toFileInfo();
+ const QFileInfo fileInfo = toFileInfo();
if (!fileInfo.exists() || fileInfo.lastModified() >= timeStamp)
return true;
if (fileInfo.isDir()) {
- const QStringList dirContents = QDir(filePath.toString())
+ const QStringList dirContents = QDir(toString())
.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- foreach (const QString &curFileName, dirContents) {
- if (isFileNewerThan(FileName(filePath).appendPath(curFileName), timeStamp))
+ for (const QString &curFileName : dirContents) {
+ if (pathAppended(curFileName).isNewerThan(timeStamp))
return true;
}
}
@@ -218,30 +251,30 @@ bool FileUtils::isFileNewerThan(const FileName &filePath, const QDateTime &timeS
Returns the symlink target file path.
*/
-FileName FileUtils::resolveSymlinks(const FileName &path)
+FilePath FileUtils::resolveSymlinks(const FilePath &path)
{
QFileInfo f = path.toFileInfo();
int links = 16;
while (links-- && f.isSymLink())
f.setFile(f.dir(), f.symLinkTarget());
if (links <= 0)
- return FileName();
- return FileName::fromString(f.filePath());
+ return FilePath();
+ return FilePath::fromString(f.filePath());
}
/*!
- Recursively resolves possibly present symlinks in \a filePath.
+ Recursively resolves possibly present symlinks in this file name.
Unlike QFileInfo::canonicalFilePath(), this function will not return an empty
string if path doesn't exist.
Returns the canonical path.
*/
-FileName FileUtils::canonicalPath(const FileName &path)
+FilePath FilePath::canonicalPath() const
{
- const QString result = path.toFileInfo().canonicalFilePath();
+ const QString result = toFileInfo().canonicalFilePath();
if (result.isEmpty())
- return path;
- return FileName::fromString(result);
+ return *this;
+ return FilePath::fromString(result);
}
/*!
@@ -250,16 +283,16 @@ FileName FileUtils::canonicalPath(const FileName &path)
Returns the possibly shortened path with native separators.
*/
-QString FileUtils::shortNativePath(const FileName &path)
+QString FilePath::shortNativePath() const
{
if (HostOsInfo::isAnyUnixHost()) {
- const FileName home = FileName::fromString(QDir::cleanPath(QDir::homePath()));
- if (path.isChildOf(home)) {
+ const FilePath home = FilePath::fromString(QDir::cleanPath(QDir::homePath()));
+ if (isChildOf(home)) {
return QLatin1Char('~') + QDir::separator()
- + QDir::toNativeSeparators(path.relativeChildPath(home).toString());
+ + QDir::toNativeSeparators(relativeChildPath(home).toString());
}
}
- return path.toUserOutput();
+ return toUserOutput();
}
QString FileUtils::fileSystemFriendlyName(const QString &name)
@@ -293,10 +326,10 @@ QString FileUtils::qmakeFriendlyName(const QString &name)
return fileSystemFriendlyName(result);
}
-bool FileUtils::makeWritable(const FileName &path)
+bool FileUtils::makeWritable(const FilePath &path)
{
- const QString fileName = path.toString();
- return QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
+ const QString filePath = path.toString();
+ return QFile::setPermissions(filePath, QFile::permissions(filePath) | QFile::WriteUser);
}
// makes sure that capitalization of directories is canonical on Windows and OS X.
@@ -347,12 +380,80 @@ QString FileUtils::resolvePath(const QString &baseDir, const QString &fileName)
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
}
-FileName FileUtils::commonPath(const FileName &oldCommonPath, const FileName &fileName)
+FilePath FileUtils::commonPath(const FilePath &oldCommonPath, const FilePath &filePath)
{
- FileName newCommonPath = oldCommonPath;
- while (!newCommonPath.isEmpty() && !fileName.isChildOf(newCommonPath))
+ FilePath newCommonPath = oldCommonPath;
+ while (!newCommonPath.isEmpty() && !filePath.isChildOf(newCommonPath))
newCommonPath = newCommonPath.parentDir();
- return canonicalPath(newCommonPath);
+ return newCommonPath.canonicalPath();
+}
+
+// Copied from qfilesystemengine_win.cpp
+#ifdef Q_OS_WIN
+
+// File ID for Windows up to version 7.
+static inline QByteArray fileIdWin7(HANDLE handle)
+{
+ BY_HANDLE_FILE_INFORMATION info;
+ if (GetFileInformationByHandle(handle, &info)) {
+ char buffer[sizeof "01234567:0123456701234567\0"];
+ qsnprintf(buffer, sizeof(buffer), "%lx:%08lx%08lx",
+ info.dwVolumeSerialNumber,
+ info.nFileIndexHigh,
+ info.nFileIndexLow);
+ return QByteArray(buffer);
+ }
+ return QByteArray();
+}
+
+// File ID for Windows starting from version 8.
+static QByteArray fileIdWin8(HANDLE handle)
+{
+ QByteArray result;
+ FILE_ID_INFO infoEx;
+ if (GetFileInformationByHandleEx(handle,
+ static_cast<FILE_INFO_BY_HANDLE_CLASS>(18), // FileIdInfo in Windows 8
+ &infoEx, sizeof(FILE_ID_INFO))) {
+ result = QByteArray::number(infoEx.VolumeSerialNumber, 16);
+ result += ':';
+ // Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one.
+ result += QByteArray(reinterpret_cast<const char *>(&infoEx.FileId), int(sizeof(infoEx.FileId))).toHex();
+ }
+ return result;
+}
+
+static QByteArray fileIdWin(HANDLE fHandle)
+{
+ return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ?
+ fileIdWin8(HANDLE(fHandle)) : fileIdWin7(HANDLE(fHandle));
+}
+#endif
+
+QByteArray FileUtils::fileId(const FilePath &fileName)
+{
+ QByteArray result;
+
+#ifdef Q_OS_WIN
+ const HANDLE handle =
+ CreateFile((wchar_t*)fileName.toUserOutput().utf16(), 0,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (handle != INVALID_HANDLE_VALUE) {
+ result = fileIdWin(handle);
+ CloseHandle(handle);
+ }
+#else // Copied from qfilesystemengine_unix.cpp
+ if (Q_UNLIKELY(fileName.isEmpty()))
+ return result;
+
+ QT_STATBUF statResult;
+ if (QT_STAT(fileName.toString().toLocal8Bit().constData(), &statResult))
+ return result;
+ result = QByteArray::number(quint64(statResult.st_dev), 16);
+ result += ':';
+ result += QByteArray::number(quint64(statResult.st_ino));
+#endif
+ return result;
}
QByteArray FileReader::fetchQrc(const QString &fileName)
@@ -553,114 +654,131 @@ TempFileSaver::~TempFileSaver()
QFile::remove(m_fileName);
}
-/*! \class Utils::FileName
+/*! \class Utils::FilePath
- \brief The FileName class is a light-weight convenience class for filenames.
+ \brief The FilePath class is a light-weight convenience class for filenames.
On windows filenames are compared case insensitively.
*/
-FileName::FileName()
- : QString()
+FilePath::FilePath()
{
-
}
-/// Constructs a FileName from \a info
-FileName::FileName(const QFileInfo &info)
- : QString(info.absoluteFilePath())
+/// Constructs a FilePath from \a info
+FilePath FilePath::fromFileInfo(const QFileInfo &info)
{
+ return FilePath::fromString(info.absoluteFilePath());
}
/// \returns a QFileInfo
-QFileInfo FileName::toFileInfo() const
+QFileInfo FilePath::toFileInfo() const
{
- return QFileInfo(*this);
+ return QFileInfo(m_data);
+}
+
+FilePath FilePath::fromUrl(const QUrl &url)
+{
+ FilePath fn;
+ fn.m_url = url;
+ fn.m_data = url.path();
+ return fn;
}
/// \returns a QString for passing on to QString based APIs
-const QString &FileName::toString() const
+const QString &FilePath::toString() const
+{
+ return m_data;
+}
+
+QUrl FilePath::toUrl() const
{
- return *this;
+ return m_url;
}
/// \returns a QString to display to the user
/// Converts the separators to the native format
-QString FileName::toUserOutput() const
+QString FilePath::toUserOutput() const
{
- return QDir::toNativeSeparators(toString());
+ if (m_url.isEmpty())
+ return QDir::toNativeSeparators(toString());
+ return m_url.toString();
}
-QString FileName::fileName(int pathComponents) const
+QString FilePath::fileName(int pathComponents) const
{
if (pathComponents < 0)
- return *this;
+ return m_data;
const QChar slash = QLatin1Char('/');
- int i = lastIndexOf(slash);
+ int i = m_data.lastIndexOf(slash);
if (pathComponents == 0 || i == -1)
- return mid(i + 1);
+ return m_data.mid(i + 1);
int component = i + 1;
// skip adjacent slashes
- while (i > 0 && at(--i) == slash);
+ while (i > 0 && m_data.at(--i) == slash)
+ ;
while (i >= 0 && --pathComponents >= 0) {
- i = lastIndexOf(slash, i);
+ i = m_data.lastIndexOf(slash, i);
component = i + 1;
- while (i > 0 && at(--i) == slash);
+ while (i > 0 && m_data.at(--i) == slash)
+ ;
}
// If there are no more slashes before the found one, return the entire string
- if (i > 0 && lastIndexOf(slash, i) != -1)
- return mid(component);
- return *this;
+ if (i > 0 && m_data.lastIndexOf(slash, i) != -1)
+ return m_data.mid(component);
+ return m_data;
}
/// \returns a bool indicating whether a file with this
-/// FileName exists.
-bool FileName::exists() const
+/// FilePath exists.
+bool FilePath::exists() const
{
- return !isEmpty() && QFileInfo::exists(*this);
+ return !isEmpty() && QFileInfo::exists(m_data);
}
/// Find the parent directory of a given directory.
-/// Returns an empty FileName if the current directory is already
+/// Returns an empty FilePath if the current directory is already
/// a root level directory.
-/// \returns \a FileName with the last segment removed.
-FileName FileName::parentDir() const
+/// \returns \a FilePath with the last segment removed.
+FilePath FilePath::parentDir() const
{
const QString basePath = toString();
if (basePath.isEmpty())
- return FileName();
+ return FilePath();
const QDir base(basePath);
if (base.isRoot())
- return FileName();
+ return FilePath();
const QString path = basePath + QLatin1String("/..");
const QString parent = QDir::cleanPath(path);
- QTC_ASSERT(parent != path, return FileName());
+ QTC_ASSERT(parent != path, return FilePath());
- return FileName::fromString(parent);
+ return FilePath::fromString(parent);
}
-/// Constructs a FileName from \a filename
+/// Constructs a FilePath from \a filename
/// \a filename is not checked for validity.
-FileName FileName::fromString(const QString &filename)
+FilePath FilePath::fromString(const QString &filename)
{
- return FileName(filename);
+ FilePath fn;
+ fn.m_data = filename;
+ return fn;
}
-/// Constructs a FileName from \a fileName. The \a defaultExtension is appended
+/// Constructs a FilePath from \a filePath. The \a defaultExtension is appended
/// to \a filename if that does not have an extension already.
-/// \a fileName is not checked for validity.
-FileName FileName::fromString(const QString &filename, const QString &defaultExtension)
+/// \a filePath is not checked for validity.
+FilePath FilePath::fromStringWithExtension(const QString &filepath, const QString &defaultExtension)
{
- if (filename.isEmpty() || defaultExtension.isEmpty())
- return filename;
+ if (filepath.isEmpty() || defaultExtension.isEmpty())
+ return FilePath::fromString(filepath);
- QString rc = filename;
- QFileInfo fi(filename);
+ QString rc = filepath;
+ QFileInfo fi(filepath);
// Add extension unless user specified something else
const QChar dot = QLatin1Char('.');
if (!fi.fileName().contains(dot)) {
@@ -668,138 +786,148 @@ FileName FileName::fromString(const QString &filename, const QString &defaultExt
rc += dot;
rc += defaultExtension;
}
- return rc;
-}
-
-/// Constructs a FileName from \a fileName
-/// \a fileName is not checked for validity.
-FileName FileName::fromLatin1(const QByteArray &filename)
-{
- return FileName(QString::fromLatin1(filename));
+ return FilePath::fromString(rc);
}
-/// Constructs a FileName from \a fileName
-/// \a fileName is only passed through QDir::cleanPath
-FileName FileName::fromUserInput(const QString &filename)
+/// Constructs a FilePath from \a filePath
+/// \a filePath is only passed through QDir::cleanPath
+FilePath FilePath::fromUserInput(const QString &filePath)
{
- QString clean = QDir::cleanPath(filename);
+ QString clean = QDir::cleanPath(filePath);
if (clean.startsWith(QLatin1String("~/")))
clean = QDir::homePath() + clean.mid(1);
- return FileName(clean);
+ return FilePath::fromString(clean);
}
-/// Constructs a FileName from \a fileName, which is encoded as UTF-8.
-/// \a fileName is not checked for validity.
-FileName FileName::fromUtf8(const char *filename, int filenameSize)
+/// Constructs a FilePath from \a filePath, which is encoded as UTF-8.
+/// \a filePath is not checked for validity.
+FilePath FilePath::fromUtf8(const char *filename, int filenameSize)
{
- return FileName(QString::fromUtf8(filename, filenameSize));
+ return FilePath::fromString(QString::fromUtf8(filename, filenameSize));
}
-FileName::FileName(const QString &string)
- : QString(string)
+FilePath FilePath::fromVariant(const QVariant &variant)
{
+ if (variant.type() == QVariant::Url)
+ return FilePath::fromUrl(variant.toUrl());
+ return FilePath::fromString(variant.toString());
+}
+QVariant FilePath::toVariant() const
+{
+ if (!m_url.isEmpty())
+ return m_url;
+ return m_data;
}
-bool FileName::operator==(const FileName &other) const
+bool FilePath::operator==(const FilePath &other) const
{
- return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) == 0;
+ if (!m_url.isEmpty())
+ return m_url == other.m_url;
+ return QString::compare(m_data, other.m_data, HostOsInfo::fileNameCaseSensitivity()) == 0;
}
-bool FileName::operator!=(const FileName &other) const
+bool FilePath::operator!=(const FilePath &other) const
{
return !(*this == other);
}
-bool FileName::operator<(const FileName &other) const
+bool FilePath::operator<(const FilePath &other) const
{
- return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) < 0;
+ if (!m_url.isEmpty())
+ return m_url < other.m_url;
+ return QString::compare(m_data, other.m_data, HostOsInfo::fileNameCaseSensitivity()) < 0;
}
-bool FileName::operator<=(const FileName &other) const
+bool FilePath::operator<=(const FilePath &other) const
{
- return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) <= 0;
+ return !(other < *this);
}
-bool FileName::operator>(const FileName &other) const
+bool FilePath::operator>(const FilePath &other) const
{
return other < *this;
}
-bool FileName::operator>=(const FileName &other) const
+bool FilePath::operator>=(const FilePath &other) const
{
- return other <= *this;
+ return !(*this < other);
}
-FileName FileName::operator+(const QString &s) const
+FilePath FilePath::operator+(const QString &s) const
{
- FileName result(*this);
- result.appendString(s);
- return result;
+ return FilePath::fromString(m_data + s);
}
-/// \returns whether FileName is a child of \a s
-bool FileName::isChildOf(const FileName &s) const
+/// \returns whether FilePath is a child of \a s
+bool FilePath::isChildOf(const FilePath &s) const
{
if (s.isEmpty())
return false;
- if (!QString::startsWith(s, HostOsInfo::fileNameCaseSensitivity()))
+ if (!m_data.startsWith(s.m_data, HostOsInfo::fileNameCaseSensitivity()))
return false;
- if (size() <= s.size())
+ if (m_data.size() <= s.m_data.size())
return false;
// s is root, '/' was already tested in startsWith
- if (s.QString::endsWith(QLatin1Char('/')))
+ if (s.m_data.endsWith(QLatin1Char('/')))
return true;
// s is a directory, next character should be '/' (/tmpdir is NOT a child of /tmp)
- return at(s.size()) == QLatin1Char('/');
+ return m_data.at(s.m_data.size()) == QLatin1Char('/');
}
/// \overload
-bool FileName::isChildOf(const QDir &dir) const
+bool FilePath::isChildOf(const QDir &dir) const
{
- return isChildOf(FileName::fromString(dir.absolutePath()));
+ return isChildOf(FilePath::fromString(dir.absolutePath()));
}
-/// \returns whether FileName endsWith \a s
-bool FileName::endsWith(const QString &s) const
+/// \returns whether FilePath endsWith \a s
+bool FilePath::endsWith(const QString &s) const
{
- return QString::endsWith(s, HostOsInfo::fileNameCaseSensitivity());
+ return m_data.endsWith(s, HostOsInfo::fileNameCaseSensitivity());
}
-/// \returns the relativeChildPath of FileName to parent if FileName is a child of parent
-/// \note returns a empty FileName if FileName is not a child of parent
+bool FilePath::isLocal() const
+{
+ return m_url.isEmpty() || m_url.isLocalFile();
+}
+
+/// \returns the relativeChildPath of FilePath to parent if FilePath is a child of parent
+/// \note returns a empty FilePath if FilePath is not a child of parent
/// That is, this never returns a path starting with "../"
-FileName FileName::relativeChildPath(const FileName &parent) const
+FilePath FilePath::relativeChildPath(const FilePath &parent) const
{
if (!isChildOf(parent))
- return FileName();
- return FileName(QString::mid(parent.size() + 1, -1));
+ return FilePath();
+ return FilePath::fromString(m_data.mid(parent.m_data.size() + 1, -1));
}
-/// Appends \a s, ensuring a / between the parts
-FileName &FileName::appendPath(const QString &s)
+FilePath FilePath::pathAppended(const QString &str) const
{
- if (s.isEmpty())
- return *this;
- if (!isEmpty() && !QString::endsWith(QLatin1Char('/')))
- appendString(QLatin1Char('/'));
- appendString(s);
- return *this;
+ FilePath fn = *this;
+ if (str.isEmpty())
+ return fn;
+ if (!isEmpty() && !m_data.endsWith(QLatin1Char('/')))
+ fn.m_data.append('/');
+ fn.m_data.append(str);
+ return fn;
}
-FileName &FileName::appendString(const QString &str)
+FilePath FilePath::stringAppended(const QString &str) const
{
- QString::append(str);
- return *this;
+ FilePath fn = *this;
+ fn.m_data.append(str);
+ return fn;
}
-FileName &FileName::appendString(QChar str)
+uint FilePath::hash(uint seed) const
{
- QString::append(str);
- return *this;
+ if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
+ return qHash(m_data.toUpper(), seed);
+ return qHash(m_data, seed);
}
-QTextStream &operator<<(QTextStream &s, const FileName &fn)
+QTextStream &operator<<(QTextStream &s, const FilePath &fn)
{
return s << fn.toString();
}
@@ -813,14 +941,4 @@ void withNtfsPermissions(const std::function<void()> &task)
qt_ntfs_permission_lookup--;
}
#endif
-
} // namespace Utils
-
-QT_BEGIN_NAMESPACE
-uint qHash(const Utils::FileName &a)
-{
- if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
- return qHash(a.toString().toUpper());
- return qHash(a.toString());
-}
-QT_END_NAMESPACE
diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h
index aa6310c760..ec018b9c3b 100644
--- a/src/libs/utils/fileutils.h
+++ b/src/libs/utils/fileutils.h
@@ -33,11 +33,12 @@
#include <QXmlStreamWriter> // Mac.
#include <QMetaType>
#include <QStringList>
+#include <QUrl>
#include <functional>
#include <memory>
-namespace Utils {class FileName; }
+namespace Utils { class FilePath; }
QT_BEGIN_NAMESPACE
class QDataStream;
@@ -49,7 +50,7 @@ class QTemporaryFile;
class QTextStream;
class QWidget;
-QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FileName &c);
+QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FilePath &c);
// for withNtfsPermissions
#ifdef Q_OS_WIN
@@ -60,76 +61,114 @@ QT_END_NAMESPACE
namespace Utils {
-class QTCREATOR_UTILS_EXPORT FileName : private QString
+class QTCREATOR_UTILS_EXPORT FilePath
{
public:
- FileName();
- explicit FileName(const QFileInfo &info);
- QFileInfo toFileInfo() const;
- static FileName fromString(const QString &filename);
- static FileName fromString(const QString &filename, const QString &defaultExtension);
- static FileName fromLatin1(const QByteArray &filename);
- static FileName fromUserInput(const QString &filename);
- static FileName fromUtf8(const char *filename, int filenameSize = -1);
+ FilePath();
+
+ static FilePath fromString(const QString &filepath);
+ static FilePath fromFileInfo(const QFileInfo &info);
+ static FilePath fromStringWithExtension(const QString &filepath, const QString &defaultExtension);
+ static FilePath fromUserInput(const QString &filepath);
+ static FilePath fromUtf8(const char *filepath, int filepathSize = -1);
+ static FilePath fromVariant(const QVariant &variant);
+
const QString &toString() const;
+ QFileInfo toFileInfo() const;
+ QVariant toVariant() const;
+
QString toUserOutput() const;
+ QString shortNativePath() const;
+
QString fileName(int pathComponents = 0) const;
bool exists() const;
- FileName parentDir() const;
+ FilePath parentDir() const;
- bool operator==(const FileName &other) const;
- bool operator!=(const FileName &other) const;
- bool operator<(const FileName &other) const;
- bool operator<=(const FileName &other) const;
- bool operator>(const FileName &other) const;
- bool operator>=(const FileName &other) const;
- FileName operator+(const QString &s) const;
+ bool operator==(const FilePath &other) const;
+ bool operator!=(const FilePath &other) const;
+ bool operator<(const FilePath &other) const;
+ bool operator<=(const FilePath &other) const;
+ bool operator>(const FilePath &other) const;
+ bool operator>=(const FilePath &other) const;
+ FilePath operator+(const QString &s) const;
- bool isChildOf(const FileName &s) const;
+ bool isChildOf(const FilePath &s) const;
bool isChildOf(const QDir &dir) const;
bool endsWith(const QString &s) const;
+ bool isLocal() const;
+
+ bool isNewerThan(const QDateTime &timeStamp) const;
+
+ FilePath relativeChildPath(const FilePath &parent) const;
+ FilePath pathAppended(const QString &str) const;
+ FilePath stringAppended(const QString &str) const;
+
+ FilePath canonicalPath() const;
+
+ void clear() { m_data.clear(); }
+ bool isEmpty() const { return m_data.isEmpty(); }
+
+ uint hash(uint seed) const;
+
+ // NOTE: FileName operations on FilePath created from URL currenly
+ // do not work except for .toVariant() and .toUrl().
+ static FilePath fromUrl(const QUrl &url);
+ QUrl toUrl() const;
- FileName relativeChildPath(const FileName &parent) const;
- FileName &appendPath(const QString &s);
- FileName &appendString(const QString &str);
- FileName &appendString(QChar str);
-
- using QString::chop;
- using QString::clear;
- using QString::count;
- using QString::isEmpty;
- using QString::isNull;
- using QString::length;
- using QString::size;
private:
- FileName(const QString &string);
+ QString m_data;
+ QUrl m_url;
};
-QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FileName &fn);
+QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FilePath &fn);
+
+using FilePathList = QList<FilePath>;
+
+using FileName = FilePath;
+using FileNameList = FilePathList;
-using FileNameList = QList<FileName>;
+class QTCREATOR_UTILS_EXPORT CommandLine
+{
+public:
+ CommandLine() {}
+
+ CommandLine(const FilePath &executable, const QString &arguments)
+ : m_executable(executable), m_arguments(arguments)
+ {}
+
+ void addArg(const QString &arg, OsType osType = HostOsInfo::hostOs());
+ void addArgs(const QStringList &inArgs, OsType osType = HostOsInfo::hostOs());
+ void addArgs(const QString &inArgs);
+
+ QString toUserOutput() const;
+
+ FilePath executable() const { return m_executable; }
+ QString arguments() const { return m_arguments; }
+
+private:
+ FilePath m_executable;
+ QString m_arguments;
+};
class QTCREATOR_UTILS_EXPORT FileUtils {
public:
- static bool removeRecursively(const FileName &filePath, QString *error = nullptr);
+ static bool removeRecursively(const FilePath &filePath, QString *error = nullptr);
static bool copyRecursively(
- const FileName &srcFilePath, const FileName &tgtFilePath, QString *error = nullptr,
+ const FilePath &srcFilePath, const FilePath &tgtFilePath, QString *error = nullptr,
const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper = nullptr);
- static bool isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp);
- static FileName resolveSymlinks(const FileName &path);
- static FileName canonicalPath(const FileName &path);
- static QString shortNativePath(const FileName &path);
+ static FilePath resolveSymlinks(const FilePath &path);
static QString fileSystemFriendlyName(const QString &name);
static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0);
static QString qmakeFriendlyName(const QString &name);
- static bool makeWritable(const FileName &path);
+ static bool makeWritable(const FilePath &path);
static QString normalizePathName(const QString &name);
static bool isRelativePath(const QString &fileName);
static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
static QString resolvePath(const QString &baseDir, const QString &fileName);
- static FileName commonPath(const FileName &oldCommonPath, const FileName &fileName);
+ static FilePath commonPath(const FilePath &oldCommonPath, const FilePath &fileName);
+ static QByteArray fileId(const FilePath &fileName);
};
// for actually finding out if e.g. directories are writable on Windows
@@ -240,16 +279,14 @@ private:
bool m_autoRemove = true;
};
-} // namespace Utils
+inline uint qHash(const Utils::FilePath &a, uint seed = 0) { return a.hash(seed); }
-QT_BEGIN_NAMESPACE
-QTCREATOR_UTILS_EXPORT uint qHash(const Utils::FileName &a);
-QT_END_NAMESPACE
+} // namespace Utils
namespace std {
-template<> struct hash<Utils::FileName>
+template<> struct hash<Utils::FilePath>
{
- using argument_type = Utils::FileName;
+ using argument_type = Utils::FilePath;
using result_type = size_t;
result_type operator()(const argument_type &fn) const
{
@@ -260,4 +297,4 @@ template<> struct hash<Utils::FileName>
};
} // namespace std
-Q_DECLARE_METATYPE(Utils::FileName)
+Q_DECLARE_METATYPE(Utils::FilePath)
diff --git a/src/libs/utils/genericconstants.h b/src/libs/utils/genericconstants.h
new file mode 100644
index 0000000000..a380fc15ba
--- /dev/null
+++ b/src/libs/utils/genericconstants.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** 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
+
+namespace Utils {
+
+namespace Constants {
+
+const char BEAUTIFIER_SETTINGS_GROUP[] = "Beautifier";
+const char BEAUTIFIER_GENERAL_GROUP[] = "General";
+const char BEAUTIFIER_AUTO_FORMAT_ON_SAVE[] = "autoFormatOnSave";
+
+} // namespace Constants
+} // namespace Utils
diff --git a/src/libs/utils/highlightingitemdelegate.cpp b/src/libs/utils/highlightingitemdelegate.cpp
index e253689843..4874200e86 100644
--- a/src/libs/utils/highlightingitemdelegate.cpp
+++ b/src/libs/utils/highlightingitemdelegate.cpp
@@ -114,7 +114,8 @@ int HighlightingItemDelegate::drawLineNumber(QPainter *painter, const QStyleOpti
const bool isSelected = option.state & QStyle::State_Selected;
const QString lineText = QString::number(lineNumber);
const int minimumLineNumberDigits = qMax(kMinimumLineNumberDigits, lineText.count());
- const int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, '0'));
+ const int fontWidth =
+ painter->fontMetrics().horizontalAdvance(QString(minimumLineNumberDigits, '0'));
const int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth
+ lineNumberAreaHorizontalPadding;
QRect lineNumberAreaRect(rect);
diff --git a/src/libs/utils/images/dir.png b/src/libs/utils/images/dir.png
new file mode 100644
index 0000000000..57cec6bcd3
--- /dev/null
+++ b/src/libs/utils/images/dir.png
Binary files differ
diff --git a/src/libs/utils/images/pinned.png b/src/libs/utils/images/pinned.png
new file mode 100644
index 0000000000..dc96231ca4
--- /dev/null
+++ b/src/libs/utils/images/pinned.png
Binary files differ
diff --git a/src/libs/utils/images/pinned@2x.png b/src/libs/utils/images/pinned@2x.png
new file mode 100644
index 0000000000..d7c59e83ce
--- /dev/null
+++ b/src/libs/utils/images/pinned@2x.png
Binary files differ
diff --git a/src/libs/utils/images/settings.png b/src/libs/utils/images/settings.png
new file mode 100644
index 0000000000..2621923499
--- /dev/null
+++ b/src/libs/utils/images/settings.png
Binary files differ
diff --git a/src/libs/utils/images/settings@2x.png b/src/libs/utils/images/settings@2x.png
new file mode 100644
index 0000000000..456f0cc56b
--- /dev/null
+++ b/src/libs/utils/images/settings@2x.png
Binary files differ
diff --git a/src/libs/utils/images/sort_alphabetically.png b/src/libs/utils/images/sort_alphabetically.png
new file mode 100644
index 0000000000..c15eb56d50
--- /dev/null
+++ b/src/libs/utils/images/sort_alphabetically.png
Binary files differ
diff --git a/src/libs/utils/images/sort_alphabetically@2x.png b/src/libs/utils/images/sort_alphabetically@2x.png
new file mode 100644
index 0000000000..1a2e5d9520
--- /dev/null
+++ b/src/libs/utils/images/sort_alphabetically@2x.png
Binary files differ
diff --git a/src/libs/utils/images/toggleprogressdetails.png b/src/libs/utils/images/toggleprogressdetails.png
new file mode 100644
index 0000000000..b2353cd9d0
--- /dev/null
+++ b/src/libs/utils/images/toggleprogressdetails.png
Binary files differ
diff --git a/src/libs/utils/images/toggleprogressdetails@2x.png b/src/libs/utils/images/toggleprogressdetails@2x.png
new file mode 100644
index 0000000000..28a212491e
--- /dev/null
+++ b/src/libs/utils/images/toggleprogressdetails@2x.png
Binary files differ
diff --git a/src/libs/utils/images/unknownfile.png b/src/libs/utils/images/unknownfile.png
new file mode 100644
index 0000000000..88f77592d1
--- /dev/null
+++ b/src/libs/utils/images/unknownfile.png
Binary files differ
diff --git a/src/libs/utils/listmodel.h b/src/libs/utils/listmodel.h
new file mode 100644
index 0000000000..5f4de811e6
--- /dev/null
+++ b/src/libs/utils/listmodel.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** 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 "utils_global.h"
+#include "treemodel.h"
+
+namespace Utils {
+
+template <class ChildType>
+class BaseListModel : public TreeModel<TypedTreeItem<ChildType>, ChildType>
+{
+public:
+ using BaseModel = TreeModel<TypedTreeItem<ChildType>, ChildType>;
+ using BaseModel::rootItem;
+
+ explicit BaseListModel(QObject *parent = nullptr) : BaseModel(parent) {}
+
+ int itemCount() const { return rootItem()->childCount(); }
+ ChildType *itemAt(int row) const { return rootItem()->childAt(row); }
+
+ void appendItem(ChildType *item) { rootItem()->appendChild(item); }
+
+ template <class Predicate>
+ void forItems(const Predicate &pred) const
+ {
+ rootItem()->forFirstLevelChildren(pred);
+ }
+
+ template <class Predicate>
+ ChildType *findItem(const Predicate &pred) const
+ {
+ return rootItem()->findFirstLevelChild(pred);
+ }
+
+ void sortItems(const std::function<bool(const ChildType *, const ChildType *)> &lessThan)
+ {
+ return rootItem()->sortChildren([lessThan](const TreeItem *a, const TreeItem *b) {
+ return lessThan(static_cast<const ChildType *>(a), static_cast<const ChildType *>(b));
+ });
+ }
+
+ int indexOf(const ChildType *item) const { return rootItem()->indexOf(item); }
+
+ void clear() { rootItem()->removeChildren(); }
+
+ using const_iterator = typename QVector<TreeItem *>::const_iterator;
+ const_iterator begin() const { return rootItem()->begin(); }
+ const_iterator end() const { return rootItem()->end(); }
+
+};
+
+template <class ItemData>
+class ListItem : public TreeItem
+{
+public:
+ ItemData itemData;
+};
+
+template <class ItemData>
+class ListModel : public BaseListModel<ListItem<ItemData>>
+{
+public:
+ using ChildType = ListItem<ItemData>;
+ using BaseModel = BaseListModel<ChildType>;
+
+ explicit ListModel(QObject *parent = nullptr) : BaseModel(parent) {}
+
+ const ItemData &dataAt(int row) const
+ {
+ static const ItemData dummyData = {};
+ auto item = BaseModel::itemAt(row);
+ return item ? item->itemData : dummyData;
+ }
+
+ ChildType *findItemByData(const std::function<bool(const ItemData &)> &pred) const
+ {
+ return BaseModel::rootItem()->findFirstLevelChild([pred](ChildType *child) {
+ return pred(child->itemData);
+ });
+ }
+
+ void destroyItems(const std::function<bool(const ItemData &)> &pred)
+ {
+ QList<ChildType *> toDestroy;
+ BaseModel::rootItem()->forFirstLevelChildren([pred, &toDestroy](ChildType *item) {
+ if (pred(item->itemData))
+ toDestroy.append(item);
+ });
+ for (ChildType *item : toDestroy)
+ this->destroyItem(item);
+ }
+
+ ItemData *findData(const std::function<bool(const ItemData &)> &pred) const
+ {
+ ChildType *item = findItemByData(pred);
+ return item ? &item->itemData : nullptr;
+ }
+
+ void forItems(const std::function<void(ItemData &)> &func) const
+ {
+ BaseModel::rootItem()->forFirstLevelChildren([func](ChildType *child) {
+ func(child->itemData);
+ });
+ }
+
+ ChildType *appendItem(const ItemData &data)
+ {
+ auto item = new ChildType;
+ item->itemData = data;
+ BaseModel::rootItem()->appendChild(item);
+ return item;
+ }
+
+ QVariant data(const QModelIndex &idx, int role) const override
+ {
+ TreeItem *item = BaseModel::itemForIndex(idx);
+ if (item && item->parent() == BaseModel::rootItem())
+ return itemData(static_cast<ChildType *>(item)->itemData, idx.column(), role);
+ return {};
+ }
+
+ Qt::ItemFlags flags(const QModelIndex &idx) const override
+ {
+ TreeItem *item = BaseModel::itemForIndex(idx);
+ if (item && item->parent() == BaseModel::rootItem())
+ return itemFlags(static_cast<ChildType *>(item)->itemData, idx.column());
+ return {};
+ }
+
+ virtual QVariant itemData(const ItemData &idata, int column, int role) const
+ {
+ if (m_dataAccessor)
+ return m_dataAccessor(idata, column, role);
+ return {};
+ }
+
+ virtual Qt::ItemFlags itemFlags(const ItemData &idata, int column) const
+ {
+ if (m_flagsAccessor)
+ return m_flagsAccessor(idata, column);
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ }
+
+ void setDataAccessor(const std::function<QVariant(const ItemData &, int, int)> &accessor)
+ {
+ m_dataAccessor = accessor;
+ }
+
+ void setFlagsAccessor(const std::function<Qt::ItemFlags(const ItemData &, int)> &accessor)
+ {
+ m_flagsAccessor = accessor;
+ }
+
+private:
+ std::function<QVariant(const ItemData &, int, int)> m_dataAccessor;
+ std::function<Qt::ItemFlags(const ItemData &, int)> m_flagsAccessor;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp
index eb3f05e175..a41fbde31d 100644
--- a/src/libs/utils/macroexpander.cpp
+++ b/src/libs/utils/macroexpander.cpp
@@ -290,11 +290,39 @@ QString MacroExpander::expand(const QString &stringWithVariables) const
return res;
}
+FilePath MacroExpander::expand(const FilePath &fileNameWithVariables) const
+{
+ return FilePath::fromString(expand(fileNameWithVariables.toString()));
+}
+
QByteArray MacroExpander::expand(const QByteArray &stringWithVariables) const
{
return expand(QString::fromLatin1(stringWithVariables)).toLatin1();
}
+QVariant MacroExpander::expandVariant(const QVariant &v) const
+{
+ const auto type = QMetaType::Type(v.type());
+ if (type == QMetaType::QString) {
+ return expand(v.toString());
+ } else if (type == QMetaType::QStringList) {
+ return Utils::transform(v.toStringList(),
+ [this](const QString &s) -> QVariant { return expand(s); });
+ } else if (type == QMetaType::QVariantList) {
+ return Utils::transform(v.toList(), [this](const QVariant &v) { return expandVariant(v); });
+ } else if (type == QMetaType::QVariantMap) {
+ const auto map = v.toMap();
+ QVariantMap result;
+ QMapIterator<QString, QVariant> it(map);
+ while (it.hasNext()) {
+ it.next();
+ result.insert(it.key(), expandVariant(it.value()));
+ }
+ return result;
+ }
+ return v;
+}
+
QString MacroExpander::expandProcessArgs(const QString &argsWithVariables) const
{
return QtcProcess::expandMacros(argsWithVariables, d);
@@ -394,7 +422,7 @@ void MacroExpander::registerFileVariables(const QByteArray &prefix,
registerVariable(prefix + kFileNamePostfix,
tr("%1: File name without path.").arg(heading),
- [base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : FileName::fromString(tmp).fileName(); },
+ [base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : FilePath::fromString(tmp).fileName(); },
visibleInChooser);
registerVariable(prefix + kFileBaseNamePostfix,
diff --git a/src/libs/utils/macroexpander.h b/src/libs/utils/macroexpander.h
index f17ae86b8c..70448069c5 100644
--- a/src/libs/utils/macroexpander.h
+++ b/src/libs/utils/macroexpander.h
@@ -37,6 +37,7 @@ namespace Utils {
namespace Internal { class MacroExpanderPrivate; }
+class FilePath;
class MacroExpander;
using MacroExpanderProvider = std::function<MacroExpander *()>;
using MacroExpanderProviders = QVector<MacroExpanderProvider>;
@@ -55,7 +56,9 @@ public:
QString value(const QByteArray &variable, bool *found = nullptr) const;
QString expand(const QString &stringWithVariables) const;
+ FilePath expand(const FilePath &fileNameWithVariables) const;
QByteArray expand(const QByteArray &stringWithVariables) const;
+ QVariant expandVariant(const QVariant &v) const;
QString expandProcessArgs(const QString &argsWithVariables) const;
diff --git a/src/libs/utils/mimetypes/mimeprovider.cpp b/src/libs/utils/mimetypes/mimeprovider.cpp
index d444aa899c..46d3eb71bd 100644
--- a/src/libs/utils/mimetypes/mimeprovider.cpp
+++ b/src/libs/utils/mimetypes/mimeprovider.cpp
@@ -803,11 +803,7 @@ void MimeXMLProvider::ensureLoaded()
// if (!fdoXmlFound) {
// // We could instead install the file as part of installing Qt?
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
const char freedesktopOrgXml[] = ":/qt-project.org/qmime/packages/freedesktop.org.xml";
-#else
- const char freedesktopOrgXml[] = ":/qt-project.org/qmime/freedesktop.org.xml";
-#endif
allFiles.prepend(QLatin1String(freedesktopOrgXml));
// }
diff --git a/src/libs/utils/newclasswidget.cpp b/src/libs/utils/newclasswidget.cpp
index 8700b8204c..9205d435dc 100644
--- a/src/libs/utils/newclasswidget.cpp
+++ b/src/libs/utils/newclasswidget.cpp
@@ -88,7 +88,7 @@ NewClassWidget::NewClassWidget(QWidget *parent) :
connect(d->m_ui.classLineEdit, &QLineEdit::textEdited,
this, &NewClassWidget::classNameEdited);
connect(d->m_ui.baseClassComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &NewClassWidget::suggestClassNameFromBase);
connect(d->m_ui.baseClassComboBox, &QComboBox::editTextChanged,
this, &NewClassWidget::slotValidChanged);
diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp
index ec85a748a6..7926422da6 100644
--- a/src/libs/utils/outputformatter.cpp
+++ b/src/libs/utils/outputformatter.cpp
@@ -78,7 +78,8 @@ void OutputFormatter::appendMessage(const QString &text, OutputFormat format)
void OutputFormatter::appendMessage(const QString &text, const QTextCharFormat &format)
{
- foreach (const FormattedText &output, parseAnsi(text, format))
+ const QList<FormattedText> formattedTextList = parseAnsi(text, format);
+ for (const FormattedText &output : formattedTextList)
append(output.text, output.format);
}
diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h
index c516ca14e2..1db42453d5 100644
--- a/src/libs/utils/outputformatter.h
+++ b/src/libs/utils/outputformatter.h
@@ -62,6 +62,9 @@ public:
virtual void clear() {}
void setBoldFontEnabled(bool enabled);
+signals:
+ void contentChanged();
+
protected:
void initFormats();
virtual void clearLastLine();
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index e29b0c7663..f08391d6a6 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -193,14 +193,14 @@ QString PathChooserPrivate::expandedPath(const QString &input) const
if (m_macroExpander)
expandedInput = m_macroExpander->expand(expandedInput);
- const QString path = FileName::fromUserInput(expandedInput).toString();
+ const QString path = FilePath::fromUserInput(expandedInput).toString();
if (path.isEmpty())
return path;
switch (m_acceptingKind) {
case PathChooser::Command:
case PathChooser::ExistingCommand: {
- const FileName expanded = m_environment.searchInPath(path, {FileName::fromString(m_baseDirectory)});
+ const FilePath expanded = m_environment.searchInPath(path, {FilePath::fromString(m_baseDirectory)});
return expanded.isEmpty() ? path : expanded.toString();
}
case PathChooser::Any:
@@ -293,12 +293,12 @@ void PathChooser::setBaseDirectory(const QString &directory)
triggerChanged();
}
-FileName PathChooser::baseFileName() const
+FilePath PathChooser::baseFileName() const
{
- return FileName::fromString(d->m_baseDirectory);
+ return FilePath::fromString(d->m_baseDirectory);
}
-void PathChooser::setBaseFileName(const FileName &base)
+void PathChooser::setBaseFileName(const FilePath &base)
{
setBaseDirectory(base.toString());
}
@@ -323,14 +323,14 @@ QString PathChooser::path() const
return fileName().toString();
}
-FileName PathChooser::rawFileName() const
+FilePath PathChooser::rawFileName() const
{
- return FileName::fromString(QDir::fromNativeSeparators(d->m_lineEdit->text()));
+ return FilePath::fromString(QDir::fromNativeSeparators(d->m_lineEdit->text()));
}
-FileName PathChooser::fileName() const
+FilePath PathChooser::fileName() const
{
- return FileName::fromUserInput(d->expandedPath(rawFileName().toString()));
+ return FilePath::fromUserInput(d->expandedPath(rawFileName().toString()));
}
// FIXME: try to remove again
@@ -352,7 +352,7 @@ void PathChooser::setPath(const QString &path)
d->m_lineEdit->setTextKeepingActiveCursor(QDir::toNativeSeparators(path));
}
-void PathChooser::setFileName(const FileName &fn)
+void PathChooser::setFileName(const FilePath &fn)
{
d->m_lineEdit->setTextKeepingActiveCursor(fn.toUserOutput());
}
diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h
index 73939e1bf4..09d98e71c8 100644
--- a/src/libs/utils/pathchooser.h
+++ b/src/libs/utils/pathchooser.h
@@ -55,8 +55,8 @@ class QTCREATOR_UTILS_EXPORT PathChooser : public QWidget
Q_PROPERTY(QStringList commandVersionArguments READ commandVersionArguments WRITE setCommandVersionArguments)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly DESIGNABLE true)
// Designer does not know this type, so force designable to false:
- Q_PROPERTY(Utils::FileName fileName READ fileName WRITE setFileName DESIGNABLE false)
- Q_PROPERTY(Utils::FileName baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false)
+ Q_PROPERTY(Utils::FilePath fileName READ fileName WRITE setFileName DESIGNABLE false)
+ Q_PROPERTY(Utils::FilePath baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false)
Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor DESIGNABLE true)
Q_PROPERTY(QColor okColor READ okColor WRITE setOkColor DESIGNABLE true)
@@ -93,8 +93,8 @@ public:
QString path() const;
QString rawPath() const; // The raw unexpanded input.
- FileName rawFileName() const; // The raw unexpanded input.
- FileName fileName() const;
+ FilePath rawFileName() const; // The raw unexpanded input.
+ FilePath fileName() const;
static QString expandedDirectory(const QString &input, const Environment &env,
const QString &baseDir);
@@ -102,8 +102,8 @@ public:
QString baseDirectory() const;
void setBaseDirectory(const QString &directory);
- FileName baseFileName() const;
- void setBaseFileName(const FileName &base);
+ FilePath baseFileName() const;
+ void setBaseFileName(const FilePath &base);
void setEnvironment(const Environment &env);
@@ -172,7 +172,7 @@ signals:
public slots:
void setPath(const QString &);
- void setFileName(const FileName &);
+ void setFileName(const FilePath &);
void setErrorColor(const QColor &errorColor);
void setOkColor(const QColor &okColor);
diff --git a/src/libs/utils/persistentsettings.cpp b/src/libs/utils/persistentsettings.cpp
index db0f8d0db5..92d32109ea 100644
--- a/src/libs/utils/persistentsettings.cpp
+++ b/src/libs/utils/persistentsettings.cpp
@@ -341,7 +341,7 @@ QVariantMap PersistentSettingsReader::restoreValues() const
return m_valueMap;
}
-bool PersistentSettingsReader::load(const FileName &fileName)
+bool PersistentSettingsReader::load(const FilePath &fileName)
{
m_valueMap.clear();
@@ -409,7 +409,7 @@ static void writeVariantValue(QXmlStreamWriter &w, const Context &ctx,
}
}
-PersistentSettingsWriter::PersistentSettingsWriter(const FileName &fileName, const QString &docType) :
+PersistentSettingsWriter::PersistentSettingsWriter(const FilePath &fileName, const QString &docType) :
m_fileName(fileName), m_docType(docType)
{ }
@@ -438,7 +438,7 @@ bool PersistentSettingsWriter::save(const QVariantMap &data, QWidget *parent) co
}
#endif // QT_GUI_LIB
-FileName PersistentSettingsWriter::fileName() const
+FilePath PersistentSettingsWriter::fileName() const
{ return m_fileName; }
//** * @brief Set contents of file (e.g. from data read from it). */
diff --git a/src/libs/utils/persistentsettings.h b/src/libs/utils/persistentsettings.h
index a7255dcb8a..92dbf0d8c9 100644
--- a/src/libs/utils/persistentsettings.h
+++ b/src/libs/utils/persistentsettings.h
@@ -42,7 +42,7 @@ public:
PersistentSettingsReader();
QVariant restoreValue(const QString &variable, const QVariant &defaultValue = QVariant()) const;
QVariantMap restoreValues() const;
- bool load(const FileName &fileName);
+ bool load(const FilePath &fileName);
private:
QMap<QString, QVariant> m_valueMap;
@@ -51,7 +51,7 @@ private:
class QTCREATOR_UTILS_EXPORT PersistentSettingsWriter
{
public:
- PersistentSettingsWriter(const FileName &fileName, const QString &docType);
+ PersistentSettingsWriter(const FilePath &fileName, const QString &docType);
~PersistentSettingsWriter();
bool save(const QVariantMap &data, QString *errorString) const;
@@ -59,14 +59,14 @@ public:
bool save(const QVariantMap &data, QWidget *parent) const;
#endif
- FileName fileName() const;
+ FilePath fileName() const;
void setContents(const QVariantMap &data);
private:
bool write(const QVariantMap &data, QString *errorString) const;
- const FileName m_fileName;
+ const FilePath m_fileName;
const QString m_docType;
mutable QMap<QString, QVariant> m_savedData;
};
diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp
index a449fe1285..56127ac479 100644
--- a/src/libs/utils/projectintropage.cpp
+++ b/src/libs/utils/projectintropage.cpp
@@ -101,7 +101,7 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) :
connect(d->m_ui.nameLineEdit, &FancyLineEdit::validReturnPressed,
this, &ProjectIntroPage::slotActivated);
connect(d->m_ui.projectComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ProjectIntroPage::slotChanged);
setProperty(SHORT_TITLE_PROPERTY, tr("Location"));
diff --git a/src/libs/utils/qrcparser.cpp b/src/libs/utils/qrcparser.cpp
new file mode 100644
index 0000000000..21904d3716
--- /dev/null
+++ b/src/libs/utils/qrcparser.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** 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 "qrcparser.h"
+
+#include <utils/qtcassert.h>
+
+#include <QCoreApplication>
+#include <QDir>
+#include <QDomDocument>
+#include <QFile>
+#include <QFileInfo>
+#include <QLocale>
+#include <QLoggingCategory>
+#include <QMultiHash>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QSet>
+#include <QStringList>
+
+Q_LOGGING_CATEGORY(qrcParserLog, "qtc.qrcParser", QtWarningMsg)
+
+namespace Utils {
+
+namespace Internal {
+/*!
+ * \class QrcParser
+ * \brief Parses one or more qrc files, and keeps their content cached
+ *
+ * A Qrc resource contains files read from the filesystem but organized in a possibly different way.
+ *
+ * To easily describe that with a simple structure we use a map from qrc paths to the paths in the
+ * filesystem.
+ * By using a map we can easily find all qrc paths that start with a given prefix, and thus loop
+ * on a qrc directory.
+ *
+ * Qrc files also support languages, those are mapped to a prefix of the qrc path.
+ * For example the french /image/bla.png (lang=fr) will have the path "fr/image/bla.png".
+ * The empty language represent the default resource.
+ * Languages are looked up using the locale uiLanguages() property
+ *
+ * For a single qrc a given path maps to a single file, but when one has multiple
+ * (platform specific exclusive) qrc files, then multiple files match, so QStringList are used.
+ *
+ * Especially the collect* functions are thought as low level interface.
+ */
+class QrcParserPrivate
+{
+ Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcParser)
+public:
+ typedef QMap<QString,QStringList> SMap;
+ QrcParserPrivate(QrcParser *q);
+ bool parseFile(const QString &path, const QString &contents);
+ QString firstFileAtPath(const QString &path, const QLocale &locale) const;
+ void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = 0) const;
+ bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const;
+ void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
+ const QLocale *locale = 0) const;
+ void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
+ const QLocale *locale = 0) const;
+
+ QStringList errorMessages() const;
+ QStringList languages() const;
+private:
+ static QString fixPrefix(const QString &prefix);
+ const QStringList allUiLanguages(const QLocale *locale) const;
+
+ SMap m_resources;
+ SMap m_files;
+ QStringList m_languages;
+ QStringList m_errorMessages;
+};
+
+class QrcCachePrivate
+{
+ Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcCachePrivate)
+public:
+ QrcCachePrivate(QrcCache *q);
+ QrcParser::Ptr addPath(const QString &path, const QString &contents);
+ void removePath(const QString &path);
+ QrcParser::Ptr updatePath(const QString &path, const QString &contents);
+ QrcParser::Ptr parsedPath(const QString &path);
+ void clear();
+private:
+ QHash<QString, QPair<QrcParser::Ptr,int> > m_cache;
+ QMutex m_mutex;
+};
+} // namespace Internal
+
+/*! \brief normalizes the path to a file in a qrc resource by dropping the "qrc:/" or ":" and
+ * any extra slashes at the beginning
+ */
+QString QrcParser::normalizedQrcFilePath(const QString &path) {
+ QString normPath = path;
+ int endPrefix = 0;
+ if (path.startsWith(QLatin1String("qrc:/")))
+ endPrefix = 4;
+ else if (path.startsWith(QLatin1String(":/")))
+ endPrefix = 1;
+ if (endPrefix < path.size() && path.at(endPrefix) == QLatin1Char('/'))
+ while (endPrefix + 1 < path.size() && path.at(endPrefix+1) == QLatin1Char('/'))
+ ++endPrefix;
+ normPath = path.right(path.size()-endPrefix);
+ if (!normPath.startsWith(QLatin1Char('/')))
+ normPath.insert(0, QLatin1Char('/'));
+ return normPath;
+}
+
+/*! \brief normalizes the path to a directory in a qrc resource by dropping the "qrc:/" or ":" and
+ * any extra slashes at the beginning, and ensuring it ends with a slash
+ */
+QString QrcParser::normalizedQrcDirectoryPath(const QString &path) {
+ QString normPath = normalizedQrcFilePath(path);
+ if (!normPath.endsWith(QLatin1Char('/')))
+ normPath.append(QLatin1Char('/'));
+ return normPath;
+}
+
+QString QrcParser::qrcDirectoryPathForQrcFilePath(const QString &file)
+{
+ return file.left(file.lastIndexOf(QLatin1Char('/')));
+}
+
+QrcParser::QrcParser()
+{
+ d = new Internal::QrcParserPrivate(this);
+}
+
+QrcParser::~QrcParser()
+{
+ delete d;
+}
+
+bool QrcParser::parseFile(const QString &path, const QString &contents)
+{
+ return d->parseFile(path, contents);
+}
+
+/*! \brief returns fs path of the first (active) file at the given qrc path
+ */
+QString QrcParser::firstFileAtPath(const QString &path, const QLocale &locale) const
+{
+ return d->firstFileAtPath(path, locale);
+}
+
+/*! \brief adds al the fs paths for the given qrc path to *res
+ * If locale is null all possible files are added, otherwise just the first match
+ * using that locale.
+ */
+void QrcParser::collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale) const
+{
+ d->collectFilesAtPath(path, res, locale);
+}
+
+/*! \brief returns true if the given path is a non empty directory
+ */
+bool QrcParser::hasDirAtPath(const QString &path, const QLocale *locale) const
+{
+ return d->hasDirAtPath(path, locale);
+}
+
+/*! \brief adds the directory contents of the given qrc path to res
+ *
+ * adds the qrcFileName => fs paths associations contained in the given qrc path
+ * to res. If addDirs is true directories are also added.
+ * If locale is null all possible files are added, otherwise just the first match
+ * using that locale.
+ */
+void QrcParser::collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs,
+ const QLocale *locale) const
+{
+ d->collectFilesInPath(path, res, addDirs, locale);
+}
+
+void QrcParser::collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
+ const QLocale *locale) const
+{
+ d->collectResourceFilesForSourceFile(sourceFile, res, locale);
+}
+
+/*! \brief returns the errors found while parsing
+ */
+QStringList QrcParser::errorMessages() const
+{
+ return d->errorMessages();
+}
+
+/*! \brief returns all languages used in this qrc resource
+ */
+QStringList QrcParser::languages() const
+{
+ return d->languages();
+}
+
+/*! \brief if the contents are valid
+ */
+bool QrcParser::isValid() const
+{
+ return errorMessages().isEmpty();
+}
+
+QrcParser::Ptr QrcParser::parseQrcFile(const QString &path, const QString &contents)
+{
+ Ptr res(new QrcParser);
+ if (!path.isEmpty())
+ res->parseFile(path, contents);
+ return res;
+}
+
+// ----------------
+
+QrcCache::QrcCache()
+{
+ d = new Internal::QrcCachePrivate(this);
+}
+
+QrcCache::~QrcCache()
+{
+ delete d;
+}
+
+QrcParser::ConstPtr QrcCache::addPath(const QString &path, const QString &contents)
+{
+ return d->addPath(path, contents);
+}
+
+void QrcCache::removePath(const QString &path)
+{
+ d->removePath(path);
+}
+
+QrcParser::ConstPtr QrcCache::updatePath(const QString &path, const QString &contents)
+{
+ return d->updatePath(path, contents);
+}
+
+QrcParser::ConstPtr QrcCache::parsedPath(const QString &path)
+{
+ return d->parsedPath(path);
+}
+
+void QrcCache::clear()
+{
+ d->clear();
+}
+
+// --------------------
+
+namespace Internal {
+
+QrcParserPrivate::QrcParserPrivate(QrcParser *)
+{ }
+
+bool QrcParserPrivate::parseFile(const QString &path, const QString &contents)
+{
+ QDomDocument doc;
+ QDir baseDir(QFileInfo(path).path());
+
+ if (contents.isEmpty()) {
+ // Regular file
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly)) {
+ m_errorMessages.append(file.errorString());
+ return false;
+ }
+
+ QString error_msg;
+ int error_line, error_col;
+ if (!doc.setContent(&file, &error_msg, &error_line, &error_col)) {
+ m_errorMessages.append(tr("XML error on line %1, col %2: %3")
+ .arg(error_line).arg(error_col).arg(error_msg));
+ return false;
+ }
+ } else {
+ // Virtual file from qmake evaluator
+ QString error_msg;
+ int error_line, error_col;
+ if (!doc.setContent(contents, &error_msg, &error_line, &error_col)) {
+ m_errorMessages.append(tr("XML error on line %1, col %2: %3")
+ .arg(error_line).arg(error_col).arg(error_msg));
+ return false;
+ }
+ }
+
+ QDomElement root = doc.firstChildElement(QLatin1String("RCC"));
+ if (root.isNull()) {
+ m_errorMessages.append(tr("The <RCC> root element is missing."));
+ return false;
+ }
+
+ QDomElement relt = root.firstChildElement(QLatin1String("qresource"));
+ for (; !relt.isNull(); relt = relt.nextSiblingElement(QLatin1String("qresource"))) {
+
+ QString prefix = fixPrefix(relt.attribute(QLatin1String("prefix")));
+ const QString language = relt.attribute(QLatin1String("lang"));
+ if (!m_languages.contains(language))
+ m_languages.append(language);
+
+ QDomElement felt = relt.firstChildElement(QLatin1String("file"));
+ for (; !felt.isNull(); felt = felt.nextSiblingElement(QLatin1String("file"))) {
+ const QString fileName = felt.text();
+ const QString alias = felt.attribute(QLatin1String("alias"));
+ QString filePath = baseDir.absoluteFilePath(fileName);
+ QString accessPath;
+ if (!alias.isEmpty())
+ accessPath = language + prefix + alias;
+ else
+ accessPath = language + prefix + fileName;
+ QStringList &resources = m_resources[accessPath];
+ if (!resources.contains(filePath))
+ resources.append(filePath);
+ QStringList &files = m_files[filePath];
+ if (!files.contains(accessPath))
+ files.append(accessPath);
+ }
+ }
+ return true;
+}
+
+// path is assumed to be a normalized absolute path
+QString QrcParserPrivate::firstFileAtPath(const QString &path, const QLocale &locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ for (const QString &language : allUiLanguages(&locale)) {
+ if (m_languages.contains(language)) {
+ SMap::const_iterator res = m_resources.find(language + path);
+ if (res != m_resources.end())
+ return res.value().at(0);
+ }
+ }
+ return QString();
+}
+
+void QrcParserPrivate::collectFilesAtPath(const QString &path, QStringList *files,
+ const QLocale *locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ for (const QString &language : allUiLanguages(locale)) {
+ if (m_languages.contains(language)) {
+ SMap::const_iterator res = m_resources.find(language + path);
+ if (res != m_resources.end())
+ (*files) << res.value();
+ }
+ }
+}
+
+// path is expected to be normalized and start and end with a slash
+bool QrcParserPrivate::hasDirAtPath(const QString &path, const QLocale *locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ QTC_CHECK(path.endsWith(QLatin1Char('/')));
+ for (const QString &language : allUiLanguages(locale)) {
+ if (m_languages.contains(language)) {
+ QString key = language + path;
+ SMap::const_iterator res = m_resources.lowerBound(key);
+ if (res != m_resources.end() && res.key().startsWith(key))
+ return true;
+ }
+ }
+ return false;
+}
+
+void QrcParserPrivate::collectFilesInPath(const QString &path, QMap<QString,QStringList> *contents,
+ bool addDirs, const QLocale *locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ QTC_CHECK(path.endsWith(QLatin1Char('/')));
+ SMap::const_iterator end = m_resources.end();
+ for (const QString &language : allUiLanguages(locale)) {
+ QString key = language + path;
+ SMap::const_iterator res = m_resources.lowerBound(key);
+ while (res != end && res.key().startsWith(key)) {
+ const QString &actualKey = res.key();
+ int endDir = actualKey.indexOf(QLatin1Char('/'), key.size());
+ if (endDir == -1) {
+ QString fileName = res.key().right(res.key().size()-key.size());
+ QStringList &els = (*contents)[fileName];
+ for (const QString &val : res.value())
+ if (!els.contains(val))
+ els << val;
+ ++res;
+ } else {
+ QString dirName = res.key().mid(key.size(), endDir - key.size() + 1);
+ if (addDirs)
+ contents->insert(dirName, QStringList());
+ QString key2 = key + dirName;
+ do {
+ ++res;
+ } while (res != end && res.key().startsWith(key2));
+ }
+ }
+ }
+}
+
+void QrcParserPrivate::collectResourceFilesForSourceFile(const QString &sourceFile,
+ QStringList *results,
+ const QLocale *locale) const
+{
+ // TODO: use FileName from fileutils for file paths
+
+ const QStringList langs = allUiLanguages(locale);
+ SMap::const_iterator file = m_files.find(sourceFile);
+ if (file == m_files.end())
+ return;
+ for (const QString &resource : file.value()) {
+ for (const QString &language : langs) {
+ if (resource.startsWith(language) && !results->contains(resource))
+ results->append(resource);
+ }
+ }
+}
+
+QStringList QrcParserPrivate::errorMessages() const
+{
+ return m_errorMessages;
+}
+
+QStringList QrcParserPrivate::languages() const
+{
+ return m_languages;
+}
+
+QString QrcParserPrivate::fixPrefix(const QString &prefix)
+{
+ const QChar slash = QLatin1Char('/');
+ QString result = QString(slash);
+ for (int i = 0; i < prefix.size(); ++i) {
+ const QChar c = prefix.at(i);
+ if (c == slash && result.at(result.size() - 1) == slash)
+ continue;
+ result.append(c);
+ }
+
+ if (!result.endsWith(slash))
+ result.append(slash);
+
+ return result;
+}
+
+const QStringList QrcParserPrivate::allUiLanguages(const QLocale *locale) const
+{
+ if (!locale)
+ return languages();
+ QStringList langs = locale->uiLanguages();
+ foreach (const QString &language, langs) { // qt4 support
+ if (language.contains(QLatin1Char('_')) || language.contains(QLatin1Char('-'))) {
+ QStringList splits = QString(language).replace(QLatin1Char('_'), QLatin1Char('-'))
+ .split(QLatin1Char('-'));
+ if (splits.size() > 1 && !langs.contains(splits.at(0)))
+ langs.append(splits.at(0));
+ }
+ }
+ if (!langs.contains(QString()))
+ langs.append(QString());
+ return langs;
+}
+
+// ----------------
+
+QrcCachePrivate::QrcCachePrivate(QrcCache *)
+{ }
+
+QrcParser::Ptr QrcCachePrivate::addPath(const QString &path, const QString &contents)
+{
+ QPair<QrcParser::Ptr,int> currentValue;
+ {
+ QMutexLocker l(&m_mutex);
+ currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ currentValue.second += 1;
+ if (currentValue.second > 1) {
+ m_cache.insert(path, currentValue);
+ return currentValue.first;
+ }
+ }
+ QrcParser::Ptr newParser = QrcParser::parseQrcFile(path, contents);
+ if (!newParser->isValid())
+ qCWarning(qrcParserLog) << "adding invalid qrc " << path << " to the cache:" << newParser->errorMessages();
+ {
+ QMutexLocker l(&m_mutex);
+ QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ if (currentValue.first.isNull())
+ currentValue.first = newParser;
+ currentValue.second += 1;
+ m_cache.insert(path, currentValue);
+ return currentValue.first;
+ }
+}
+
+void QrcCachePrivate::removePath(const QString &path)
+{
+ QPair<QrcParser::Ptr,int> currentValue;
+ {
+ QMutexLocker l(&m_mutex);
+ currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ if (currentValue.second == 1) {
+ m_cache.remove(path);
+ } else if (currentValue.second > 1) {
+ currentValue.second -= 1;
+ m_cache.insert(path, currentValue);
+ } else {
+ QTC_CHECK(!m_cache.contains(path));
+ }
+ }
+}
+
+QrcParser::Ptr QrcCachePrivate::updatePath(const QString &path, const QString &contents)
+{
+ QrcParser::Ptr newParser = QrcParser::parseQrcFile(path, contents);
+ {
+ QMutexLocker l(&m_mutex);
+ QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ currentValue.first = newParser;
+ if (currentValue.second == 0)
+ currentValue.second = 1; // add qrc files that are not in the resources of a project
+ m_cache.insert(path, currentValue);
+ return currentValue.first;
+ }
+}
+
+QrcParser::Ptr QrcCachePrivate::parsedPath(const QString &path)
+{
+ QMutexLocker l(&m_mutex);
+ QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ return currentValue.first;
+}
+
+void QrcCachePrivate::clear()
+{
+ QMutexLocker l(&m_mutex);
+ m_cache.clear();
+}
+
+} // namespace Internal
+} // namespace QmlJS
diff --git a/src/libs/utils/qrcparser.h b/src/libs/utils/qrcparser.h
new file mode 100644
index 0000000000..b5a7be761b
--- /dev/null
+++ b/src/libs/utils/qrcparser.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** 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 "utils_global.h"
+
+#include <QMap>
+#include <QSharedPointer>
+#include <QString>
+#include <QStringList>
+
+QT_FORWARD_DECLARE_CLASS(QLocale)
+
+namespace Utils {
+
+namespace Internal {
+class QrcParserPrivate;
+class QrcCachePrivate;
+}
+
+class QTCREATOR_UTILS_EXPORT QrcParser
+{
+public:
+ typedef QSharedPointer<QrcParser> Ptr;
+ typedef QSharedPointer<const QrcParser> ConstPtr;
+ ~QrcParser();
+ bool parseFile(const QString &path, const QString &contents);
+ QString firstFileAtPath(const QString &path, const QLocale &locale) const;
+ void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = 0) const;
+ bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const;
+ void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
+ const QLocale *locale = 0) const;
+ void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *results,
+ const QLocale *locale = 0) const;
+
+ QStringList errorMessages() const;
+ QStringList languages() const;
+ bool isValid() const;
+
+ static Ptr parseQrcFile(const QString &path, const QString &contents);
+ static QString normalizedQrcFilePath(const QString &path);
+ static QString normalizedQrcDirectoryPath(const QString &path);
+ static QString qrcDirectoryPathForQrcFilePath(const QString &file);
+private:
+ QrcParser();
+ QrcParser(const QrcParser &);
+ Internal::QrcParserPrivate *d;
+};
+
+class QTCREATOR_UTILS_EXPORT QrcCache
+{
+public:
+ QrcCache();
+ ~QrcCache();
+ QrcParser::ConstPtr addPath(const QString &path, const QString &contents);
+ void removePath(const QString &path);
+ QrcParser::ConstPtr updatePath(const QString &path, const QString &contents);
+ QrcParser::ConstPtr parsedPath(const QString &path);
+ void clear();
+private:
+ Internal::QrcCachePrivate *d;
+};
+}
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
index dd4fe16f49..992e1817c0 100644
--- a/src/libs/utils/qtcprocess.cpp
+++ b/src/libs/utils/qtcprocess.cpp
@@ -595,12 +595,12 @@ static QString quoteArgWin(const QString &arg)
}
QtcProcess::Arguments QtcProcess::prepareArgs(const QString &cmd, SplitError *err, OsType osType,
- const Environment *env, const QString *pwd)
+ const Environment *env, const QString *pwd, bool abortOnMeta)
{
if (osType == OsTypeWindows)
return prepareArgsWin(cmd, err, env, pwd);
else
- return Arguments::createUnixArgs(splitArgs(cmd, osType, true, err, env, pwd));
+ return Arguments::createUnixArgs(splitArgs(cmd, osType, abortOnMeta, err, env, pwd));
}
@@ -694,7 +694,8 @@ void QtcProcess::start()
const OsType osType = HostOsInfo::hostOs();
if (m_haveEnv) {
if (m_environment.size() == 0)
- qWarning("QtcProcess::start: Empty environment set when running '%s'.", qPrintable(m_command));
+ qWarning("QtcProcess::start: Empty environment set when running '%s'.",
+ qPrintable(m_commandLine.executable().toString()));
env = m_environment;
QProcess::setEnvironment(env.toStringList());
@@ -705,7 +706,9 @@ void QtcProcess::start()
const QString &workDir = workingDirectory();
QString command;
QtcProcess::Arguments arguments;
- bool success = prepareCommand(m_command, m_arguments, &command, &arguments, osType, &env, &workDir);
+ bool success = prepareCommand(m_commandLine.executable().toString(),
+ m_commandLine.arguments(),
+ &command, &arguments, osType, &env, &workDir);
if (osType == OsTypeWindows) {
QString args;
if (m_useCtrlCStub) {
diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h
index 44c5786661..5eeacf666e 100644
--- a/src/libs/utils/qtcprocess.h
+++ b/src/libs/utils/qtcprocess.h
@@ -38,10 +38,9 @@ class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess
public:
QtcProcess(QObject *parent = nullptr);
- void setEnvironment(const Environment &env)
- { m_environment = env; m_haveEnv = true; }
- void setCommand(const QString &command, const QString &arguments)
- { m_command = command; m_arguments = arguments; }
+
+ void setEnvironment(const Environment &env) { m_environment = env; m_haveEnv = true; }
+ void setCommand(const CommandLine &cmdLine) { m_commandLine = cmdLine; }
void setUseCtrlCStub(bool enabled);
void start();
void terminate();
@@ -80,7 +79,8 @@ public:
//! Prepare argument of a shell command for feeding into QProcess
static Arguments prepareArgs(const QString &cmd, SplitError *err,
OsType osType = HostOsInfo::hostOs(),
- const Environment *env = nullptr, const QString *pwd = nullptr);
+ const Environment *env = nullptr, const QString *pwd = nullptr,
+ bool abortOnMeta = true);
//! Prepare a shell command for feeding into QProcess
static bool prepareCommand(const QString &command, const QString &arguments,
QString *outCmd, Arguments *outArgs, OsType osType = HostOsInfo::hostOs(),
@@ -141,8 +141,7 @@ public:
};
private:
- QString m_command;
- QString m_arguments;
+ CommandLine m_commandLine;
Environment m_environment;
bool m_haveEnv = false;
bool m_useCtrlCStub = false;
diff --git a/src/libs/utils/reloadpromptutils.cpp b/src/libs/utils/reloadpromptutils.cpp
index 2270053be0..09a9855784 100644
--- a/src/libs/utils/reloadpromptutils.cpp
+++ b/src/libs/utils/reloadpromptutils.cpp
@@ -33,7 +33,7 @@
namespace Utils {
-QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
+QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FilePath &fileName,
bool modified,
bool enableDiffOption,
QWidget *parent)
@@ -50,7 +50,10 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
msg = QCoreApplication::translate("Utils::reloadPrompt",
"The file <i>%1</i> has been changed on disk. Do you want to reload it?");
}
- msg = msg.arg(fileName.fileName());
+ msg = "<p>" + msg.arg(fileName.fileName()) + "</p><p>" +
+ QCoreApplication::translate("Utils::reloadPrompt",
+ "The default behavior can be set in Tools > Options > Environment > System.")
+ + "</p>";
return reloadPrompt(title, msg, fileName.toUserOutput(), enableDiffOption, parent);
}
diff --git a/src/libs/utils/reloadpromptutils.h b/src/libs/utils/reloadpromptutils.h
index 8991d52b59..82aa409cf5 100644
--- a/src/libs/utils/reloadpromptutils.h
+++ b/src/libs/utils/reloadpromptutils.h
@@ -33,7 +33,7 @@ class QWidget;
QT_END_NAMESPACE
namespace Utils {
-class FileName;
+class FilePath;
enum ReloadPromptAnswer {
ReloadCurrent,
@@ -44,7 +44,7 @@ enum ReloadPromptAnswer {
CloseCurrent
};
-QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
+QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FilePath &fileName,
bool modified,
bool enableDiffOption,
QWidget *parent);
diff --git a/src/libs/utils/runextensions.h b/src/libs/utils/runextensions.h
index 6925504693..eacbd8dc4c 100644
--- a/src/libs/utils/runextensions.h
+++ b/src/libs/utils/runextensions.h
@@ -600,4 +600,59 @@ const QFuture<T> &onResultReady(const QFuture<T> &future, Function f)
return future;
}
-} // Utils
+/*!
+ Adds a handler for when the future is finished.
+ This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
+ or create a QFutureWatcher already for other reasons.
+*/
+template<typename R, typename T>
+const QFuture<T> &onFinished(const QFuture<T> &future,
+ R *receiver,
+ void (R::*member)(const QFuture<T> &))
+{
+ auto watcher = new QFutureWatcher<T>();
+ QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
+ QObject::connect(watcher,
+ &QFutureWatcherBase::finished,
+ receiver,
+ [receiver, member, watcher]() { (receiver->*member)(watcher->future()); });
+ watcher->setFuture(future);
+ return future;
+}
+
+/*!
+ Adds a handler for when the future is finished. The guard object determines the lifetime of
+ the connection.
+ This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
+ or create a QFutureWatcher already for other reasons.
+*/
+template<typename T, typename Function>
+const QFuture<T> &onFinished(const QFuture<T> &future, QObject *guard, Function f)
+{
+ auto watcher = new QFutureWatcher<T>();
+ QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
+ QObject::connect(watcher, &QFutureWatcherBase::finished, guard, [f, watcher]() {
+ f(watcher->future());
+ });
+ watcher->setFuture(future);
+ return future;
+}
+
+/*!
+ Adds a handler for when the future is finished.
+ This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
+ or create a QFutureWatcher already for other reasons.
+*/
+template<typename T, typename Function>
+const QFuture<T> &onFinished(const QFuture<T> &future, Function f)
+{
+ auto watcher = new QFutureWatcher<T>();
+ QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
+ QObject::connect(watcher, &QFutureWatcherBase::finished, [f, watcher]() {
+ f(watcher->future());
+ });
+ watcher->setFuture(future);
+ return future;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/savedaction.cpp b/src/libs/utils/savedaction.cpp
index 0000e54d31..87a785f6db 100644
--- a/src/libs/utils/savedaction.cpp
+++ b/src/libs/utils/savedaction.cpp
@@ -235,7 +235,7 @@ void SavedAction::connectWidget(QWidget *widget, ApplyMode applyMode)
} else if (auto spinBox = qobject_cast<QSpinBox *>(widget)) {
spinBox->setValue(m_value.toInt());
if (applyMode == ImmediateApply) {
- connect(spinBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, [this, spinBox]() { setValue(spinBox->value()); });
}
} else if (auto lineEdit = qobject_cast<QLineEdit *>(widget)) {
diff --git a/src/libs/utils/savefile.cpp b/src/libs/utils/savefile.cpp
index cac25546db..b25432a280 100644
--- a/src/libs/utils/savefile.cpp
+++ b/src/libs/utils/savefile.cpp
@@ -119,7 +119,7 @@ bool SaveFile::commit()
}
QString finalFileName
- = FileUtils::resolveSymlinks(FileName::fromString(m_finalFileName)).toString();
+ = FileUtils::resolveSymlinks(FilePath::fromString(m_finalFileName)).toString();
#ifdef Q_OS_WIN
// Release the file lock
diff --git a/src/libs/utils/settingsaccessor.cpp b/src/libs/utils/settingsaccessor.cpp
index 662ad4bd43..f6d90df7e0 100644
--- a/src/libs/utils/settingsaccessor.cpp
+++ b/src/libs/utils/settingsaccessor.cpp
@@ -98,7 +98,7 @@ bool SettingsAccessor::saveSettings(const QVariantMap &data, QWidget *parent) co
/*!
* Read data from \a path. Do all the necessary postprocessing of the data.
*/
-SettingsAccessor::RestoreData SettingsAccessor::readData(const FileName &path, QWidget *parent) const
+SettingsAccessor::RestoreData SettingsAccessor::readData(const FilePath &path, QWidget *parent) const
{
Q_UNUSED(parent);
RestoreData result = readFile(path);
@@ -111,13 +111,13 @@ SettingsAccessor::RestoreData SettingsAccessor::readData(const FileName &path, Q
* Store the \a data in \a path on disk. Do all the necessary preprocessing of the data.
*/
optional<SettingsAccessor::Issue>
-SettingsAccessor::writeData(const FileName &path, const QVariantMap &data, QWidget *parent) const
+SettingsAccessor::writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const
{
Q_UNUSED(parent);
return writeFile(path, prepareToWriteSettings(data));
}
-QVariantMap SettingsAccessor::restoreSettings(const FileName &settingsPath, QWidget *parent) const
+QVariantMap SettingsAccessor::restoreSettings(const FilePath &settingsPath, QWidget *parent) const
{
const RestoreData result = readData(settingsPath, parent);
@@ -131,7 +131,7 @@ QVariantMap SettingsAccessor::restoreSettings(const FileName &settingsPath, QWid
*
* This method does not do *any* processing of the file contents.
*/
-SettingsAccessor::RestoreData SettingsAccessor::readFile(const FileName &path) const
+SettingsAccessor::RestoreData SettingsAccessor::readFile(const FilePath &path) const
{
PersistentSettingsReader reader;
if (!reader.load(path)) {
@@ -156,7 +156,7 @@ SettingsAccessor::RestoreData SettingsAccessor::readFile(const FileName &path) c
* This method does not do *any* processing of the file contents.
*/
optional<SettingsAccessor::Issue>
-SettingsAccessor::writeFile(const FileName &path, const QVariantMap &data) const
+SettingsAccessor::writeFile(const FilePath &path, const QVariantMap &data) const
{
if (data.isEmpty()) {
return Issue(QCoreApplication::translate("Utils::SettingsAccessor", "Failed to Write File"),
@@ -176,7 +176,7 @@ SettingsAccessor::writeFile(const FileName &path, const QVariantMap &data) const
}
SettingsAccessor::ProceedInfo
-SettingsAccessor::reportIssues(const SettingsAccessor::Issue &issue, const FileName &path,
+SettingsAccessor::reportIssues(const SettingsAccessor::Issue &issue, const FilePath &path,
QWidget *parent) const
{
if (!path.exists())
@@ -217,14 +217,14 @@ QVariantMap SettingsAccessor::prepareToWriteSettings(const QVariantMap &data) co
// BackingUpSettingsAccessor:
// --------------------------------------------------------------------
-FileNameList BackUpStrategy::readFileCandidates(const FileName &baseFileName) const
+FilePathList BackUpStrategy::readFileCandidates(const FilePath &baseFileName) const
{
const QFileInfo pfi = baseFileName.toFileInfo();
const QStringList filter(pfi.fileName() + '*');
const QFileInfoList list = QDir(pfi.dir()).entryInfoList(filter, QDir::Files | QDir::Hidden | QDir::System);
- return Utils::transform(list, [](const QFileInfo &fi) { return FileName::fromString(fi.absoluteFilePath()); });
+ return Utils::transform(list, [](const QFileInfo &fi) { return FilePath::fromString(fi.absoluteFilePath()); });
}
int BackUpStrategy::compare(const SettingsAccessor::RestoreData &data1,
@@ -239,14 +239,12 @@ int BackUpStrategy::compare(const SettingsAccessor::RestoreData &data1,
return 0;
}
-optional<FileName>
-BackUpStrategy::backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const
+optional<FilePath>
+BackUpStrategy::backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const
{
if (oldData == data)
return nullopt;
- FileName backup = path;
- backup.appendString(".bak");
- return backup;
+ return path.stringAppended(".bak");
}
BackingUpSettingsAccessor::BackingUpSettingsAccessor(const QString &docType,
@@ -264,9 +262,9 @@ BackingUpSettingsAccessor::BackingUpSettingsAccessor(std::unique_ptr<BackUpStrat
{ }
SettingsAccessor::RestoreData
-BackingUpSettingsAccessor::readData(const FileName &path, QWidget *parent) const
+BackingUpSettingsAccessor::readData(const FilePath &path, QWidget *parent) const
{
- const FileNameList fileList = readFileCandidates(path);
+ const FilePathList fileList = readFileCandidates(path);
if (fileList.isEmpty()) // No settings found at all.
return RestoreData(path, QVariantMap());
@@ -289,7 +287,7 @@ BackingUpSettingsAccessor::readData(const FileName &path, QWidget *parent) const
}
optional<SettingsAccessor::Issue>
-BackingUpSettingsAccessor::writeData(const FileName &path, const QVariantMap &data,
+BackingUpSettingsAccessor::writeData(const FilePath &path, const QVariantMap &data,
QWidget *parent) const
{
if (data.isEmpty())
@@ -300,9 +298,9 @@ BackingUpSettingsAccessor::writeData(const FileName &path, const QVariantMap &da
return SettingsAccessor::writeData(path, data, parent);
}
-FileNameList BackingUpSettingsAccessor::readFileCandidates(const FileName &path) const
+FilePathList BackingUpSettingsAccessor::readFileCandidates(const FilePath &path) const
{
- FileNameList result = Utils::filteredUnique(m_strategy->readFileCandidates(path));
+ FilePathList result = Utils::filteredUnique(m_strategy->readFileCandidates(path));
if (result.removeOne(baseFilePath()))
result.prepend(baseFilePath());
@@ -310,10 +308,10 @@ FileNameList BackingUpSettingsAccessor::readFileCandidates(const FileName &path)
}
SettingsAccessor::RestoreData
-BackingUpSettingsAccessor::bestReadFileData(const FileNameList &candidates, QWidget *parent) const
+BackingUpSettingsAccessor::bestReadFileData(const FilePathList &candidates, QWidget *parent) const
{
SettingsAccessor::RestoreData bestMatch;
- for (const FileName &c : candidates) {
+ for (const FilePath &c : candidates) {
RestoreData cData = SettingsAccessor::readData(c, parent);
if (m_strategy->compare(bestMatch, cData) > 0)
bestMatch = cData;
@@ -321,7 +319,7 @@ BackingUpSettingsAccessor::bestReadFileData(const FileNameList &candidates, QWid
return bestMatch;
}
-void BackingUpSettingsAccessor::backupFile(const FileName &path, const QVariantMap &data,
+void BackingUpSettingsAccessor::backupFile(const FilePath &path, const QVariantMap &data,
QWidget *parent) const
{
RestoreData oldSettings = SettingsAccessor::readData(path, parent);
@@ -330,7 +328,7 @@ void BackingUpSettingsAccessor::backupFile(const FileName &path, const QVariantM
// Do we need to do a backup?
const QString origName = path.toString();
- optional<FileName> backupFileName = m_strategy->backupName(oldSettings.data, path, data);
+ optional<FilePath> backupFileName = m_strategy->backupName(oldSettings.data, path, data);
if (backupFileName)
QFile::copy(origName, backupFileName.value().toString());
}
@@ -361,22 +359,23 @@ int VersionedBackUpStrategy::compare(const SettingsAccessor::RestoreData &data1,
return -1;
}
-optional<FileName>
-VersionedBackUpStrategy::backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const
+optional<FilePath>
+VersionedBackUpStrategy::backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const
{
Q_UNUSED(data);
- FileName backupName = path;
+ FilePath backupName = path;
const QByteArray oldEnvironmentId = settingsIdFromMap(oldData);
const int oldVersion = versionFromMap(oldData);
if (!oldEnvironmentId.isEmpty() && oldEnvironmentId != m_accessor->settingsId())
- backupName.appendString('.' + QString::fromLatin1(oldEnvironmentId).mid(1, 7));
+ backupName = backupName.stringAppended
+ ('.' + QString::fromLatin1(oldEnvironmentId).mid(1, 7));
if (oldVersion != m_accessor->currentVersion()) {
VersionUpgrader *upgrader = m_accessor->upgrader(oldVersion);
if (upgrader)
- backupName.appendString('.' + upgrader->backupExtension());
+ backupName = backupName.stringAppended('.' + upgrader->backupExtension());
else
- backupName.appendString('.' + QString::number(oldVersion));
+ backupName = backupName.stringAppended('.' + QString::number(oldVersion));
}
if (backupName == path)
return nullopt;
@@ -464,7 +463,7 @@ bool UpgradingSettingsAccessor::isValidVersionAndId(const int version, const QBy
&& (id.isEmpty() || id == m_id || m_id.isEmpty());
}
-SettingsAccessor::RestoreData UpgradingSettingsAccessor::readData(const FileName &path,
+SettingsAccessor::RestoreData UpgradingSettingsAccessor::readData(const FilePath &path,
QWidget *parent) const
{
return upgradeSettings(BackingUpSettingsAccessor::readData(path, parent), currentVersion());
@@ -606,7 +605,7 @@ MergingSettingsAccessor::MergingSettingsAccessor(std::unique_ptr<BackUpStrategy>
UpgradingSettingsAccessor(std::move(strategy), docType, displayName, applicationDisplayName)
{ }
-SettingsAccessor::RestoreData MergingSettingsAccessor::readData(const FileName &path,
+SettingsAccessor::RestoreData MergingSettingsAccessor::readData(const FilePath &path,
QWidget *parent) const
{
RestoreData mainData = UpgradingSettingsAccessor::readData(path, parent); // FULLY upgraded!
diff --git a/src/libs/utils/settingsaccessor.h b/src/libs/utils/settingsaccessor.h
index 10675cbf4c..fd5cf87ef7 100644
--- a/src/libs/utils/settingsaccessor.h
+++ b/src/libs/utils/settingsaccessor.h
@@ -99,7 +99,7 @@ public:
class RestoreData {
public:
RestoreData() = default;
- RestoreData(const FileName &path, const QVariantMap &data) : path{path}, data{data} { }
+ RestoreData(const FilePath &path, const QVariantMap &data) : path{path}, data{data} { }
RestoreData(const QString &title, const QString &message, const Issue::Type type) :
RestoreData(Issue(title, message, type))
{ }
@@ -109,7 +109,7 @@ public:
bool hasError() const { return hasIssue() && issue.value().type == Issue::Type::ERROR; }
bool hasWarning() const { return hasIssue() && issue.value().type == Issue::Type::WARNING; }
- FileName path;
+ FilePath path;
QVariantMap data;
optional<Issue> issue;
};
@@ -121,26 +121,26 @@ public:
const QString displayName;
const QString applicationDisplayName;
- void setBaseFilePath(const FileName &baseFilePath) { m_baseFilePath = baseFilePath; }
+ void setBaseFilePath(const FilePath &baseFilePath) { m_baseFilePath = baseFilePath; }
void setReadOnly() { m_readOnly = true; }
- FileName baseFilePath() const { return m_baseFilePath; }
+ FilePath baseFilePath() const { return m_baseFilePath; }
- virtual RestoreData readData(const FileName &path, QWidget *parent) const;
- virtual optional<Issue> writeData(const FileName &path, const QVariantMap &data, QWidget *parent) const;
+ virtual RestoreData readData(const FilePath &path, QWidget *parent) const;
+ virtual optional<Issue> writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const;
protected:
// Report errors:
- QVariantMap restoreSettings(const FileName &settingsPath, QWidget *parent) const;
- ProceedInfo reportIssues(const Issue &issue, const FileName &path, QWidget *parent) const;
+ QVariantMap restoreSettings(const FilePath &settingsPath, QWidget *parent) const;
+ ProceedInfo reportIssues(const Issue &issue, const FilePath &path, QWidget *parent) const;
virtual QVariantMap preprocessReadSettings(const QVariantMap &data) const;
virtual QVariantMap prepareToWriteSettings(const QVariantMap &data) const;
- virtual RestoreData readFile(const FileName &path) const;
- virtual optional<Issue> writeFile(const FileName &path, const QVariantMap &data) const;
+ virtual RestoreData readFile(const FilePath &path) const;
+ virtual optional<Issue> writeFile(const FilePath &path, const QVariantMap &data) const;
private:
- FileName m_baseFilePath;
+ FilePath m_baseFilePath;
mutable std::unique_ptr<PersistentSettingsWriter> m_writer;
bool m_readOnly = false;
};
@@ -154,14 +154,14 @@ class QTCREATOR_UTILS_EXPORT BackUpStrategy
public:
virtual ~BackUpStrategy() = default;
- virtual FileNameList readFileCandidates(const FileName &baseFileName) const;
+ virtual FilePathList readFileCandidates(const FilePath &baseFileName) const;
// Return -1 if data1 is better that data2, 0 if both are equally worthwhile
// and 1 if data2 is better than data1
virtual int compare(const SettingsAccessor::RestoreData &data1,
const SettingsAccessor::RestoreData &data2) const;
- virtual optional<FileName>
- backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const;
+ virtual optional<FilePath>
+ backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const;
};
class QTCREATOR_UTILS_EXPORT BackingUpSettingsAccessor : public SettingsAccessor
@@ -172,16 +172,16 @@ public:
BackingUpSettingsAccessor(std::unique_ptr<BackUpStrategy> &&strategy, const QString &docType,
const QString &displayName, const QString &applicationDisplayName);
- RestoreData readData(const FileName &path, QWidget *parent) const override;
- optional<Issue> writeData(const FileName &path, const QVariantMap &data,
+ RestoreData readData(const FilePath &path, QWidget *parent) const override;
+ optional<Issue> writeData(const FilePath &path, const QVariantMap &data,
QWidget *parent) const override;
BackUpStrategy *strategy() const { return m_strategy.get(); }
private:
- FileNameList readFileCandidates(const FileName &path) const;
- RestoreData bestReadFileData(const FileNameList &candidates, QWidget *parent) const;
- void backupFile(const FileName &path, const QVariantMap &data, QWidget *parent) const;
+ FilePathList readFileCandidates(const FilePath &path) const;
+ RestoreData bestReadFileData(const FilePathList &candidates, QWidget *parent) const;
+ void backupFile(const FilePath &path, const QVariantMap &data, QWidget *parent) const;
std::unique_ptr<BackUpStrategy> m_strategy;
};
@@ -202,8 +202,8 @@ public:
int compare(const SettingsAccessor::RestoreData &data1,
const SettingsAccessor::RestoreData &data2) const override;
- optional<FileName>
- backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const override;
+ optional<FilePath>
+ backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const override;
const UpgradingSettingsAccessor *accessor() const { return m_accessor; }
@@ -251,7 +251,7 @@ public:
bool isValidVersionAndId(const int version, const QByteArray &id) const;
VersionUpgrader *upgrader(const int version) const;
- RestoreData readData(const FileName &path, QWidget *parent) const override;
+ RestoreData readData(const FilePath &path, QWidget *parent) const override;
protected:
QVariantMap prepareToWriteSettings(const QVariantMap &data) const override;
@@ -284,7 +284,7 @@ public:
const QString &docType, const QString &displayName,
const QString &applicationDisplayName);
- RestoreData readData(const FileName &path, QWidget *parent) const final;
+ RestoreData readData(const FilePath &path, QWidget *parent) const final;
void setSecondaryAccessor(std::unique_ptr<SettingsAccessor> &&secondary);
diff --git a/src/libs/utils/settingsselector.cpp b/src/libs/utils/settingsselector.cpp
index ddfa7a137c..6ae5bff43c 100644
--- a/src/libs/utils/settingsselector.cpp
+++ b/src/libs/utils/settingsselector.cpp
@@ -73,7 +73,7 @@ SettingsSelector::SettingsSelector(QWidget *parent) :
connect(m_renameButton, &QAbstractButton::clicked,
this, &SettingsSelector::renameButtonClicked);
connect(m_configurationCombo,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SettingsSelector::currentChanged);
}
diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp
index 14f52d2539..5a84c92f15 100644
--- a/src/libs/utils/shellcommand.cpp
+++ b/src/libs/utils/shellcommand.cpp
@@ -68,11 +68,11 @@ class ShellCommandPrivate
{
public:
struct Job {
- explicit Job(const QString &wd, const FileName &b, const QStringList &a, int t,
+ explicit Job(const QString &wd, const FilePath &b, const QStringList &a, int t,
const ExitCodeInterpreter &interpreter);
QString workingDirectory;
- FileName binary;
+ FilePath binary;
QStringList arguments;
ExitCodeInterpreter exitCodeInterpreter;
int timeoutS;
@@ -113,7 +113,7 @@ ShellCommandPrivate::~ShellCommandPrivate()
delete m_progressParser;
}
-ShellCommandPrivate::Job::Job(const QString &wd, const FileName &b, const QStringList &a,
+ShellCommandPrivate::Job::Job(const QString &wd, const FilePath &b, const QStringList &a,
int t, const ExitCodeInterpreter &interpreter) :
workingDirectory(wd),
binary(b),
@@ -195,13 +195,13 @@ void ShellCommand::addFlags(unsigned f)
d->m_flags |= f;
}
-void ShellCommand::addJob(const FileName &binary, const QStringList &arguments,
+void ShellCommand::addJob(const FilePath &binary, const QStringList &arguments,
const QString &workingDirectory, const ExitCodeInterpreter &interpreter)
{
addJob(binary, arguments, defaultTimeoutS(), workingDirectory, interpreter);
}
-void ShellCommand::addJob(const FileName &binary, const QStringList &arguments, int timeoutS,
+void ShellCommand::addJob(const FilePath &binary, const QStringList &arguments, int timeoutS,
const QString &workingDirectory, const ExitCodeInterpreter &interpreter)
{
d->m_jobs.push_back(Internal::ShellCommandPrivate::Job(workDirectory(workingDirectory), binary,
@@ -319,7 +319,7 @@ void ShellCommand::run(QFutureInterface<void> &future)
this->deleteLater();
}
-SynchronousProcessResponse ShellCommand::runCommand(const FileName &binary,
+SynchronousProcessResponse ShellCommand::runCommand(const FilePath &binary,
const QStringList &arguments, int timeoutS,
const QString &workingDirectory,
const ExitCodeInterpreter &interpreter)
@@ -359,7 +359,7 @@ SynchronousProcessResponse ShellCommand::runCommand(const FileName &binary,
return response;
}
-SynchronousProcessResponse ShellCommand::runFullySynchronous(const FileName &binary,
+SynchronousProcessResponse ShellCommand::runFullySynchronous(const FilePath &binary,
const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS,
@@ -399,7 +399,7 @@ SynchronousProcessResponse ShellCommand::runFullySynchronous(const FileName &bin
return resp;
}
-SynchronousProcessResponse ShellCommand::runSynchronous(const FileName &binary,
+SynchronousProcessResponse ShellCommand::runSynchronous(const FilePath &binary,
const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS,
diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h
index 22ff4a8df2..f0c427ef53 100644
--- a/src/libs/utils/shellcommand.h
+++ b/src/libs/utils/shellcommand.h
@@ -46,7 +46,7 @@ QT_END_NAMESPACE
namespace Utils {
-class FileName;
+class FilePath;
namespace Internal { class ShellCommandPrivate; }
class QTCREATOR_UTILS_EXPORT ProgressParser
@@ -79,7 +79,7 @@ signals:
void append(const QString &text);
void appendSilently(const QString &text);
void appendError(const QString &text);
- void appendCommand(const QString &workingDirectory, const Utils::FileName &binary,
+ void appendCommand(const QString &workingDirectory, const Utils::FilePath &binary,
const QStringList &args);
void appendMessage(const QString &text);
};
@@ -112,9 +112,9 @@ public:
QString displayName() const;
void setDisplayName(const QString &name);
- void addJob(const FileName &binary, const QStringList &arguments,
+ void addJob(const FilePath &binary, const QStringList &arguments,
const QString &workingDirectory = QString(), const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
- void addJob(const FileName &binary, const QStringList &arguments, int timeoutS,
+ void addJob(const FilePath &binary, const QStringList &arguments, int timeoutS,
const QString &workingDirectory = QString(), const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
void execute(); // Execute tasks asynchronously!
void abort();
@@ -145,7 +145,7 @@ public:
// This is called once per job in a thread.
// When called from the UI thread it will execute fully synchronously, so no signals will
// be triggered!
- virtual SynchronousProcessResponse runCommand(const FileName &binary, const QStringList &arguments,
+ virtual SynchronousProcessResponse runCommand(const FilePath &binary, const QStringList &arguments,
int timeoutS,
const QString &workingDirectory = QString(),
const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
@@ -171,12 +171,12 @@ private:
void run(QFutureInterface<void> &future);
// Run without a event loop in fully blocking mode. No signals will be delivered.
- SynchronousProcessResponse runFullySynchronous(const FileName &binary, const QStringList &arguments,
+ SynchronousProcessResponse runFullySynchronous(const FilePath &binary, const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS, const QString &workingDirectory,
const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
// Run with an event loop. Signals will be delivered.
- SynchronousProcessResponse runSynchronous(const FileName &binary, const QStringList &arguments,
+ SynchronousProcessResponse runSynchronous(const FilePath &binary, const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS, const QString &workingDirectory,
const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h
index dc6867af5d..c381fbd44b 100644
--- a/src/libs/utils/smallstringlayout.h
+++ b/src/libs/utils/smallstringlayout.h
@@ -198,13 +198,6 @@ struct StringDataLayout {
shortString.string[0] = '\0';
}
- StringDataLayout &operator=(const StringDataLayout &other)
- {
- this->shortString = other.shortString;
-
- return *this;
- }
-
union {
AllocatedLayout<MaximumShortStringDataAreaSize> allocated;
ReferenceLayout<MaximumShortStringDataAreaSize> reference;
diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp
index b39af367d5..161cf44e74 100644
--- a/src/libs/utils/stringutils.cpp
+++ b/src/libs/utils/stringutils.cpp
@@ -143,7 +143,7 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt
varName.reserve(strLen - i);
for (; i < strLen; prev = c) {
c = str.at(i++);
- if (c == '\\' && i < strLen && validateVarName(varName)) {
+ if (c == '\\' && i < strLen) {
c = str.at(i++);
// For the replacement, do not skip the escape sequence when followed by a digit.
// This is needed for enabling convenient capture group replacement,
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index e44037f5a1..388da7eeba 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -209,9 +209,9 @@ static void verticalGradientHelper(QPainter *p, const QRect &spanRect, const QRe
void StyleHelper::verticalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored)
{
if (StyleHelper::usePixmapCache()) {
- QString key;
+
QColor keyColor = baseColor(lightColored);
- key.sprintf("mh_vertical %d %d %d %d %d",
+ const QString key = QString::asprintf("mh_vertical %d %d %d %d %d",
spanRect.width(), spanRect.height(), clipRect.width(),
clipRect.height(), keyColor.rgb());
@@ -267,9 +267,9 @@ QRect &rect, bool lightColored)
void StyleHelper::horizontalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored)
{
if (StyleHelper::usePixmapCache()) {
- QString key;
+
QColor keyColor = baseColor(lightColored);
- key.sprintf("mh_horizontal %d %d %d %d %d %d",
+ const QString key = QString::asprintf("mh_horizontal %d %d %d %d %d %d",
spanRect.width(), spanRect.height(), clipRect.width(),
clipRect.height(), keyColor.rgb(), spanRect.x());
@@ -309,8 +309,7 @@ void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *painter,
QRect r = option->rect;
int size = qMin(r.height(), r.width());
QPixmap pixmap;
- QString pixmapName;
- pixmapName.sprintf("StyleHelper::drawArrow-%d-%d-%d-%f",
+ const QString pixmapName = QString::asprintf("StyleHelper::drawArrow-%d-%d-%d-%f",
element, size, enabled, devicePixelRatio);
if (!QPixmapCache::find(pixmapName, &pixmap)) {
QImage image(size * devicePixelRatio, size * devicePixelRatio, QImage::Format_ARGB32_Premultiplied);
@@ -351,8 +350,7 @@ void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *painter,
void StyleHelper::menuGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect)
{
if (StyleHelper::usePixmapCache()) {
- QString key;
- key.sprintf("mh_menu %d %d %d %d %d",
+ const QString key = QString::asprintf("mh_menu %d %d %d %d %d",
spanRect.width(), spanRect.height(), clipRect.width(),
clipRect.height(), StyleHelper::baseColor().rgb());
diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp
index a153e6ac91..bfb9d0d296 100644
--- a/src/libs/utils/synchronousprocess.cpp
+++ b/src/libs/utils/synchronousprocess.cpp
@@ -297,8 +297,7 @@ SynchronousProcess::SynchronousProcess() :
{
d->m_timer.setInterval(1000);
connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout);
- connect(&d->m_process,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&d->m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &SynchronousProcess::finished);
connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error);
connect(&d->m_process, &QProcess::readyReadStandardOutput,
diff --git a/src/libs/utils/textfieldcombobox.cpp b/src/libs/utils/textfieldcombobox.cpp
index db940ad53a..aad64d2e7d 100644
--- a/src/libs/utils/textfieldcombobox.cpp
+++ b/src/libs/utils/textfieldcombobox.cpp
@@ -43,7 +43,7 @@ TextFieldComboBox::TextFieldComboBox(QWidget *parent) :
QComboBox(parent)
{
setEditable(false);
- connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &TextFieldComboBox::slotCurrentIndexChanged);
}
diff --git a/src/libs/utils/touchbar/touchbar.pri b/src/libs/utils/touchbar/touchbar.pri
index 8d60ee423b..5f18595785 100644
--- a/src/libs/utils/touchbar/touchbar.pri
+++ b/src/libs/utils/touchbar/touchbar.pri
@@ -9,7 +9,6 @@ macos {
$$PWD/touchbar_mac.mm \
$$PWD/touchbar_appdelegate_mac.mm
- QT += macextras
LIBS += -framework Foundation -framework AppKit
} else {
SOURCES += $$PWD/touchbar.cpp
diff --git a/src/libs/utils/touchbar/touchbar_mac.mm b/src/libs/utils/touchbar/touchbar_mac.mm
index 67c83aec0c..ee5a45bf72 100644
--- a/src/libs/utils/touchbar/touchbar_mac.mm
+++ b/src/libs/utils/touchbar/touchbar_mac.mm
@@ -29,8 +29,6 @@
#include <utils/utilsicons.h>
-#include <QtMac>
-
#import <AppKit/NSButton.h>
#import <AppKit/NSCustomTouchBarItem.h>
#import <AppKit/NSImage.h>
@@ -145,8 +143,12 @@ static NSImage *iconToTemplateNSImage(const QIcon &icon)
{
// touch bar icons are max 18-22 pts big. our are always 22 pts big.
const QPixmap pixmap = icon.pixmap(22);
- NSImage *image = QtMac::toNSImage(pixmap);
- // toNSImage ignores devicePixelRatio, so fixup after the fact
+
+ CGImageRef cgImage = pixmap.toImage().toCGImage();
+ NSImage *image = [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
+ CFRelease(cgImage);
+
+ // The above code ignores devicePixelRatio, so fixup after the fact
const CGFloat userWidth = pixmap.width() / pixmap.devicePixelRatio();
const CGFloat userHeight = pixmap.height() / pixmap.devicePixelRatio();
image.size = CGSizeMake(userWidth, userHeight); // scales the image
diff --git a/src/libs/utils/unixutils.cpp b/src/libs/utils/unixutils.cpp
index 7db05c22ea..77daae645c 100644
--- a/src/libs/utils/unixutils.cpp
+++ b/src/libs/utils/unixutils.cpp
@@ -77,7 +77,7 @@ QString UnixUtils::substituteFileBrowserParameters(const QString &pre, const QSt
} else if (c == QLatin1Char('f')) {
s = QLatin1Char('"') + file + QLatin1Char('"');
} else if (c == QLatin1Char('n')) {
- s = QLatin1Char('"') + FileName::fromString(file).fileName() + QLatin1Char('"');
+ s = QLatin1Char('"') + FilePath::fromString(file).fileName() + QLatin1Char('"');
} else if (c == QLatin1Char('%')) {
s = c;
} else {
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 5a2712cc3f..c7fef47c97 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -13,7 +13,7 @@ shared {
}
}
-QT += widgets gui network qml
+QT += widgets gui network qml xml
CONFIG += exceptions # used by portlist.cpp, textfileformat.cpp, and ssh/*
@@ -27,6 +27,7 @@ SOURCES += \
$$PWD/environment.cpp \
$$PWD/environmentmodel.cpp \
$$PWD/environmentdialog.cpp \
+ $$PWD/qrcparser.cpp \
$$PWD/qtcprocess.cpp \
$$PWD/reloadpromptutils.cpp \
$$PWD/settingsaccessor.cpp \
@@ -131,12 +132,14 @@ win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
HEADERS += \
+ $$PWD/genericconstants.h \
$$PWD/globalfilechangeblocker.h \
$$PWD/benchmarker.h \
$$PWD/environment.h \
$$PWD/environmentmodel.h \
$$PWD/environmentdialog.h \
$$PWD/pointeralgorithm.h \
+ $$PWD/qrcparser.h \
$$PWD/qtcprocess.h \
$$PWD/utils_global.h \
$$PWD/reloadpromptutils.h \
@@ -266,7 +269,8 @@ HEADERS += \
$$PWD/removefiledialog.h \
$$PWD/differ.h \
$$PWD/cpplanguage_details.h \
- $$PWD/jsontreeitem.h
+ $$PWD/jsontreeitem.h \
+ $$PWD/listmodel.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/newclasswidget.ui \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index d50f7f41f6..694045e290 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -33,7 +33,7 @@ Project {
cpp.frameworks: ["Foundation", "AppKit"]
}
- Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets"] }
+ Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets", "xml"] }
Depends { name: "Qt.macextras"; condition: qbs.targetOS.contains("macos") }
Depends { name: "app_version_header" }
@@ -146,6 +146,7 @@ Project {
"jsontreeitem.h",
"linecolumn.h",
"link.h",
+ "listmodel.h",
"listutils.h",
"macroexpander.cpp",
"macroexpander.h",
@@ -191,6 +192,8 @@ Project {
"proxycredentialsdialog.cpp",
"proxycredentialsdialog.h",
"proxycredentialsdialog.ui",
+ "qrcparser.cpp",
+ "qrcparser.h",
"qtcassert.cpp",
"qtcassert.h",
"qtcolorbutton.cpp",
diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc
index 6ad7dd3196..a8731b6b20 100644
--- a/src/libs/utils/utils.qrc
+++ b/src/libs/utils/utils.qrc
@@ -34,6 +34,8 @@
<file>images/locked@2x.png</file>
<file>images/unlocked.png</file>
<file>images/unlocked@2x.png</file>
+ <file>images/pinned.png</file>
+ <file>images/pinned@2x.png</file>
<file>images/broken.png</file>
<file>images/broken@2x.png</file>
<file>images/notloaded.png</file>
@@ -213,6 +215,14 @@
<file>images/macos_touchbar_bookmark@2x.png</file>
<file>images/macos_touchbar_clear.png</file>
<file>images/macos_touchbar_clear@2x.png</file>
+ <file>images/settings.png</file>
+ <file>images/settings@2x.png</file>
+ <file>images/sort_alphabetically.png</file>
+ <file>images/sort_alphabetically@2x.png</file>
+ <file>images/toggleprogressdetails.png</file>
+ <file>images/toggleprogressdetails@2x.png</file>
+ <file>images/unknownfile.png</file>
+ <file>images/dir.png</file>
</qresource>
<qresource prefix="/codemodel">
<file>images/enum.png</file>
diff --git a/src/libs/utils/utilsicons.cpp b/src/libs/utils/utilsicons.cpp
index 9855165c3e..2227f530c6 100644
--- a/src/libs/utils/utilsicons.cpp
+++ b/src/libs/utils/utilsicons.cpp
@@ -28,7 +28,6 @@
namespace Utils {
namespace Icons {
-
const Icon HOME({
{QLatin1String(":/utils/images/home.png"), Theme::PanelTextColorDark}}, Icon::Tint);
const Icon HOME_TOOLBAR({
@@ -43,6 +42,8 @@ const Icon LOCKED({
{QLatin1String(":/utils/images/locked.png"), Theme::PanelTextColorDark}}, Icon::Tint);
const Icon UNLOCKED_TOOLBAR({
{QLatin1String(":/utils/images/unlocked.png"), Theme::IconsBaseColor}});
+const Icon PINNED({
+ {QLatin1String(":/utils/images/pinned.png"), Theme::PanelTextColorDark}}, Icon::Tint);
const Icon NEXT({
{QLatin1String(":/utils/images/next.png"), Theme::IconsWarningColor}}, Icon::MenuTintedStyle);
const Icon NEXT_TOOLBAR({
@@ -85,6 +86,8 @@ const Icon SNAPSHOT_TOOLBAR({
const Icon NEWSEARCH_TOOLBAR({
{QLatin1String(":/utils/images/zoom.png"), Theme::IconsBaseColor},
{QLatin1String(":/utils/images/iconoverlay_add_small.png"), Theme::IconsRunColor}});
+const Icon SETTINGS_TOOLBAR({
+ {QLatin1String(":/utils/images/settings.png"), Theme::IconsBaseColor}});
const Icon NEWFILE({
{QLatin1String(":/utils/images/filenew.png"), Theme::PanelTextColorMid}}, Icon::Tint);
@@ -102,6 +105,11 @@ const Icon EXPORTFILE_TOOLBAR({
const Icon MULTIEXPORTFILE_TOOLBAR({
{QLatin1String(":/utils/images/filemultiexport.png"), Theme::IconsBaseColor}});
+const Icon UNKNOWN_FILE({
+ {QLatin1String(":/utils/images/unknownfile.png"), Theme::IconsBaseColor}});
+const Icon DIR({
+ {QLatin1String(":/utils/images/dir.png"), Theme::IconsBaseColor}});
+
const Icon UNDO({
{QLatin1String(":/utils/images/undo.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon UNDO_TOOLBAR({
@@ -182,6 +190,11 @@ const Icon LINK({
{QLatin1String(":/utils/images/linkicon.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon LINK_TOOLBAR({
{QLatin1String(":/utils/images/linkicon.png"), Theme::IconsBaseColor}});
+const Icon SORT_ALPHABETICALLY_TOOLBAR({
+ {QLatin1String(":/utils/images/sort_alphabetically.png"), Theme::IconsBaseColor}});
+const Icon TOGGLE_PROGRESSDETAILS_TOOLBAR({
+ {QLatin1String(":/utils/images/toggleprogressdetails.png"), Theme::IconsBaseColor}});
+
const Icon WARNING({
{QLatin1String(":/utils/images/warningfill.png"), Theme::BackgroundColorNormal},
{QLatin1String(":/utils/images/warning.png"), Theme::IconsWarningColor}}, Icon::Tint);
@@ -444,6 +457,10 @@ QIcon CodeModelIcon::iconForType(CodeModelIcon::Type type)
}, Icon::Tint).icon());
return icon;
}
+ case Unknown: {
+ const static QIcon icon(Icons::EMPTY16.icon());
+ return icon;
+ }
default:
break;
}
diff --git a/src/libs/utils/utilsicons.h b/src/libs/utils/utilsicons.h
index b229523911..ae6cd4d1dc 100644
--- a/src/libs/utils/utilsicons.h
+++ b/src/libs/utils/utilsicons.h
@@ -38,6 +38,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon EDIT_CLEAR_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon LOCKED_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon LOCKED;
QTCREATOR_UTILS_EXPORT extern const Icon UNLOCKED_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon PINNED;
QTCREATOR_UTILS_EXPORT extern const Icon NEXT;
QTCREATOR_UTILS_EXPORT extern const Icon NEXT_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon PREV;
@@ -56,6 +57,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TEXTEDITOR;
QTCREATOR_UTILS_EXPORT extern const Icon SNAPSHOT_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon NEWSEARCH_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon SETTINGS_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon NEWFILE;
QTCREATOR_UTILS_EXPORT extern const Icon OPENFILE;
@@ -66,6 +68,9 @@ QTCREATOR_UTILS_EXPORT extern const Icon SAVEFILE_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon EXPORTFILE_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon MULTIEXPORTFILE_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon UNKNOWN_FILE;
+QTCREATOR_UTILS_EXPORT extern const Icon DIR;
+
QTCREATOR_UTILS_EXPORT extern const Icon UNDO;
QTCREATOR_UTILS_EXPORT extern const Icon UNDO_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon REDO;
@@ -106,6 +111,8 @@ QTCREATOR_UTILS_EXPORT extern const Icon CLOSE_SPLIT_RIGHT;
QTCREATOR_UTILS_EXPORT extern const Icon FILTER;
QTCREATOR_UTILS_EXPORT extern const Icon LINK;
QTCREATOR_UTILS_EXPORT extern const Icon LINK_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon SORT_ALPHABETICALLY_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon TOGGLE_PROGRESSDETAILS_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon INFO;
QTCREATOR_UTILS_EXPORT extern const Icon INFO_TOOLBAR;
diff --git a/src/libs/utils/variant.h b/src/libs/utils/variant.h
index 00e9eaf252..371b9312d3 100644
--- a/src/libs/utils/variant.h
+++ b/src/libs/utils/variant.h
@@ -30,10 +30,25 @@
*/
// TODO: replace by #include <(experimental/)variant> depending on compiler and C++ version
-#include <3rdparty/variant/variant.hpp>
+#if __cplusplus >= 201703L
+#error Please delete variant.hpp and the #else section below, then remove this error
+#include <variant>
namespace Utils {
+using std::get;
+using std::get_if;
+using std::holds_alternative;
+using std::variant;
+} // namespace Utils
-using namespace mpark;
+#else
+#include <3rdparty/variant/variant.hpp>
+namespace Utils {
+using mpark::get;
+using mpark::get_if;
+using mpark::holds_alternative;
+using mpark::variant;
} // namespace Utils
+
+#endif
diff --git a/src/libs/utils/wizardpage.h b/src/libs/utils/wizardpage.h
index fa8c60b052..abeccfce13 100644
--- a/src/libs/utils/wizardpage.h
+++ b/src/libs/utils/wizardpage.h
@@ -29,6 +29,7 @@
#include <QSet>
#include <QString>
+#include <QVariant>
#include <QWizardPage>
#include <functional>
@@ -41,30 +42,30 @@ namespace Internal {
class QTCREATOR_UTILS_EXPORT ObjectToFieldWidgetConverter : public QWidget
{
Q_OBJECT
- Q_PROPERTY(QString text READ text NOTIFY textChanged)
+ Q_PROPERTY(QVariant value READ value NOTIFY valueChanged)
public:
- template <class T, typename... Arguments>
- static ObjectToFieldWidgetConverter *create(T *sender, void (T::*member)(Arguments...), const std::function<QString()> &toTextFunction)
+ template<class T, typename... Arguments>
+ static ObjectToFieldWidgetConverter *create(T *sender,
+ void (T::*member)(Arguments...),
+ const std::function<QVariant()> &toVariantFunction)
{
auto widget = new ObjectToFieldWidgetConverter();
- widget->toTextFunction = toTextFunction;
+ widget->toVariantFunction = toVariantFunction;
connect(sender, &QObject::destroyed, widget, &QObject::deleteLater);
- connect(sender, member, widget, [widget] () {
- emit widget->textChanged(widget->text());
- });
+ connect(sender, member, widget, [widget]() { emit widget->valueChanged(widget->value()); });
return widget;
}
signals:
- void textChanged(const QString&);
+ void valueChanged(const QVariant &);
private:
ObjectToFieldWidgetConverter () = default;
- // is used by the property text
- QString text() {return toTextFunction();}
- std::function<QString()> toTextFunction;
+ // is used by the property value
+ QVariant value() { return toVariantFunction(); }
+ std::function<QVariant()> toVariantFunction;
};
} // Internal
@@ -79,10 +80,17 @@ public:
virtual void pageWasAdded(); // called when this page was added to a Utils::Wizard
template<class T, typename... Arguments>
- void registerObjectAsFieldWithName(const QString &name, T *sender, void (T::*changeSignal)(Arguments...),
- const std::function<QString()> &senderToString)
+ void registerObjectAsFieldWithName(const QString &name,
+ T *sender,
+ void (T::*changeSignal)(Arguments...),
+ const std::function<QVariant()> &senderToVariant)
{
- registerFieldWithName(name, Internal::ObjectToFieldWidgetConverter::create(sender, changeSignal, senderToString), "text", SIGNAL(textChanged(QString)));
+ registerFieldWithName(name,
+ Internal::ObjectToFieldWidgetConverter::create(sender,
+ changeSignal,
+ senderToVariant),
+ "value",
+ SIGNAL(valueChanged(QValue)));
}
void registerFieldWithName(const QString &name, QWidget *widget,