From f967545c5aa992146138a12c85fbf8bce450feaf Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 8 Nov 2016 16:00:21 +0100 Subject: [PATCH 01/33] AutoTest: Fix handling of enabled state for code parser Avoid unintentional re-enabling of the code parser. Handling of the enabled state broke several times before, therefore separate it from other states of the parser to avoid breaking it again when not taking enough care while refactoring or adding features related to states. Change-Id: If1eb0dd649225f10bfc3bf06f09851649da75983 Reviewed-by: David Schulz --- src/plugins/autotest/autotestplugin.cpp | 1 + src/plugins/autotest/testcodeparser.cpp | 26 +++++++------------ src/plugins/autotest/testcodeparser.h | 6 +++-- src/plugins/autotest/testnavigationwidget.cpp | 2 +- src/plugins/autotest/testtreemodel.cpp | 5 ++-- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp index 976bee11c85..f6e12685fb4 100644 --- a/src/plugins/autotest/autotestplugin.cpp +++ b/src/plugins/autotest/autotestplugin.cpp @@ -178,6 +178,7 @@ void AutotestPlugin::onRunSelectedTriggered() void AutotestPlugin::updateMenuItemsEnabledState() { const bool enabled = !TestRunner::instance()->isTestRunning() + && TestTreeModel::instance()->parser()->enabled() && TestTreeModel::instance()->parser()->state() == TestCodeParser::Idle; const bool hasTests = TestTreeModel::instance()->hasTests(); diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index bc0845411bc..dadae37de89 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -81,7 +81,7 @@ TestCodeParser::~TestCodeParser() void TestCodeParser::setState(State state) { - if (m_parserState == Shutdown) + if (m_parserState == Shutdown || !m_enabled) return; qCDebug(LOG) << "setState(" << state << "), currentState:" << m_parserState; // avoid triggering parse before code model parsing has finished, but mark as dirty @@ -91,17 +91,13 @@ void TestCodeParser::setState(State state) return; } - if ((state == Disabled || state == Idle) - && (m_parserState == PartialParse || m_parserState == FullParse)) { + if ((state == Idle) && (m_parserState == PartialParse || m_parserState == FullParse)) { qCDebug(LOG) << "Not setting state, parse is running"; return; } m_parserState = state; - if (m_parserState == Disabled) { - m_fullUpdatePostponed = m_partialUpdatePostponed = false; - m_postponedFiles.clear(); - } else if (m_parserState == Idle && ProjectExplorer::SessionManager::startupProject()) { + if (m_parserState == Idle && ProjectExplorer::SessionManager::startupProject()) { if (m_fullUpdatePostponed || m_dirty) { emitUpdateTestTree(); } else if (m_partialUpdatePostponed) { @@ -115,7 +111,7 @@ void TestCodeParser::setState(State state) void TestCodeParser::syncTestFrameworks(const QVector &frameworkIds) { - if (m_parserState != Disabled && m_parserState != Idle) { + if (m_enabled && m_parserState != Idle) { // there's a running parse m_fullUpdatePostponed = m_partialUpdatePostponed = false; m_postponedFiles.clear(); @@ -129,7 +125,7 @@ void TestCodeParser::syncTestFrameworks(const QVector &frameworkIds) QTC_ASSERT(testParser, continue); m_testCodeParsers.append(testParser); } - if (m_parserState != Disabled) + if (m_enabled) updateTestTree(); } @@ -211,7 +207,7 @@ void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) { if (project != ProjectExplorer::SessionManager::startupProject()) return; - if (m_codeModelParsing || m_parserState == Disabled) + if (m_codeModelParsing || !m_enabled) m_fullUpdatePostponed = true; else emitUpdateTestTree(); @@ -276,7 +272,6 @@ bool TestCodeParser::postponed(const QStringList &fileList) m_partialUpdatePostponed = true; } return true; - case Disabled: case Shutdown: break; } @@ -297,7 +292,9 @@ static void parseFileForTests(const QVector &parsers, void TestCodeParser::scanForTests(const QStringList &fileList) { - if (m_parserState == Disabled || m_parserState == Shutdown) { + if (m_parserState == Shutdown) + return; + if (!m_enabled) { m_dirty = true; if (fileList.isEmpty()) { m_fullUpdatePostponed = true; @@ -419,11 +416,6 @@ void TestCodeParser::onFinished() } m_dirty = false; break; - case Disabled: // can happen if all Test related widgets become hidden while parsing - qCDebug(LOG) << "emitting parsingFinished (onFinished, Disabled)"; - emit parsingFinished(); - qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "ParsingFin"; - break; case Shutdown: qCDebug(LOG) << "Shutdown complete - not emitting parsingFinished (onFinished)"; break; diff --git a/src/plugins/autotest/testcodeparser.h b/src/plugins/autotest/testcodeparser.h index 9967c3d08b8..2c68d143f2f 100644 --- a/src/plugins/autotest/testcodeparser.h +++ b/src/plugins/autotest/testcodeparser.h @@ -49,7 +49,6 @@ public: Idle, PartialParse, FullParse, - Disabled, Shutdown }; @@ -57,6 +56,8 @@ public: virtual ~TestCodeParser(); void setState(State state); State state() const { return m_parserState; } + void setEnabled(bool enabled) { m_enabled = enabled; } + bool enabled() const { return m_enabled; } bool isParsing() const { return m_parserState == PartialParse || m_parserState == FullParse; } void setDirty() { m_dirty = true; } void syncTestFrameworks(const QVector &frameworkIds); @@ -95,6 +96,7 @@ private: TestTreeModel *m_model; + bool m_enabled = false; bool m_codeModelParsing = false; bool m_fullUpdatePostponed = false; bool m_partialUpdatePostponed = false; @@ -102,7 +104,7 @@ private: bool m_singleShotScheduled = false; bool m_reparseTimerTimedOut = false; QSet m_postponedFiles; - State m_parserState = Disabled; + State m_parserState = Idle; QFutureWatcher m_futureWatcher; QVector m_testCodeParsers; // ptrs are still owned by TestFrameworkManager QTimer m_reparseTimer; diff --git a/src/plugins/autotest/testnavigationwidget.cpp b/src/plugins/autotest/testnavigationwidget.cpp index 4618520019c..1972638714b 100644 --- a/src/plugins/autotest/testnavigationwidget.cpp +++ b/src/plugins/autotest/testnavigationwidget.cpp @@ -115,7 +115,7 @@ TestNavigationWidget::~TestNavigationWidget() void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) { const bool enabled = !TestRunner::instance()->isTestRunning() - && m_model->parser()->state() == TestCodeParser::Idle; + && m_model->parser()->enabled() && m_model->parser()->state() == TestCodeParser::Idle; const bool hasTests = m_model->hasTests(); QMenu menu; diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index 62b801d5033..6aba8e413c4 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -90,6 +90,7 @@ void TestTreeModel::setupParsingConnections() if (!m_connectionsInitialized) m_parser->setDirty(); + m_parser->setEnabled(true); m_parser->setState(TestCodeParser::Idle); if (m_connectionsInitialized) return; @@ -117,13 +118,13 @@ void TestTreeModel::setupParsingConnections() void TestTreeModel::disableParsing() { if (!m_refCounter.deref() && !AutotestPlugin::instance()->settings()->alwaysParse) - m_parser->setState(TestCodeParser::Disabled); + m_parser->setEnabled(false); } void TestTreeModel::disableParsingFromSettings() { if (!m_refCounter.load()) - m_parser->setState(TestCodeParser::Disabled); + m_parser->setEnabled(false); } bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) From 6d7bb54e774510f1efbe38ffdb6ddcede48b734a Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 3 Nov 2016 16:35:55 +0100 Subject: [PATCH 02/33] AutoTest: Use themed test result icons Task-number: QTCREATORBUG-16663 Change-Id: I087024bf2882690233032e555a825e397c945d3e Reviewed-by: Christian Stenger --- src/plugins/autotest/autotest.qrc | 10 ------ src/plugins/autotest/autotesticons.h | 34 ++++++++++++++++++ .../autotest/images/blacklisted_fail.png | Bin 520 -> 0 bytes .../autotest/images/blacklisted_pass.png | Bin 519 -> 0 bytes src/plugins/autotest/images/debug.png | Bin 621 -> 0 bytes src/plugins/autotest/images/fail.png | Bin 600 -> 0 bytes src/plugins/autotest/images/fatal.png | Bin 597 -> 0 bytes src/plugins/autotest/images/pass.png | Bin 595 -> 0 bytes src/plugins/autotest/images/skip.png | Bin 368 -> 0 bytes src/plugins/autotest/images/warn.png | Bin 621 -> 0 bytes src/plugins/autotest/images/xfail.png | Bin 547 -> 0 bytes src/plugins/autotest/images/xpass.png | Bin 599 -> 0 bytes src/plugins/autotest/testresultmodel.cpp | 29 +++++++-------- 13 files changed, 49 insertions(+), 24 deletions(-) delete mode 100644 src/plugins/autotest/images/blacklisted_fail.png delete mode 100644 src/plugins/autotest/images/blacklisted_pass.png delete mode 100644 src/plugins/autotest/images/debug.png delete mode 100644 src/plugins/autotest/images/fail.png delete mode 100644 src/plugins/autotest/images/fatal.png delete mode 100644 src/plugins/autotest/images/pass.png delete mode 100644 src/plugins/autotest/images/skip.png delete mode 100644 src/plugins/autotest/images/warn.png delete mode 100644 src/plugins/autotest/images/xfail.png delete mode 100644 src/plugins/autotest/images/xpass.png diff --git a/src/plugins/autotest/autotest.qrc b/src/plugins/autotest/autotest.qrc index f92f835e599..6bd7eac6d79 100644 --- a/src/plugins/autotest/autotest.qrc +++ b/src/plugins/autotest/autotest.qrc @@ -5,16 +5,6 @@ images/sort@2x.png images/leafsort.png images/leafsort@2x.png - images/debug.png - images/fail.png - images/fatal.png - images/pass.png - images/skip.png - images/warn.png - images/xfail.png - images/xpass.png - images/blacklisted_fail.png - images/blacklisted_pass.png images/benchmark.png images/runselected_boxes.png images/runselected_boxes@2x.png diff --git a/src/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h index f7845b071f8..ae4a1527cfd 100644 --- a/src/plugins/autotest/autotesticons.h +++ b/src/plugins/autotest/autotesticons.h @@ -38,5 +38,39 @@ const Utils::Icon RUN_SELECTED_OVERLAY({ {QLatin1String(":/images/runselected_boxes.png"), Utils::Theme::BackgroundColorDark}, {QLatin1String(":/images/runselected_tickmarks.png"), Utils::Theme::IconsBaseColor}}); +const Utils::Icon RESULT_PASS({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestPassTextColor}}, + Utils::Icon::Tint); +const Utils::Icon RESULT_FAIL({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestFailTextColor}}, + Utils::Icon::Tint); +const Utils::Icon RESULT_XFAIL({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestXFailTextColor}}, + Utils::Icon::Tint); +const Utils::Icon RESULT_XPASS({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestXPassTextColor}}, + Utils::Icon::Tint); +const Utils::Icon RESULT_SKIP({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestSkipTextColor}}, + Utils::Icon::Tint); +const Utils::Icon RESULT_BLACKLISTEDPASS({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestPassTextColor}, + {":/projectexplorer/images/buildstepdisable.png", Utils::Theme::PanelTextColorDark}}, + Utils::Icon::Tint | Utils::Icon::PunchEdges); +const Utils::Icon RESULT_BLACKLISTEDFAIL({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestFailTextColor}, + {":/projectexplorer/images/buildstepdisable.png", Utils::Theme::PanelTextColorDark}}, + Utils::Icon::Tint | Utils::Icon::PunchEdges); +const Utils::Icon RESULT_BENCHMARK(":/images/benchmark.png"); +const Utils::Icon RESULT_MESSAGEDEBUG({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestDebugTextColor}}, + Utils::Icon::Tint); +const Utils::Icon RESULT_MESSAGEWARN({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestWarnTextColor}}, + Utils::Icon::Tint); +const Utils::Icon RESULT_MESSAGEFATAL({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestFatalTextColor}}, + Utils::Icon::Tint); + } // namespace Icons } // namespace Autotest diff --git a/src/plugins/autotest/images/blacklisted_fail.png b/src/plugins/autotest/images/blacklisted_fail.png deleted file mode 100644 index 695e1f9246856f97b9fd7f952f2bce22a5407761..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7&wIK!hFJ72y?oYNBthW# z$Mc(4?p~LFAxQ7XB)KKsimEOFF71A@Jqm}aFW3uwu`l_YArQMNx_t!)lcUQ^p%f3X zD$bkElb&viTATUqa^n1yvw5}#(<{^Vo&S^ejMLEVfAOq;Wi0|mi+kiB-x2gH-_RSL zy6oMtA7315l3CrIC8Sc4W_a6bENU=g+4K0IhZ)x)Cpp*kw|@BG*<(C2b?v=(Yg6nuH1-{JEi4K;@ia$QXT<~SO+6+|WvgF4lGcjwH&U{i zKE0LYZ;yUy#ah7+Rn6U^Q!d|#y5ws5RcXnoeM!8l&zLi%6=vJAnyWuATctLg!Tz$w z^&7f|+u1t|?YI?fZasOG<#o?<(yiB3-+$T_Jg@E1&x}|i;56TA>wf0;%X%iKZm#sM z*?g+?tAzHY*VS!~Hf}se{F2N!PQT&4_JFO3RPmwxb;%qLrOrJ_sj84OHazy6J?Z~< c>;G(DvUkjAcbp>3z`(%Z>FVdQ&MBb@0Iag@R{#J2 diff --git a/src/plugins/autotest/images/blacklisted_pass.png b/src/plugins/autotest/images/blacklisted_pass.png deleted file mode 100644 index bac3ffb1342bbfa8d291fcfc41f7fc2ce95427d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 519 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7&w08yhFJ72z3l5P5+HKy ztPvLH7igJvVexV6*iEx8G<{3C)W8#U z_wow;IsDfjm7MW>8gxanG$t%}R>c~Vy{p!q3V1$Y;yJ;)Z|}}2zUJHiO|V5E@AR&x z9;;+rMYCS4e{FupX3gS7htmo#JH2H}zr)}BFjA&pcsC2P((g?Xr)m`Q>$2~?xwa-o z(VbCJQkU&idBI7(vJI{GZyeB13rp)cYIt?wtuMb!R!6um<$lV>I@@zgoY1L-yIhR7 zTZP}c#y0Kp?OjPb52k15MI7bIx-6Hlc?-AV#ituvT!Wvoz5iH{|7u-@^~Dg?=G--j zo(Ib(SF;%&yRO(Ge(laj<<4@UB3Z4;2lI08J^rCvx8RMCGsoQ-M?AkSl`hbE7_N5N z{>0Bm%U>5-K3n>-x-+<!5W$hxpz_7s0>KU5XTmJt&CU7V==HO8lyVg#L$3GhH e9j<%6-$7v0(SyCorx_R+7(8A5T-G@yGywpiwe&{- diff --git a/src/plugins/autotest/images/debug.png b/src/plugins/autotest/images/debug.png deleted file mode 100644 index e18bd157e4a53187cb30ea2ec9b3a948c8445ec0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 621 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QUm z*zlT}=>-N#xw%Prc!=BC$+)^og@ouvM#@J;DW#@b6c#EcCCNob$|onQ=HytHmZ}#Q ztCyE+R8(k`mb$jLs}&Y%R#k;`cB&T^#!Q~9T~%e-+^kVq2@zK>E7Pv6)vB-8s;$+m zt##{Ybc=__s6)VD5u8dy2I&s~)r1k4lHf+e)v?*)z=A6x& zbGK~C+q$)2+qRBWmHFJE4F?b_CxH+S5=z3cYv-FNQnyLa!_unIyQw9tS3~N1I977}|Sr0n;9dck`IB>JfJMut) zu)oyflmF|F>Q@*F2`hF)YIUv|VVy;AjiPR7f4^RsE!^M5V> z6uWg#&f1_`%kKUC=$>qUp)B_L(S5Zyvc9a?Iwi=fHZGfIM)A4FZ_7?w2OgcWSkLG4 z+AhEH9kap`Pt}WGj9~t1er&^&$}6W{v!u=wZ(rQj&to8$5qYjqHela9aVCjhiI%c-SRB7Bd2n#H`qyid!yWfCpKWfuXv(AdL$_xM2%eYS zk#*ptL-p^E+ak`a`u#V)?&i1O$5&o?9s7E=wuO380*l(@f`w~0Prh(~LDtrGi|b+w zr9U3a<9*Jby<5F?+qAo(2X}ZpvZ?8Cj4|nT$k$((GAW_nepjNxtYe+~_GLdT`0-+8 z#+NTX8zXKo@*Ga#dBpHworE}T;`C?Ft(n(%{Ste<*3A|~)9_-ulW#OI;4!YA1OYe|FDkU*11u*V}tc2hw-UZe41hd+xyZ@(&5s@0c!o>F#gb{MlgZ_3uRve_PUn z4Zel0yi^wV?N_g`Qg~J366QY3gz&^NPCL8sSGlim**4a9-cQTP_wuAA`@Vnrba?ugeXp;$|6&fYxotb=^TRvwPMSymyA;$raV$K0NLO~5 z^28H6Gpz0^%KXbH-JL&Av|FG5%6C5l#UmRZ8{{9D`md3(XQSbyn>v3_s&E|K9`y3% zqfejyevgix$}Aispk&XP|9HY>CdQz{hb3B>ninrV!pp2HpkQlM6n*{c<;f?X9Mzwe z`i`;hP>oCx!^M!U9f=dpJeANA@p%3@s9aC_n5w+TfspqHH8ejiae4Pf!CJP?l27+^ z((%%XclBlkMXAZm`?S4)<=i)>yv2^Uw`E?*`V$j>{Iks#2ZrTA2Umt=Mv5t3w|&Yi zbs}y-?E2*VJfXg$3>jClID8l9-kz~ksBEXtVG~>V7l+gnwu#@2i)LP0Alq&i>(0@5 zJLge|R*rbL$ceCIvtl)IjqSU$<$o-=@{8+C&Y|wZQnmrnAD(ERsS7`K z?`-$sy2o1t%!3Q;SkgsGtT%+Tx3Vscd%xaR{sY0xVp`EZIc3%V~5-g zy_05oS_10F*^R}Y-K}^(x4M39$uSWwo8840&ktADx@sOx)cH~F;KFpKpk3}<>*0r+ z3vJ)MnD_7K-J<)c^V06UJDva5Vcm(qa|YgB*|AmP&a%#5Tz_?JJucAlrs&(zPrsl3 zj$XgL=(p8`)sr3>$#+b?;Ii2MlK(9a;|!jpHXoCV9(}6Idu9|WmD!ao+!3JjM)sk} z<|CdAC9m(!NSy4V;&{tra@R5rwx%`LuYK(Qd3^2bYsm?03JeODizYMXz1iRt)!|{_ z_T*G~GOfy+Iw|v6PvuXPk7Lf>rlgvv}`A;P;-Q%=xp872@SAkb?bDLrt*yN;Z?tS+7C|@Jw4Yv6Zm&6Cmf*ciw^!9Z**H6MrK#e!si|4)C(kbl zrG^bUhV#HPfgCnyLUgIp8s!Z ae#;D7rPd$vXBZe57(8A5T-G@yGywq9U!=GI diff --git a/src/plugins/autotest/images/warn.png b/src/plugins/autotest/images/warn.png deleted file mode 100644 index a813c1dc9a6478e754aa3f62c40e14bf0f7c814c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 621 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!toOgvp2Lo9liPWJYg5-4)K z{(JQqZ)sggmv+VYr;8T|O*(Lb>voGk)0YKiiY$Vn8Z4@7Z;1%*SQW-9rg24WQV)+) z*7Q`bwN(==BUc*C>N39n_g(qzC&zy@bp0z3`(ALa|ML#_jI}@IBTvgZaXfzI%BS9S zQ?j$=HP7w?g>xR9P6@KJy=(ZZz_q4~^?3A=w%Y0!cS26qU5@is2x*hmI=1E0N1KBu zZa=xZZ(sRa^IiM=*Q|K(L@=;u#mscq)+4P38=E;>?-vi_UxKe?3B{$s6D6Ee@Btfsjn~-oI16wDr>L#=8G3ujW}DNu4(1sZ)={WS>bYo>MeV1y9*OWxn|I z?(*&P^KLT>uVB|YoEzqu{PM*TkBQ3e({$9-b}gH1H*sH{#4(>QQD1Vtx^Dec-cmWu zBbl+sxUaLb)wNGX(ujp)!$G!tiSIi$zp!BvV>Dsdx=7FP@E`eW9Lg;mf@(dTp7U&i zeI_b6ws2h2e7)@F4V&xC6OzyEpK&gKYv$!eu5+zISD9o!dZfhe!Y#*p?yGW(#XI&l z8{K=Q`1oG0dHitU;^gGbhyBE-W%zw(?CO)>a9S@q$MBd010SE1lxfx!&CMs(L|0bS zIyA38P-&miYs#|FPnMavb&(^p^lTwjtFq+`4IKx##6M0*WwpO-v;UHfkGBkQIAXLXD0a7tlNP%3EGS-nS2>iE&e%%|@t zy!*Z)@%oB+D_NIWb{;fjnXbj!RWl{}Q`v&@{m=h!H%IX?tu&5(#=yY9;OXk;vd$@? F2>^vX?UMii diff --git a/src/plugins/autotest/images/xpass.png b/src/plugins/autotest/images/xpass.png deleted file mode 100644 index 964bb4a181e56ac6bb3c5b60fdfaab16755f9f3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 599 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to{$Gm-I&?lq=ic2r=kwz`{mN0<|J2v4l~zi!Y51IJ zA=T@~ADNrGF8g-;bDQ^%-{yRKyY0_e*%*LdUEWSQEBwyY#@qWLeOSnLK6X=1Gw|xVd>)4({VV`pEf#Rs&-}{F66%7MmL- zCvvz23#Szu^Y%F}S>ONSfdcQ_w-KEz&MU7>mF_FHVYy@wQ*P|FaH`X9yT;dxR)vP_ z>{)m9!o2pSTMZL#AATrUb}%6J?<=iUK?n843ZFk$dK2dbufW+e59*5;BpJH2B-G084>`pARe0Z(+9l7G)_*@> z`A)Y2e7%-X_8+>2>C~`&>^LMjriXTE={|qm9B;E7gB#!Hgh)p$= Result::MessageInternal) { From e5becbdfb97b9ec8c6b8f09ea405ec3289c6713d Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 11 Nov 2016 14:26:52 +0100 Subject: [PATCH 03/33] Replace WIN32 define with _WIN32 Only MinGW gcc defines WIN32, MSVC compiler does not. It's also defined by qmake (msvc-desktop.conf), but not by qbs ... Let's just use _WIN32, that's defined everywhere. Change-Id: I8342a70498be54a965dcf7fae63eaf406aaa3c04 Reviewed-by: Tobias Hunger Reviewed-by: Tim Jenssen --- src/libs/utils/smallstringmemory.h | 8 +++++--- .../source/clangrefactoringbackend_global.h | 2 +- .../clangrefactoringbackend/source/sourcelocationsutils.h | 2 +- src/tools/clangrefactoringbackend/source/symbolfinder.cpp | 2 +- tests/unit/unittest/filesystem-utilities.h | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libs/utils/smallstringmemory.h b/src/libs/utils/smallstringmemory.h index 966d12159d8..c9687a09fb6 100644 --- a/src/libs/utils/smallstringmemory.h +++ b/src/libs/utils/smallstringmemory.h @@ -25,6 +25,8 @@ #pragma once +#include + #include #include #include @@ -35,7 +37,7 @@ namespace Memory { inline char *allocate(std::size_t size) { -#ifdef WIN32 +#ifdef Q_OS_WIN32 return static_cast(_aligned_malloc(size, 64)); #else return static_cast(std::malloc(size)); @@ -44,7 +46,7 @@ inline char *allocate(std::size_t size) inline void deallocate(char *memory) { -#ifdef WIN32 +#ifdef Q_OS_WIN32 _aligned_free(memory); #else #pragma GCC diagnostic push @@ -58,7 +60,7 @@ inline void deallocate(char *memory) inline char *reallocate(char *oldMemory, std::size_t newSize) { -#ifdef WIN32 +#ifdef Q_OS_WIN32 return static_cast(_aligned_realloc(oldMemory, newSize, 64)); #else return static_cast(std::realloc(oldMemory, newSize)); diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend_global.h b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend_global.h index fc286b8780e..30d4b2e1a08 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend_global.h +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend_global.h @@ -35,7 +35,7 @@ namespace ClangBackEnd { using USRName = llvm::SmallVector; // use std::filesystem::path if it is supported by all compilers -#ifdef WIN32 +#ifdef _WIN32 const char nativeSeperator = '\\'; #else const char nativeSeperator = '/'; diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h index 70e14b92d22..716c3ef5ee4 100644 --- a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h +++ b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h @@ -58,7 +58,7 @@ Utils::SmallString fromNativePath(Container container) { Utils::SmallString path(container.data(), container.size()); -#ifdef WIN32 +#ifdef _WIN32 std::replace(path.begin(), path.end(), '\\', '/'); #endif diff --git a/src/tools/clangrefactoringbackend/source/symbolfinder.cpp b/src/tools/clangrefactoringbackend/source/symbolfinder.cpp index 1b9a1e23f28..a86da245110 100644 --- a/src/tools/clangrefactoringbackend/source/symbolfinder.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolfinder.cpp @@ -43,7 +43,7 @@ namespace { std::string toNativePath(std::string &&path) { -#ifdef WIN32 +#ifdef _WIN32 std::replace(path.begin(), path.end(), '/', '\\'); #endif diff --git a/tests/unit/unittest/filesystem-utilities.h b/tests/unit/unittest/filesystem-utilities.h index b102a596dcc..36b3e5ed703 100644 --- a/tests/unit/unittest/filesystem-utilities.h +++ b/tests/unit/unittest/filesystem-utilities.h @@ -28,7 +28,7 @@ #include // use std::filesystem::path if it is supported by all compilers -#ifdef WIN32 +#ifdef _WIN32 const char nativeSeperator = '\\'; #else const char nativeSeperator = '/'; @@ -37,7 +37,7 @@ const char nativeSeperator = '/'; inline std::string toNativePath(std::string &&path) { -#ifdef WIN32 +#ifdef _WIN32 std::replace(path.begin(), path.end(), '/', '\\'); #endif From 7fd4cf4a0a153644aa57cbf613a6e9930b753813 Mon Sep 17 00:00:00 2001 From: Sergey Belyashov Date: Thu, 10 Nov 2016 18:34:06 +0300 Subject: [PATCH 04/33] Update Russian translation Change-Id: I75931da08feded181687e313193d79689c38ae49 Reviewed-by: Denis Shienkov Reviewed-by: Oswald Buddenhagen --- share/qtcreator/translations/qtcreator_ru.ts | 613 +++++++++---------- 1 file changed, 299 insertions(+), 314 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts index 9c618509070..7ada6cbbc78 100644 --- a/share/qtcreator/translations/qtcreator_ru.ts +++ b/share/qtcreator/translations/qtcreator_ru.ts @@ -1,177 +1,6 @@ - - - - Zoom In - Увеличить - - - Zoom In (Ctrl + + / Ctrl + Wheel) - Увеличить (Ctrl++ / Ctrl+Колёсико) - - - Zoom Out - Уменьшить - - - Zoom Out (Ctrl + - / Ctrl + Wheel) - Уменьшить (Ctrl+- / Ctrl+Колёсико) - - - Fit to View - Растянуть на окно - - - Fit to View (F11) - Растянуть на окно (F11) - - - Panning - Панорамирование - - - Panning (Shift) - Панорамирование (Shift) - - - Magnifier - Лупа - - - Magnifier Tool (Alt) - Лупа (Alt) - - - Navigator - Навигатор - - - Navigator (Ctrl+E) - Навигатор (Ctrl+E) - - - Copy - Копировать - - - Copy (Ctrl + C) - Копировать (Ctrl+C) - - - Cut - Вырезать - - - Cut (Ctrl + X) - Вырезать (Ctrl+X) - - - Paste - Вставить - - - Paste (Ctrl + V) - Вставить (Ctrl+V) - - - Screenshot - Снимок экрана - - - Screenshot (Ctrl + Shift + C) - Снимок экрана (Ctrl+Shift+C) - - - Export to Image - В изображение - - - Toggle Full Namespace - Переключить пространство имён - - - Align Left - По левому краю - - - Align Left (Ctrl+L,1) - По левому краю (Ctrl + L,1) - - - Align Right - По правому краю - - - Align Right (Ctrl+L,2) - По правому краю (Ctrl+L,2) - - - Align Top - По верху - - - Align Top (Ctrl+L,3) - По верху (Ctrl+L,3) - - - Align Bottom - По низу - - - Align Bottom (Ctrl+L,4) - По низу (Ctrl+L,4) - - - Align Horizontal - Выравнить гоизонтально - - - Align Horizontal (Ctrl+L,5) - Выравнить гоизонтально (Ctrl+L,5) - - - Align Vertical - Выравнить вертикально - - - Align Vertical (Ctrl+L,6) - Выравнить гоизонтально (Ctrl+L,6) - - - Adjust Width - Подогнать ширину - - - Adjust Width (Ctrl+L,7) - Подогнать ширину (Ctrl+L,7) - - - Adjust Height - Подогнать высоту - - - Adjust Height (Ctrl+L,8) - Подогнать высоту (Ctrl+L,8) - - - Adjust Size - Подогнать размер - - - Adjust Size (Ctrl+L,9) - Подогнать размер (Ctrl+L,9) - - - Show Statistics... - Показать статистику... - - - Show Statistics - Показать статистику - - AddSignalHandlerDialog @@ -4129,7 +3958,7 @@ For example, "Revision: 15" will leave the branch at revision 15.Генератор CMake не создаёт файл CodeBlocks. Qt Creator не сможет обрабатывать проект CMake. - Generator: %1<br>Extra Generator: %2 + Generator: %1<br>Extra generator: %2 Генератор: %1<br>Дополнительный генератор: %2 @@ -4259,8 +4088,8 @@ For example, "Revision: 15" will leave the branch at revision 15.Настройка «%1» - *** cmake process crashed! - *** процесс cmake аварийно завершился! + *** cmake process crashed. + *** процесс cmake аварийно завершился. *** cmake process exited with exit code %1. @@ -4454,7 +4283,7 @@ For example, "Revision: 15" will leave the branch at revision 15.Изменить... - CMake Generator: + CMake generator: Генератор CMake: @@ -4474,7 +4303,7 @@ For example, "Revision: 15" will leave the branch at revision 15.Генератор: - Extra Generator: + Extra generator: Дополнительный генератор: @@ -8626,6 +8455,10 @@ Do you want to kill it? Core::Internal::ThemeChooser + + Current theme: %1 + Текущая тема: %1 + Restart Required Требуется перезапуск @@ -11099,10 +10932,6 @@ Flags: %3 Pat&h: Пут&ь: - - <p>Specifying the module (base name of the library or executable) for function or file type breakpoints can significantly speed up debugger start-up times (CDB, LLDB). - <p>Указание модуля (имени библиотеки или программы) для точек останова на функциях или исходниках может значительно повысить скорость запуска отладчика (CDB, LLDB). - &Module: &Модуль: @@ -11159,14 +10988,6 @@ Flags: %3 Edit Selected Breakpoints... Изменить выбранные точки останова... - - Associate Breakpoint With All Threads - Сопоставить точку останова со всеми потоками - - - Associate Breakpoint With Thread %1 - Сопоставить точку останова с потоком %1 - Disable Selected Breakpoints Деактивировать выбранные точки останова @@ -11319,6 +11140,14 @@ Flags: %3 Function Name: Имя функции: + + Associate Breakpoint with All Threads + Сопоставить точку останова со всеми потоками + + + Associate Breakpoint with Thread %1 + Сопоставить точку останова с потоком %1 + Line Number: Номер строки: @@ -11359,6 +11188,10 @@ Flags: %3 Breakpoint on QML Signal Emit Точка остановка на инициировании сигнала QML + + <p>Specifying the module (base name of the library or executable) for function or file type breakpoints can significantly speed up debugger startup times (CDB, LLDB). + <p>Указание модуля (имени библиотеки или программы) для точек останова на функциях или исходниках может значительно повысить скорость запуска отладчика (CDB, LLDB). + Function Функция @@ -11623,17 +11456,6 @@ Flags: %3 Debugger::Internal::CommonOptionsPage - - Stop when %1() is called - Остановиться на вызове %1() - - - Always adds a breakpoint on the <i>%1()</i> function. - Всегда устанавливать точку останова на функцию <i>%1()</i>. - - - - Debugger::Internal::CommonOptionsPageWidget Behavior Поведение @@ -11642,6 +11464,10 @@ Flags: %3 Use alternating row colors in debug views Чередование цвета строк в представлении отладчика + + Changes the font size in the debugger views when the font size in the main editor changes. + Менять размер шрифта в окне отладчика при изменении его в основном окне редактора. + Debugger font size follows main editor Размер шрифта отладчика соответствует редактору @@ -11650,34 +11476,6 @@ Flags: %3 Use tooltips in main editor while debugging Использовать подсказки в основном редакторе при отладке - - Changes the font size in the debugger views when the font size in the main editor changes. - Менять размер шрифта в окне отладчика при изменении его в основном окне редактора. - - - Switch to previous mode on debugger exit - Переключаться в предыдущий режим при завершении отладчика - - - Bring Qt Creator to foreground when application interrupts - Переходить в окно Qt Creator при прерывании приложения - - - Enables a full file path in breakpoints by default also for GDB. - Включение полного пути к исходным файлам для точек останова так же для GDB. - - - Registers Qt Creator for debugging crashed applications. - Зарегистрировать Qt Creator для отладки приложений, завершённых аварийно. - - - Shows a warning when starting the debugger on a binary with insufficient debug information. - Показывать предупреждение при запуске отладчика на программе без отладочной информации. - - - Show QML object tree - Показывать дерево объектов QML - Stopping and stepping in the debugger will automatically open views associated with the current location. Остановка и пошаговая отладка автоматически открывают обзор кода соответствующий текущему положению. @@ -11698,14 +11496,34 @@ Flags: %3 Select this option to close automatically opened memory views when the debugger exits. Включение закрытия автоматически открытых обзоров памяти при завершении отладки. + + Switch to previous mode on debugger exit + Переключаться в предыдущий режим при завершении отладчика + + + Bring Qt Creator to foreground when application interrupts + Переходить в окно Qt Creator при прерывании приложения + Shows QML object tree in Locals and Expressions when connected and not stepping. Показывать дерево объектов QML в окне «Переменные и выражения» при подключении, но не при пошаговой отладке. + + Show QML object tree + Показывать дерево объектов QML + + + Enables a full file path in breakpoints by default also for GDB. + Включение по умолчанию полного пути к исходным файлам для точек останова также и для GDB. + Set breakpoints using a full absolute path Задавать полный путь к точкам останова + + Registers Qt Creator for debugging crashed applications. + Зарегистрировать Qt Creator для отладки приложений, завершённых аварийно. + Use Qt Creator for post-mortem debugging Назначить Qt Creator системным отладчиком @@ -11714,6 +11532,10 @@ Flags: %3 Warn when debugging "Release" builds Предупреждать при отладке «выпускаемых» сборок + + Shows a warning when starting the debugger on a binary with insufficient debug information. + Показывать предупреждение при запуске отладчика на программе без отладочной информации. + Keep editor stationary when stepping Сохранять позицию редактора при пошаговой отладке @@ -11730,6 +11552,14 @@ Flags: %3 <unlimited> <бесконечна> + + Stop when %1() is called + Остановиться на вызове %1() + + + Always adds a breakpoint on the <i>%1()</i> function. + Всегда устанавливать точку останова на функцию <i>%1()</i>. + Debugger::Internal::Console @@ -13939,7 +13769,7 @@ Do you want to retry? Шестнадцатеричный - DecimalFormat + Decimal Десятичный @@ -14674,6 +14504,18 @@ Do you want to retry? Automatic Автоматический + + Note: Evaluators will be re-evaluated after each step. For details, see the <a href="qthelp://org.qt-project.qtcreator/doc/creator-debug-mode.html#locals-and-expressions">documentation</a>. + Замечание: выражения вычисляются после каждого шага. Подробнее читайте в <a href="qthelp://org.qt-project.qtcreator/doc/creator-debug-mode.html#locals-and-expressions">документации</a>. + + + Stop the program when the data at the address is modified. + Останавливать программу при изменении данных по указанному адресу. + + + Stop the program when the data at the address given by the expression is modified. + Останавливать программу при изменении данных по адресу, заданному выражением. + Raw Data Сырые данные @@ -14760,10 +14602,6 @@ Do you want to retry? Enter an expression to evaluate. Введите выражение для вычисления. - - Note: Evaluators will be re-evaluated after each step. For details check the <a href="qthelp://org.qt-project.qtcreator/doc/creator-debug-mode.html#locals-and-expressions">documentation</a>. - Замечание: выражения вычисляются после каждого шага. Подробнее читайте в <a href="qthelp://org.qt-project.qtcreator/doc/creator-debug-mode.html#locals-and-expressions">документации</a>. - New Evaluated Expression Новое вычисляемое выражение @@ -14808,10 +14646,6 @@ Do you want to retry? Add Data Breakpoint at Object's Address (0x%1) Добавить контрольную точку на адрес объекта (0x%1) - - Setting a data breakpoint on an address will cause the program to stop when the data at the address is modified. - Установка контрольной точки на адрес приведёт к остановке программы при изменении данных по этому адресу. - Add Data Breakpoint at Pointer's Address (0x%1) Добавить контрольную точку по адресу указателя (0x%1) @@ -14828,10 +14662,6 @@ Do you want to retry? Add Data Breakpoint at Expression Добавить контрольную точку на вычисляемый адрес - - Setting a data breakpoint on an expression will cause the program to stop when the data at the address given by the expression is modified. - Установка контрольной точки на адрес приведёт к остановке программы при изменении данных по этому адресу. - Open Memory Editor Открыть редактор памяти @@ -17541,6 +17371,10 @@ Would you like to terminate it? copied скопирован + + typechange + смена типа + by both обоими @@ -20352,38 +20186,6 @@ Ids must begin with a lowercase letter. Simulator application process error %1 Приложение из эмулятора вернуло ошибку %1 - - Application install on Simulator failed. %1 - Не удалось установить приложение на эмулятор. %1 - - - Application install on Simulator failed. Simulator not running. - Не удалось установить приложение на эмулятор. Он не запущен. - - - Application launch on Simulator failed. Invalid Bundle path %1 - Запуск приложения на эмуляторе не удался. Неверный путь пакета %1 - - - Spawning the Application process on Simulator failed. - Не удалось породить процесс приложения на эмуляторе. - - - Application launch on Simulator failed. Simulator not running. - Не удалось запустить приложение на эмуляторе. Он не запущен. - - - Application launch on Simulator failed. %1 - Запуск приложения на эмуляторе не удался. %1 - - - Spawning the Application process on Simulator failed. Spawning timed out. - Не удалось породить процесс приложения на эмуляторе. Время порождения истекло. - - - Simulator application process error %1 - Приложение из эмулятора вернуло ошибку %1 - IosDeployStepWidget @@ -21402,6 +21204,10 @@ Ids must begin with a lowercase letter. Nim source file Исходник Nim + + Nim script file + Файл сценария Nim + Qt Creator Python project file Проект Qt Creator для Python @@ -21422,6 +21228,14 @@ Ids must begin with a lowercase letter. QML file Файл QML + + Linguist compiled translations + Скомпилированные переводы Linguist + + + Linguist source translations + Исходные переводы Linguist + SCXML State Chart Диаграмма состояний SCXML @@ -21502,14 +21316,6 @@ Ids must begin with a lowercase letter. QML Project file Файл проекта QML - - Linguist translated messages (machine-readable) - Сообщения переведенные через Linguist (удобные для машины) - - - Linguist message catalog - Каталог сообщений Linguist - Qt Resource file Файл ресурсов Qt @@ -24524,11 +24330,11 @@ cannot be found in the path. Имя в файловой системе: - Select a file as icon - Выберите файл значка + Select Icon File + Выбор файла значка - Reset to the device default icon + Reset to Device Default Icon Назначить стандартный для устройства значок @@ -24959,6 +24765,14 @@ to project "%2". Projects Проекты + + Import Existing Build... + Импорт сборки... + + + Manage Kits... + Управление... + Import directory Импортируемый каталог @@ -25111,17 +24925,6 @@ to project "%2". Новое название конфигурации установки <b>%1</b>: - - ProjectExplorer::Internal::SelectorModel - - Import Existing Build... - Импорт сборки... - - - Manage Kits... - Управление... - - ProjectExplorer::Internal::SessionDialog @@ -26182,7 +25985,7 @@ Preselects a desktop Qt for building the application if available. Material - Материальный + Материальный Universal @@ -26316,6 +26119,14 @@ Preselects a desktop Qt for building the application if available. Nim File Файл Nim + + Creates an empty Nim script file using UTF-8 charset. + Создание пустого файла сценария Nim с использованием кодировки UTF-8. + + + Nim Script File + Файл сценария Nim + State Chart Name and Location Название и размещение диаграммы состояний @@ -28653,9 +28464,8 @@ These files are preserved. QbsProjectManager::Internal::QbsProject - Failed! - Очень плохое сообщение, скорее всего не дописали - Ошибка + Failed + Сбой Could not write project file %1. @@ -30203,12 +30013,12 @@ Neither the path to the library nor the path to its includes is added to the .pr Закрытие сетевого соединения - Socket state changed to BoundState. This should not happen! - Состояние сокета изменилось на BoundState. Это не должно было произойти! + Socket state changed to BoundState. This should not happen. + Состояние сокета изменилось на BoundState. Это не должно было произойти. - Socket state changed to ListeningState. This should not happen! - Состояние сокета изменилось на ListeningState. Это не должно было произойти! + Socket state changed to ListeningState. This should not happen. + Состояние сокета изменилось на ListeningState. Это не должно было произойти. Unknown state %1 @@ -31628,7 +31438,7 @@ This is independent of the visibility property in QML. Файл или каталог не найден. - QML module not found(%1). + QML module not found (%1). Import paths: %2 @@ -33474,8 +33284,8 @@ Do you want to retry? Повторить? - Failed to connect! - Не удалось подключиться! + Failed to connect. + Не удалось подключиться. Disable Profiling @@ -36406,6 +36216,177 @@ Description: %4 Описание: %4 + + ScxmlEditor::PluginInterface::ActionHandler + + Zoom In + Увеличить + + + Zoom In (Ctrl + + / Ctrl + Wheel) + Увеличить (Ctrl++ / Ctrl+Колёсико) + + + Zoom Out + Уменьшить + + + Zoom Out (Ctrl + - / Ctrl + Wheel) + Уменьшить (Ctrl+- / Ctrl+Колёсико) + + + Fit to View + Растянуть на окно + + + Fit to View (F11) + Растянуть на окно (F11) + + + Panning + Панорамирование + + + Panning (Shift) + Панорамирование (Shift) + + + Magnifier + Лупа + + + Magnifier Tool (Alt) + Лупа (Alt) + + + Navigator + Навигатор + + + Navigator (Ctrl+E) + Навигатор (Ctrl+E) + + + Copy + Копировать + + + Copy (Ctrl + C) + Копировать (Ctrl+C) + + + Cut + Вырезать + + + Cut (Ctrl + X) + Вырезать (Ctrl+X) + + + Paste + Вставить + + + Paste (Ctrl + V) + Вставить (Ctrl+V) + + + Screenshot + Снимок экрана + + + Screenshot (Ctrl + Shift + C) + Снимок экрана (Ctrl+Shift+C) + + + Export to Image + В изображение + + + Toggle Full Namespace + Переключить пространство имён + + + Align Left + По левому краю + + + Align Left (Ctrl+L,1) + По левому краю (Ctrl + L,1) + + + Align Right + По правому краю + + + Align Right (Ctrl+L,2) + По правому краю (Ctrl+L,2) + + + Align Top + По верху + + + Align Top (Ctrl+L,3) + По верху (Ctrl+L,3) + + + Align Bottom + По низу + + + Align Bottom (Ctrl+L,4) + По низу (Ctrl+L,4) + + + Align Horizontal + Выравнить гоизонтально + + + Align Horizontal (Ctrl+L,5) + Выравнить гоизонтально (Ctrl+L,5) + + + Align Vertical + Выравнить вертикально + + + Align Vertical (Ctrl+L,6) + Выравнить гоизонтально (Ctrl+L,6) + + + Adjust Width + Подогнать ширину + + + Adjust Width (Ctrl+L,7) + Подогнать ширину (Ctrl+L,7) + + + Adjust Height + Подогнать высоту + + + Adjust Height (Ctrl+L,8) + Подогнать высоту (Ctrl+L,8) + + + Adjust Size + Подогнать размер + + + Adjust Size (Ctrl+L,9) + Подогнать размер (Ctrl+L,9) + + + Show Statistics... + Показать статистику... + + + Show Statistics + Показать статистику + + ScxmlEditor::PluginInterface::BaseItem @@ -36981,11 +36962,11 @@ with a password, which you can enter below. StatesDelegate - Set when condition + Set when Condition Задать условие when - Reset when condition + Reset when Condition Сбросить условие when @@ -37589,9 +37570,13 @@ with a password, which you can enter below. Aborting replace. Прерывание замены. - - %1 found - найдено: %1 + + %n found + + %n найден + %n найдено + %n найдено + @@ -43536,6 +43521,10 @@ should a repository require SSH-authentication (see documentation on SSH and the Auto width Автоширина + + <font color=red>Invalid syntax.</font> + <font color=red>Неверный синтаксис.</font> + Box Коробкой @@ -43576,10 +43565,6 @@ should a repository require SSH-authentication (see documentation on SSH and the Boundaries Границы - - <font color=red>Invalid syntax!</font> - <font color=red>Неверный синтаксис!</font> - Multi-Selection Множественное выделение From 3c8038979631ecc84628714318a6864074840626 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 14 Nov 2016 12:05:04 +0100 Subject: [PATCH 05/33] winrt: Remove experimental flag The plugin is in use since many years and can be considered stable these days. Change-Id: Ia41b24849abd16e15313ab97f82d277673b3904b Reviewed-by: Eike Ziller --- src/plugins/winrt/WinRt.json.in | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/winrt/WinRt.json.in b/src/plugins/winrt/WinRt.json.in index 66b4e18402d..9cccdba66f1 100644 --- a/src/plugins/winrt/WinRt.json.in +++ b/src/plugins/winrt/WinRt.json.in @@ -2,7 +2,6 @@ \"Name\" : \"WinRt\", \"Version\" : \"$$QTCREATOR_VERSION\", \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", - \"Experimental\" : true, \"Platform\" : \"Windows (8.1|10)\", \"Vendor\" : \"The Qt Company Ltd\", \"Copyright\" : \"(C) 2016 The Qt Company Ltd\", From 8f2f614f22064280f29c3aa683ceeb273ec6e9e0 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 14 Nov 2016 09:43:53 +0100 Subject: [PATCH 06/33] Debugger: Force #include in boost dumper tests We might end up with undefined boost version otherwise. Change-Id: Ibcdc70cbce8aad42947ce4760df0208d5ebe83f7 Reviewed-by: Christian Stenger --- tests/auto/debugger/tst_dumpers.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 786201dfcba..851f0d44ecc 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -587,6 +587,7 @@ struct Profile { Profile(const QByteArray &contents) : contents(contents) {} + QByteArray includes; QByteArray contents; }; @@ -609,6 +610,7 @@ struct BoostProfile : public Profile contents = QByteArray("INCLUDEPATH += ") + boostIncPath.constData(); else contents = "macx:INCLUDEPATH += /usr/local/include"; + includes = "#include \n"; } }; @@ -668,6 +670,7 @@ public: const Data &operator+(const Profile &profile) const { profileExtra += profile.contents; + includes += profile.includes; return *this; } From e4e1bdb27a04579913f8bd079b4ee2643e06a458 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 14 Nov 2016 12:24:56 +0100 Subject: [PATCH 07/33] Debugger: Robustify typedef member lookup Some code path did not resolve typedefs when looking up struct members by name, making e.g. the BoostList dumper fail for LLDB. Change-Id: I7adf235cff3941574cab9f03d6f15ec5f3e2f0bd Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index b637eef4100..91053ceced6 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -2759,6 +2759,20 @@ class DumperBase: self.targetValue = None # For references. self.isBaseClass = None + def copy(self): + val = self.dumper.Value(self.dumper) + val.dumper = self.dumper + val.name = self.name + val.type = self.type + val.ldata = self.ldata + val.laddress = self.laddress + val.lIsInScope = self.lIsInScope + val.ldisplay = self.ldisplay + val.lbitpos = self.lbitpos + val.lbitsize = self.lbitsize + val.targetValue = self.targetValue + return val + def check(self): if self.laddress is not None and not self.dumper.isInt(self.laddress): error('INCONSISTENT ADDRESS: %s' % type(self.laddress)) @@ -2848,12 +2862,18 @@ class DumperBase: members = self.members(True) for member in members: #warn('CHECKING FIELD %s' % member.name) + if member.type.code == TypeCodeTypedef: + member = member.detypedef() if member.name == name: return member for member in members: #warn('CHECKING BASE %s' % member.name) #if member.name == name: # return member + if member.type.code == TypeCodeTypedef: + member = member.detypedef() + if member.name == name: + return member if member.type.code == TypeCodeStruct: res = member.findMemberByName(name) if res is not None: @@ -2979,6 +2999,9 @@ class DumperBase: res = [] anonNumber = 0 for field in fields: + if isinstance(field, self.dumper.Value): + res.append(field) + continue if field.isBaseClass and not includeBases: continue if field.name is None or len(field.name) == 0: @@ -3029,10 +3052,8 @@ class DumperBase: self.check() if self.type.code != TypeCodeTypedef: error("WRONG") - val = self.dumper.Value(self.dumper) + val = self.copy() val.type = self.type.ltarget - val.ldata = self.ldata - val.laddress = self.laddress #warn("DETYPEDEF FROM: %s" % self) #warn("DETYPEDEF TO: %s" % val) return val From a4e213b775d41f5184d1543fae6a3a794595e6b5 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 14 Nov 2016 14:18:15 +0100 Subject: [PATCH 08/33] ProjectExplorer: Avoid accessing nullptr for unconfigured projects Task-number: QTCREATORBUG-17256 Change-Id: I586c7267cbb4f9f16134c1be08aa4a738e990e80 Reviewed-by: hjk --- src/plugins/projectexplorer/projectimporter.h | 2 +- src/plugins/projectexplorer/targetsetuppage.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/projectimporter.h b/src/plugins/projectexplorer/projectimporter.h index 50d98b275a6..62d1350559e 100644 --- a/src/plugins/projectexplorer/projectimporter.h +++ b/src/plugins/projectexplorer/projectimporter.h @@ -39,7 +39,7 @@ class Project; class Target; // Documentation inside. -class PROJECTEXPLORER_EXPORT ProjectImporter +class PROJECTEXPLORER_EXPORT ProjectImporter : public QObject { public: ProjectImporter(const QString &path); diff --git a/src/plugins/projectexplorer/targetsetuppage.h b/src/plugins/projectexplorer/targetsetuppage.h index d004143634b..8f589506294 100644 --- a/src/plugins/projectexplorer/targetsetuppage.h +++ b/src/plugins/projectexplorer/targetsetuppage.h @@ -32,6 +32,7 @@ #include +#include #include #include @@ -109,7 +110,7 @@ private: KitMatcher m_requiredMatcher; KitMatcher m_preferredMatcher; - ProjectImporter *m_importer = nullptr; + QPointer m_importer = nullptr; QLayout *m_baseLayout = nullptr; QString m_projectPath; QString m_defaultShadowBuildLocation; From 56e684fc37c77c7a161f5bcc3eed3cbd0a23bd2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Thu, 10 Nov 2016 10:57:58 +0100 Subject: [PATCH 09/33] Fix readability of TODO entries on dark themes The TODO plugin provides default values for color-coding backgrounds based on the severity of each item. These colors are rather light, and there is just one default with no theme awareness. It is a bug to use a theme-aware text color on a fixed-color background -- just switch to a dark theme such as flat-dark and observe the unreadability. This patch simply ensures that the default settings have reasonable readability. These defaults are still not theme-aware, but at least they are consistent. Change-Id: Ibf35a241c70e0f1ea001b55f84fd2e1dd1a0a2ea Reviewed-by: Alessandro Portale --- share/qtcreator/themes/flat-dark.creatortheme | 2 +- share/qtcreator/themes/flat-light.creatortheme | 2 +- share/qtcreator/themes/flat.creatortheme | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme index bf3b181a28f..5e8f7d3e11f 100644 --- a/share/qtcreator/themes/flat-dark.creatortheme +++ b/share/qtcreator/themes/flat-dark.creatortheme @@ -124,7 +124,7 @@ TextColorHighlight=ffff0000 TextColorLink=textColorLink TextColorLinkVisited=textColorLinkVisited TextColorNormal=text -TodoItemTextColor=text +TodoItemTextColor=ff000000 ToggleButtonBackgroundColor=shadowBackground ToolBarBackgroundColor=shadowBackground TreeViewArrowColorNormal=hoverBackground diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme index ae978557363..18746658a13 100644 --- a/share/qtcreator/themes/flat-light.creatortheme +++ b/share/qtcreator/themes/flat-light.creatortheme @@ -122,7 +122,7 @@ TextColorHighlight=ffff0000 TextColorLink=ff007af4 TextColorLinkVisited=ffa57aff TextColorNormal=text -TodoItemTextColor=text +TodoItemTextColor=ff000000 ToggleButtonBackgroundColor=shadowBackground ToolBarBackgroundColor=shadowBackground TreeViewArrowColorNormal=hoverBackground diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme index a4790bbbcc4..472353a6ac7 100644 --- a/share/qtcreator/themes/flat.creatortheme +++ b/share/qtcreator/themes/flat.creatortheme @@ -120,7 +120,7 @@ TextColorHighlight=ffff0000 TextColorLink=ff007af4 TextColorLinkVisited=ffa57aff TextColorNormal=text -TodoItemTextColor=text +TodoItemTextColor=ff000000 ToggleButtonBackgroundColor=shadowBackground ToolBarBackgroundColor=shadowBackground TreeViewArrowColorNormal=hoverBackground From 7e904c4d744a968a71b7480c00b37c3554103b30 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 14 Nov 2016 12:29:26 +0100 Subject: [PATCH 10/33] Debugger: Use explicit sizes in SSE dumpers We know them, no need to guess. Change-Id: I9788cfe178e4b013276f77df9aef5f4254818007 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/misctypes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/debugger/misctypes.py b/share/qtcreator/debugger/misctypes.py index a07708034a8..fa7625717f7 100644 --- a/share/qtcreator/debugger/misctypes.py +++ b/share/qtcreator/debugger/misctypes.py @@ -62,7 +62,7 @@ def qdump____m512d(d, value): d.putArrayData(value.address(), 8, d.lookupType('double')) def qdump____m128i(d, value): - data = d.hexencode(value.data()) + data = d.hexencode(value.data(16)) d.putValue(':'.join('%04x' % int(data[i:i+4], 16) for i in xrange(0, 32, 4))) if d.isExpanded(): with Children(d): @@ -73,7 +73,7 @@ def qdump____m128i(d, value): d.putArrayItem('uint64x2', addr, 2, 'unsigned long long') def qdump____m256i(d, value): - data = d.hexencode(value.data()) + data = d.hexencode(value.data(32)) d.putValue(':'.join('%04x' % int(data[i:i+4], 16) for i in xrange(0, 64, 4))) if d.isExpanded(): with Children(d): @@ -84,7 +84,7 @@ def qdump____m256i(d, value): d.putArrayItem('uint64x4', addr, 4, 'unsigned long long') def qdump____m512i(d, value): - data = d.hexencode(value.data()) + data = d.hexencode(value.data(64)) d.putValue(':'.join('%04x' % int(data[i:i+4], 16) for i in xrange(0, 64, 4)) + ', ' + ':'.join('%04x' % int(data[i:i+4], 16) for i in xrange(64, 128, 4))) if d.isExpanded(): From 0df4c0bd5f055e6f40d292aee34886cec4faae46 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 15 Nov 2016 08:52:31 +0100 Subject: [PATCH 11/33] Debugger: Remove some unused and forgotten function Change-Id: Ic9d0e609dbc41aeed292f3d069ebfc0c6ef324ee Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggertooltipmanager.cpp | 7 ------- src/plugins/debugger/debuggertooltipmanager.h | 1 - 2 files changed, 8 deletions(-) diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp index 1235adb7237..fad3fd09c01 100644 --- a/src/plugins/debugger/debuggertooltipmanager.cpp +++ b/src/plugins/debugger/debuggertooltipmanager.cpp @@ -692,13 +692,6 @@ bool DebuggerToolTipContext::isSame(const DebuggerToolTipContext &other) const && filesMatch(fileName, other.fileName); } -void DebuggerToolTipContext::appendFormatRequest(DebuggerCommand *cmd) const -{ - cmd->arg("expression", expression); - cmd->arg("fileName", fileName); - cmd->arg("iname", iname); -} - QString DebuggerToolTipContext::toolTip() const { return DebuggerToolTipManager::tr("Expression %1 in function %2 from line %3 to %4") diff --git a/src/plugins/debugger/debuggertooltipmanager.h b/src/plugins/debugger/debuggertooltipmanager.h index 78f48d97692..33324ccf45e 100644 --- a/src/plugins/debugger/debuggertooltipmanager.h +++ b/src/plugins/debugger/debuggertooltipmanager.h @@ -49,7 +49,6 @@ public: bool isValid() const { return !expression.isEmpty(); } bool matchesFrame(const StackFrame &frame) const; bool isSame(const DebuggerToolTipContext &other) const; - void appendFormatRequest(DebuggerCommand *cmd) const; QString toolTip() const; QString fileName; From e265c5403ba3bbdff939ddbffe4b6c04ea0760a2 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 15 Nov 2016 08:38:04 +0100 Subject: [PATCH 12/33] Debugger: Merge two variants to set detach-on-fork Change-Id: I8459110b2729c0ee8c797f184c018fdb44cafe45 Reviewed-by: Christian Stenger --- src/plugins/debugger/gdb/gdbengine.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 53f94c4f6b3..b9b40694789 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1687,9 +1687,6 @@ void GdbEngine::handleShowVersion(const DebuggerResponse &response) else runCommand({"set target-async off", ConsoleCommand}); - if (runParameters().multiProcess) - runCommand({"set detach-on-fork off", ConsoleCommand}); - //runCommand("set build-id-verbose 2", ConsoleCommand); } } @@ -4047,7 +4044,7 @@ void GdbEngine::startGdb(const QStringList &args) runCommand({"set auto-solib-add on", ConsoleCommand}); } - if (boolSetting(MultiInferior)) { + if (boolSetting(MultiInferior) || runParameters().multiProcess) { //runCommand("set follow-exec-mode new"); runCommand({"set detach-on-fork off"}); } From 8594020b57dea90f94fabd1227b43193e426b6f4 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 14 Nov 2016 15:35:05 +0100 Subject: [PATCH 13/33] CppTools: Fix crash on document close Emit the signal only if we are not canceled. Task-number: QTCREATORBUG-17249 Change-Id: I5082a5fe7554eecdc7ec5d148150c1b169002f6d Reviewed-by: Christian Stenger --- src/plugins/cpptools/cppchecksymbols.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp index 8859aef78eb..7bc34c903c5 100644 --- a/src/plugins/cpptools/cppchecksymbols.cpp +++ b/src/plugins/cpptools/cppchecksymbols.cpp @@ -346,9 +346,9 @@ void CheckSymbols::run() _usages << QVector::fromList(_macroUses); flush(); } - } - emit codeWarningsUpdated(_doc, _diagMsgs); + emit codeWarningsUpdated(_doc, _diagMsgs); + } reportFinished(); } From bf0c4e7c2bea83f54982a5b1f1529e2b40244c4c Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 22 Sep 2016 15:13:44 +0200 Subject: [PATCH 14/33] ClangStaticAnalyzer: Raise supported clang version to 3.9.0 Change-Id: Ic8eb8c7b25f1b2b6bdb6b645816342748b181bd0 Reviewed-by: Eike Ziller --- src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h index fb86bc1f942..dbccc365506 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h @@ -58,12 +58,12 @@ public: bool isSupportedVersion() const { - return majorNumber == 3 && minorNumber == 8; + return majorNumber == 3 && minorNumber == 9; } static QString supportedVersionAsString() { - return QLatin1String("3.8"); + return QLatin1String("3.9"); } QString toString() const From fd1d10987c60e369a5347ff4c9f28f6c0087fc10 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 22 Sep 2016 15:21:34 +0200 Subject: [PATCH 15/33] Clang: Require LLVM >= 3.9.0 We already ship with a cherry-picked change from version 3.9. Change-Id: Iad09ac8db470506c5de0321f3a2346c549b11b31 Reviewed-by: Marco Bubke Reviewed-by: Eike Ziller --- README.md | 2 +- doc/src/editors/creator-clang-codemodel.qdoc | 2 +- qbs/modules/libclang/functions.js | 4 ++-- src/shared/clang/clang_installation.pri | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ef348fb758b..ab907a13ed6 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Prerequisites: * cmake * On Mac OS X: latest Xcode * On Linux: g++ 4.8 or later -* LLVM 3.8.0 or later (optional, needed for the Clang Code Model) +* LLVM 3.9.0 or later (optional, needed for the Clang Code Model) The installed toolchains have to match the one Qt was compiled with. diff --git a/doc/src/editors/creator-clang-codemodel.qdoc b/doc/src/editors/creator-clang-codemodel.qdoc index dbf90235c55..52b506ecf3d 100644 --- a/doc/src/editors/creator-clang-codemodel.qdoc +++ b/doc/src/editors/creator-clang-codemodel.qdoc @@ -132,7 +132,7 @@ \list 1 - \li Acquire Clang 3.8.0 or higher in one of the following ways: + \li Acquire Clang 3.9.0 or higher in one of the following ways: \list diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js index 49f2512423d..5ad07af8fa6 100644 --- a/qbs/modules/libclang/functions.js +++ b/qbs/modules/libclang/functions.js @@ -1,7 +1,7 @@ var Environment = loadExtension("qbs.Environment") var File = loadExtension("qbs.File") var FileInfo = loadExtension("qbs.FileInfo") -var MinimumLLVMVersion = "3.8.0" +var MinimumLLVMVersion = "3.9.0" var Process = loadExtension("qbs.Process") function readOutput(executable, args) @@ -28,7 +28,7 @@ function llvmConfig(qbs, qtcFunctions) { var llvmInstallDirFromEnv = Environment.getEnv("LLVM_INSTALL_DIR") var llvmConfigVariants = [ - "llvm-config", "llvm-config-3.8", "llvm-config-3.9", "llvm-config-4.0", "llvm-config-4.1" + "llvm-config", "llvm-config-3.9", "llvm-config-4.0", "llvm-config-4.1" ]; // Prefer llvm-config* from LLVM_INSTALL_DIR diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri index a1a0fbb0920..9c7c3ce85fe 100644 --- a/src/shared/clang/clang_installation.pri +++ b/src/shared/clang/clang_installation.pri @@ -96,8 +96,8 @@ LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS contains(QMAKE_DEFAULT_INCDIRS, $$LLVM_INCLUDEPATH): LLVM_INCLUDEPATH = isEmpty(LLVM_VERSION): error("Cannot determine clang version at $$LLVM_INSTALL_DIR") -!versionIsAtLeast($$LLVM_VERSION, 3, 8, 0): { - error("LLVM/Clang version >= 3.8.0 required, version provided: $$LLVM_VERSION") +!versionIsAtLeast($$LLVM_VERSION, 3, 9, 0): { + error("LLVM/Clang version >= 3.9.0 required, version provided: $$LLVM_VERSION") } unix:LLVM_CXXFLAGS = -fno-rtti -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS From 745fc302771766ed04311791b8f8346f273bbd89 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 15 Nov 2016 11:57:12 +0100 Subject: [PATCH 16/33] CppEditor: Fix null pointer access Task-number: QTCREATORBUG-17253 Change-Id: Ide3d15508a2e310c307fef68457848e869c4d2de Reviewed-by: David Schulz --- src/plugins/cppeditor/cppquickfixes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 6fd02fd873a..a4382a3d849 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -4817,7 +4817,7 @@ void MoveFuncDefOutside::match(const CppQuickFixInterface &interface, QuickFixOp } } - if (!funcAST) + if (!funcAST || !funcAST->symbol) return; bool isHeaderFile = false; From 757153fce540d9c08cd3c7e9eedfbaf7fbe91857 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 11 Nov 2016 15:46:27 +0100 Subject: [PATCH 17/33] ProjectExplorer: Don't show context menu when it makes no sense Task-number: QTCREATORBUG-17152 Change-Id: Ic67386bdfd6d6d79e8a15bc6394a22cb46305335 Reviewed-by: Tobias Hunger --- src/plugins/projectexplorer/projectwindow.cpp | 12 +++--------- src/plugins/projectexplorer/projectwindow.h | 1 - 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp index 328f2591904..b1642c91b07 100644 --- a/src/plugins/projectexplorer/projectwindow.cpp +++ b/src/plugins/projectexplorer/projectwindow.cpp @@ -518,6 +518,9 @@ public: ProjectWindow::ProjectWindow() { setBackgroundRole(QPalette::Base); + + // Request custom context menu but do not provide any to avoid + // the creation of the dock window selection menu. setContextMenuPolicy(Qt::CustomContextMenu); auto selectorModel = new SelectorModel(this, [this](QWidget *panel) { setPanel(panel); }); @@ -553,15 +556,6 @@ ProjectWindow::ProjectWindow() auto selectorDock = addDockForWidget(selectorView, true); addDockWidget(Qt::LeftDockWidgetArea, selectorDock); - - connect(this, &QWidget::customContextMenuRequested, - selectorModel, &SelectorModel::openContextMenu); -} - -void ProjectWindow::contextMenuEvent(QContextMenuEvent *event) -{ - Q_UNUSED(event) - // Do nothing to avoid creation of the dock window selection menu. } void ProjectWindow::setPanel(QWidget *panel) diff --git a/src/plugins/projectexplorer/projectwindow.h b/src/plugins/projectexplorer/projectwindow.h index aa61d412967..87694ad0852 100644 --- a/src/plugins/projectexplorer/projectwindow.h +++ b/src/plugins/projectexplorer/projectwindow.h @@ -56,7 +56,6 @@ public: ProjectWindow(); private: - void contextMenuEvent(QContextMenuEvent *event) override; void setPanel(QWidget *panel); }; From cedf7a012ef7a447809bf039a8c4229329ad5b23 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 19 Oct 2016 11:48:50 +0200 Subject: [PATCH 18/33] QmlDesigner: Adding try catch block Change-Id: I4956b58f1ffd3bfdf0e6b810de1f411ae7d7f8a0 Reviewed-by: Tim Jenssen --- .../navigator/navigatortreemodel.cpp | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 4b891ce6eee..354612a3c24 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -666,20 +666,24 @@ static bool isInLayoutable(NodeAbstractProperty &parentProperty) static void reparentModelNodeToNodeProperty(NodeAbstractProperty &parentProperty, const ModelNode &modelNode) { - if (!modelNode.hasParentProperty() || parentProperty != modelNode.parentProperty()) { - if (isInLayoutable(parentProperty)) { - removePosition(modelNode); - parentProperty.reparentHere(modelNode); - } else { - if (QmlItemNode::isValidQmlItemNode(modelNode)) { - QPointF scenePosition = QmlItemNode(modelNode).instanceScenePosition(); + try { + if (!modelNode.hasParentProperty() || parentProperty != modelNode.parentProperty()) { + if (isInLayoutable(parentProperty)) { + removePosition(modelNode); parentProperty.reparentHere(modelNode); - if (!scenePosition.isNull()) - setScenePosition(modelNode, scenePosition); } else { - parentProperty.reparentHere(modelNode); + if (QmlItemNode::isValidQmlItemNode(modelNode)) { + QPointF scenePosition = QmlItemNode(modelNode).instanceScenePosition(); + parentProperty.reparentHere(modelNode); + if (!scenePosition.isNull()) + setScenePosition(modelNode, scenePosition); + } else { + parentProperty.reparentHere(modelNode); + } } } + } catch (const RewritingException &exception) { //better safe than sorry! There always might be cases where we fail + exception.showException(); } } From 37076e8c33aaf7c965446a31d38e371fc34eea87 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 14 Nov 2016 15:26:04 +0100 Subject: [PATCH 19/33] Reduce thread priority for test parsing Adding API for that to the parallel map/reduce functions Change-Id: Ic7987d899c124dcb04c1ca110b09fc97576873fe Reviewed-by: Christian Stenger --- src/libs/utils/mapreduce.h | 60 ++++++++++++++++--------- src/plugins/autotest/testcodeparser.cpp | 3 +- tests/auto/mapreduce/tst_mapreduce.cpp | 2 +- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/libs/utils/mapreduce.h b/src/libs/utils/mapreduce.h index 828b16b31f9..607ff5951aa 100644 --- a/src/libs/utils/mapreduce.h +++ b/src/libs/utils/mapreduce.h @@ -369,9 +369,12 @@ template mapReduce(ForwardIterator begin, ForwardIterator end, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, - MapReduceOption option = MapReduceOption::Unordered, int size = -1) + MapReduceOption option = MapReduceOption::Unordered, + QThread::Priority priority = QThread::InheritPriority, + int size = -1) { - return runAsync(Internal::blockingIteratorMapReduce< + return runAsync(priority, + Internal::blockingIteratorMapReduce< ForwardIterator, typename std::decay::type, typename std::decay::type, @@ -438,9 +441,11 @@ template mapReduce(Container &&container, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, - MapReduceOption option = MapReduceOption::Unordered) + MapReduceOption option = MapReduceOption::Unordered, + QThread::Priority priority = QThread::InheritPriority) { - return runAsync(Internal::blockingContainerMapReduce< + return runAsync(priority, + Internal::blockingContainerMapReduce< typename std::decay::type, typename std::decay::type, typename std::decay::type, @@ -458,9 +463,11 @@ template mapReduce(std::reference_wrapper containerWrapper, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, - MapReduceOption option = MapReduceOption::Unordered) + MapReduceOption option = MapReduceOption::Unordered, + QThread::Priority priority = QThread::InheritPriority) { - return runAsync(Internal::blockingContainerRefMapReduce< + return runAsync(priority, + Internal::blockingContainerRefMapReduce< Container, typename std::decay::type, typename std::decay::type, @@ -478,14 +485,15 @@ template ::type> QFuture mapReduce(ForwardIterator begin, ForwardIterator end, MapFunction &&map, State &&initialState, - ReduceFunction &&reduce, MapReduceOption option = MapReduceOption::Unordered, int size = -1) + ReduceFunction &&reduce, MapReduceOption option = MapReduceOption::Unordered, + QThread::Priority priority = QThread::InheritPriority, int size = -1) { return mapReduce(begin, end, Internal::StateWrapper(std::forward(initialState)), std::forward(map), Internal::ReduceWrapper(std::forward(reduce)), &Internal::cleanupReportingState, - option, size); + option, priority, size); } template ::type> QFuture mapReduce(Container &&container, MapFunction &&map, State &&initialState, ReduceFunction &&reduce, - MapReduceOption option = MapReduceOption::Unordered) + MapReduceOption option = MapReduceOption::Unordered, + QThread::Priority priority = QThread::InheritPriority) { return mapReduce(std::forward(container), Internal::StateWrapper(std::forward(initialState)), std::forward(map), Internal::ReduceWrapper(std::forward(reduce)), &Internal::cleanupReportingState, - option); + option, priority); } template (map), std::forward(initialState), std::forward(reduce), - option, size).result(); + option, priority, size).result(); } template (container), std::forward(map), std::forward(initialState), std::forward(reduce), - option).result(); + option, priority).result(); } template ::type> QFuture map(ForwardIterator begin, ForwardIterator end, MapFunction &&map, - MapReduceOption option = MapReduceOption::Ordered, int size = -1) + MapReduceOption option = MapReduceOption::Ordered, + QThread::Priority priority = QThread::InheritPriority, int size = -1) { return mapReduce(begin, end, &Internal::dummyInit, std::forward(map), Internal::DummyReduce(), &Internal::dummyCleanup, - option, size); + option, priority, size); } template ::type> QFuture -map(Container &&container, MapFunction &&map, MapReduceOption option = MapReduceOption::Ordered) +map(Container &&container, MapFunction &&map, MapReduceOption option = MapReduceOption::Ordered, + QThread::Priority priority = QThread::InheritPriority) { return mapReduce(std::forward(container), Internal::dummyInit, std::forward(map), Internal::DummyReduce(), Internal::dummyCleanup, - option); + option, priority); } template class ResultContainer, typename ForwardIterator, typename MapFunction, @@ -562,11 +575,12 @@ template class ResultContainer, typename ForwardIterator, ty Q_REQUIRED_RESULT ResultContainer mapped(ForwardIterator begin, ForwardIterator end, MapFunction &&mapFun, - MapReduceOption option = MapReduceOption::Ordered, int size = -1) + MapReduceOption option = MapReduceOption::Ordered, + QThread::Priority priority = QThread::InheritPriority, int size = -1) { return Utils::transform(map(begin, end, std::forward(mapFun), - option, size).results(), + option, priority, size).results(), [](const MapResult &r) { return r; }); } @@ -574,11 +588,13 @@ template class ResultContainer, typename Container, typename typename MapResult = typename Internal::resultType::type> Q_REQUIRED_RESULT ResultContainer -mapped(Container &&container, MapFunction &&mapFun, MapReduceOption option = MapReduceOption::Ordered) +mapped(Container &&container, MapFunction &&mapFun, + MapReduceOption option = MapReduceOption::Ordered, + QThread::Priority priority = QThread::InheritPriority) { return Utils::transform(map(container, std::forward(mapFun), - option).results(), + option, priority).results(), [](const MapResult &r) { return r; }); } diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index dadae37de89..fe4c1132f1e 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -354,7 +354,8 @@ void TestCodeParser::scanForTests(const QStringList &fileList) [this](QFutureInterface &fi, const QString &file) { parseFileForTests(m_testCodeParsers, fi, file); }, - Utils::MapReduceOption::Unordered); + Utils::MapReduceOption::Unordered, + QThread::LowestPriority); m_futureWatcher.setFuture(future); if (list.size() > 5) { Core::ProgressManager::addTask(future, tr("Scanning for Tests"), diff --git a/tests/auto/mapreduce/tst_mapreduce.cpp b/tests/auto/mapreduce/tst_mapreduce.cpp index aaa80de424d..413d8753602 100644 --- a/tests/auto/mapreduce/tst_mapreduce.cpp +++ b/tests/auto/mapreduce/tst_mapreduce.cpp @@ -214,7 +214,7 @@ void tst_MapReduce::map() QCOMPARE(container, QList({4, 10, 2})); Utils::map(container.begin(), container.end(), [](int &x) { x *= 2; }, - Utils::MapReduceOption::Unordered, 3).waitForFinished(); + Utils::MapReduceOption::Unordered, QThread::InheritPriority, 3).waitForFinished(); QCOMPARE(container, QList({8, 20, 4})); } From 45216d5c1a1d68fb75d267a763031c7c175f869b Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 15 Nov 2016 16:28:14 +0100 Subject: [PATCH 20/33] macOS: Fix that some actions still had icon in menu For example when toolbars showed a menu for actions that no longer fit (e.g. open diff viewer, reduce window size until the synchronize and switch view buttons vanish). Use the application flag to disable icons in menus on macOS globally instead of doing that individually on the actions. Change-Id: I3b682f48ee0e866f0f0d5bb0834690937f427d7f Reviewed-by: Alessandro Portale --- src/plugins/coreplugin/actionmanager/actionmanager.cpp | 2 ++ src/plugins/coreplugin/actionmanager/command.cpp | 2 -- src/plugins/coreplugin/editortoolbar.cpp | 6 ------ 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp index e3771101b75..526542a6175 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp +++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp @@ -163,6 +163,8 @@ ActionManager::ActionManager(QObject *parent) { m_instance = this; d = new ActionManagerPrivate; + if (Utils::HostOsInfo::isMacHost()) + QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus); } /*! diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp index 3e737290ae3..cdbbe200e3a 100644 --- a/src/plugins/coreplugin/actionmanager/command.cpp +++ b/src/plugins/coreplugin/actionmanager/command.cpp @@ -306,8 +306,6 @@ static QString msgActionWarning(QAction *newAction, Id id, QAction *oldAction) void Action::addOverrideAction(QAction *action, const Context &context, bool scriptable) { - if (Utils::HostOsInfo::isMacHost()) - action->setIconVisibleInMenu(false); // disallow TextHeuristic menu role, because it doesn't work with translations, // e.g. QTCREATORBUG-13101 if (action->menuRole() == QAction::TextHeuristicRole) diff --git a/src/plugins/coreplugin/editortoolbar.cpp b/src/plugins/coreplugin/editortoolbar.cpp index 466598129f8..de912d6f2c4 100644 --- a/src/plugins/coreplugin/editortoolbar.cpp +++ b/src/plugins/coreplugin/editortoolbar.cpp @@ -159,12 +159,6 @@ EditorToolBar::EditorToolBar(QWidget *parent) : d->m_forwardButton->setDefaultAction(d->m_goForwardAction); - if (Utils::HostOsInfo::isMacHost()) { - d->m_horizontalSplitAction->setIconVisibleInMenu(false); - d->m_verticalSplitAction->setIconVisibleInMenu(false); - d->m_splitNewWindowAction->setIconVisibleInMenu(false); - } - d->m_splitButton->setIcon(Utils::Icons::SPLIT_HORIZONTAL_TOOLBAR.icon()); d->m_splitButton->setToolTip(tr("Split")); d->m_splitButton->setPopupMode(QToolButton::InstantPopup); From 3508a09010623f3be3fed78aedf30bc50b7aa2aa Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 15 Nov 2016 15:58:51 +0100 Subject: [PATCH 21/33] Fix that files could not be dropped onto welcome screen Needs to be implemented in Qt Quick itself nowadays. Task-number: QTCREATORBUG-14194 Change-Id: I0456dc5d86c03672d8b6b8f9c45799851db1b059 Reviewed-by: Thomas Hartmann --- share/qtcreator/welcomescreen/welcomescreen.qml | 10 ++++++++++ src/plugins/welcome/welcomeplugin.cpp | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/share/qtcreator/welcomescreen/welcomescreen.qml b/share/qtcreator/welcomescreen/welcomescreen.qml index 62f3ccee547..36489f8e13b 100644 --- a/share/qtcreator/welcomescreen/welcomescreen.qml +++ b/share/qtcreator/welcomescreen/welcomescreen.qml @@ -33,6 +33,16 @@ Item { property int screenDependHeightDistance: Math.min(50, Math.max(16, height / 30)) + DropArea { + anchors.fill: parent + keys: ["text/uri-list"] + onDropped: { + if ((drop.supportedActions & Qt.CopyAction != 0) + && welcomeMode.openDroppedFiles(drop.urls)) + drop.accept(Qt.CopyAction); + } + } + SideBar { id: sideBar model: pagesModel diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp index 884eeb30db5..bb445eb6361 100644 --- a/src/plugins/welcome/welcomeplugin.cpp +++ b/src/plugins/welcome/welcomeplugin.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -135,6 +136,8 @@ public: QStringList recentProjectsShortcuts() const { return m_recentProjectsShortcuts; } QStringList sessionsShortcuts() const { return m_sessionsShortcuts; } + Q_INVOKABLE bool openDroppedFiles(const QList &urls); + public slots: void setActivePlugin(int pos) { @@ -307,6 +310,18 @@ void WelcomeMode::initPlugins() m_welcomePage->setSource(QUrl::fromLocalFile(path)); } +bool WelcomeMode::openDroppedFiles(const QList &urls) +{ + const QList localUrls = Utils::filtered(urls, &QUrl::isLocalFile); + if (!localUrls.isEmpty()) { + QTimer::singleShot(0, [localUrls]() { + ICore::openFiles(Utils::transform(localUrls, &QUrl::toLocalFile), ICore::SwitchMode); + }); + return true; + } + return false; +} + void WelcomeMode::welcomePluginAdded(QObject *obj) { IWelcomePage *page = qobject_cast(obj); From 5b058ebb34b035f71081921e5c76b09b401fc45a Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 15 Nov 2016 13:31:46 +0100 Subject: [PATCH 22/33] Debugger: Make QRegExp dumper test pass on Mac We need DYLD_IMAGE_SUFFIX=_debug for the captures() cache warming call to succeed even if the actual access is by offset only. Change-Id: I24a90b4c4187459904f14a664b992a5bba9a20eb Reviewed-by: Christian Stenger --- share/qtcreator/debugger/qttypes.py | 1 + tests/auto/debugger/tst_dumpers.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 57a7ed57d07..ed94f51ad36 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -1064,6 +1064,7 @@ def qdump__QRegExp(d, value): privAddress = d.extractPointer(value) (eng, pattern) = d.split('p{QString}', privAddress) d.putStringValue(pattern) + d.putNumChild(1) if d.isExpanded(): with Children(d): d.call('void', value, 'capturedTexts') # Warm up internal cache. diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 851f0d44ecc..1c4f3cb808f 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2755,6 +2755,7 @@ void tst_Dumpers::dumper_data() "int pos1 = re.indexIn(str1); unused(&pos1);\n" "int pos2 = re.indexIn(str2); unused(&pos2);\n") + CoreProfile() + + UseDebugImage() + Check("re", "\"a(.*)b(.*)c\"", "@QRegExp") + Check("re.captures.0", "[0]", "\"a1121b344c\"", "@QString") + Check("re.captures.1", "[1]", "\"1121\"", "@QString") From 80b2a4f1ba6591c68101438f9cd6d62c6e737a14 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 15 Nov 2016 09:22:53 +0100 Subject: [PATCH 23/33] Debugger: Expose DebuggerKitInformation::ConfigurationErrors ... to allow more fine-grained decision making for kit choosers. Change-Id: I9a4e97f7b4f4b074e1c764f6b134c15e2896dc79 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerdialogs.cpp | 4 ++-- .../debugger/debuggerkitinformation.cpp | 21 ++++--------------- src/plugins/debugger/debuggerkitinformation.h | 13 +++++++++++- src/plugins/debugger/debuggerplugin.cpp | 6 +++--- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 416c27eaccd..d950a26b3f8 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -107,7 +107,7 @@ DebuggerKitChooser::DebuggerKitChooser(Mode mode, QWidget *parent) { setKitMatcher([this](const Kit *k) { // Match valid debuggers and restrict local debugging to compatible toolchains. - if (!DebuggerKitInformation::isValidDebugger(k)) + if (DebuggerKitInformation::configurationErrors(k)) return false; if (m_mode == LocalDebugging) return ToolChainKitInformation::targetAbi(k).os() == m_hostAbi.os(); @@ -223,7 +223,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent) d->kitChooser = new KitChooser(this); d->kitChooser->setKitMatcher([this](const Kit *k) { - return DebuggerKitInformation::isValidDebugger(k); + return !DebuggerKitInformation::configurationErrors(k); }); d->kitChooser->populate(); diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp index 6aaaa4074cb..115e630dfb1 100644 --- a/src/plugins/debugger/debuggerkitinformation.cpp +++ b/src/plugins/debugger/debuggerkitinformation.cpp @@ -191,15 +191,7 @@ void DebuggerKitInformation::fix(Kit *k) // Check the configuration errors and return a flag mask. Provide a quick check and // a verbose one with a list of errors. -enum DebuggerConfigurationErrors { - NoDebugger = 0x1, - DebuggerNotFound = 0x2, - DebuggerNotExecutable = 0x4, - DebuggerNeedsAbsolutePath = 0x8, - DebuggerDoesNotMatch = 0x10 -}; - -static unsigned debuggerConfigurationErrors(const Kit *k) +DebuggerKitInformation::ConfigurationErrors DebuggerKitInformation::configurationErrors(const Kit *k) { QTC_ASSERT(k, return NoDebugger); @@ -210,7 +202,7 @@ static unsigned debuggerConfigurationErrors(const Kit *k) if (item->command().isEmpty()) return NoDebugger; - unsigned result = 0; + ConfigurationErrors result = NoConfigurationError; const QFileInfo fi = item->command().toFileInfo(); if (!fi.exists() || fi.isDir()) result |= DebuggerNotFound; @@ -257,17 +249,12 @@ StandardRunnable DebuggerKitInformation::runnable(const Kit *kit) return runnable; } -bool DebuggerKitInformation::isValidDebugger(const Kit *k) -{ - return debuggerConfigurationErrors(k) == 0; -} - QList DebuggerKitInformation::validateDebugger(const Kit *k) { QList result; - const unsigned errors = debuggerConfigurationErrors(k); - if (!errors) + const ConfigurationErrors errors = configurationErrors(k); + if (errors == NoConfigurationError) return result; QString path; diff --git a/src/plugins/debugger/debuggerkitinformation.h b/src/plugins/debugger/debuggerkitinformation.h index cae68aaf5ae..cbe438e3f56 100644 --- a/src/plugins/debugger/debuggerkitinformation.h +++ b/src/plugins/debugger/debuggerkitinformation.h @@ -52,8 +52,19 @@ public: static const DebuggerItem *debugger(const ProjectExplorer::Kit *kit); static ProjectExplorer::StandardRunnable runnable(const ProjectExplorer::Kit *kit); + enum ConfigurationError + { + NoConfigurationError = 0x0, + NoDebugger = 0x1, + DebuggerNotFound = 0x2, + DebuggerNotExecutable = 0x4, + DebuggerNeedsAbsolutePath = 0x8, + DebuggerDoesNotMatch = 0x10 + }; + Q_DECLARE_FLAGS(ConfigurationErrors, ConfigurationError) + static QList validateDebugger(const ProjectExplorer::Kit *k); - static bool isValidDebugger(const ProjectExplorer::Kit *k); + static ConfigurationErrors configurationErrors(const ProjectExplorer::Kit *k); ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const override; void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index bdc94011a13..6437643f512 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -583,7 +583,7 @@ static std::function cdbMatcher(char wordWidth = 0) { return [wordWidth](const Kit *k) -> bool { if (DebuggerKitInformation::engineType(k) != CdbEngineType - || !DebuggerKitInformation::isValidDebugger(k)) { + || DebuggerKitInformation::configurationErrors(k)) { return false; } if (wordWidth) @@ -1125,13 +1125,13 @@ static Kit *guessKitFromParameters(const DebuggerRunParameters &rp) // Try exact abis. kit = KitManager::find(KitMatcher([abis](const Kit *k) -> bool { const Abi tcAbi = ToolChainKitInformation::targetAbi(k); - return abis.contains(tcAbi) && DebuggerKitInformation::isValidDebugger(k); + return abis.contains(tcAbi) && !DebuggerKitInformation::configurationErrors(k); })); if (!kit) { // Or something compatible. kit = KitManager::find(KitMatcher([abis](const Kit *k) -> bool { const Abi tcAbi = ToolChainKitInformation::targetAbi(k); - return DebuggerKitInformation::isValidDebugger(k) + return !DebuggerKitInformation::configurationErrors(k) && Utils::contains(abis, [tcAbi](const Abi &a) { return a.isCompatibleWith(tcAbi); }); })); } From 88ff6cd5ae1f6de7674c63c3b850cb7282fc93c3 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 15 Nov 2016 11:56:18 +0100 Subject: [PATCH 24/33] Debugger: Use a more direct way to detect LLDB bitfields It has a function directly doing that, use it instead of guessing (badly, in some cases) Change-Id: I1ce317c28d60f820f8e868e3c0c5a665f8de6cb7 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/lldbbridge.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 51b9ce1babd..5f257fb324d 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -247,7 +247,7 @@ class Dumper(DumperBase): if bitsize > 0: #bitpos = bitpos % bitsize bitpos = bitpos % 8 # Reported type is always wrapping type! - fieldBits[f.name] = (bitsize, bitpos) + fieldBits[f.name] = (bitsize, bitpos, f.IsBitfield()) # Normal members and non-empty base classes. for i in range(fakeValue.GetNumChildren()): @@ -259,11 +259,12 @@ class Dumper(DumperBase): nativeFieldType = nativeField.GetType() if field.name in fieldBits: - (field.lbitsize, field.lbitpos) = fieldBits[field.name] + (field.lbitsize, field.lbitpos, isBitfield) = fieldBits[field.name] else: field.lbitsize = nativeFieldType.GetByteSize() * 8 + isBitfield = False - if field.lbitsize != nativeFieldType.GetByteSize() * 8: + if isBitfield: field.ltype = self.createBitfieldType(self.typeName(nativeFieldType), field.lbitsize) else: fakeMember = fakeValue.GetChildAtIndex(i) From f28cefce8c8b9cd834fa029f36fe01c61541b9c1 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Fri, 4 Nov 2016 17:39:39 +0100 Subject: [PATCH 25/33] iOS: Make iOS simulator usage asynchronous Change-Id: I5770b372542690560680ef3208a284c7f0cf6670 Reviewed-by: Eike Ziller (cherry picked from commit aa355b4f704db3f2d45b674c9532c8425ba47333) --- src/plugins/ios/iostoolhandler.cpp | 327 +++++++++++----- src/plugins/ios/simulatorcontrol.cpp | 553 +++++++++++++++------------ src/plugins/ios/simulatorcontrol.h | 47 ++- 3 files changed, 573 insertions(+), 354 deletions(-) diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index dcbb402e984..3af160caddc 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -33,6 +33,7 @@ #include #include #include +#include "utils/runextensions.h" #include #include @@ -160,10 +161,9 @@ public: protected: void killProcess(); - protected: IosToolHandler *q; - QProcess *process; + std::shared_ptr process; QTimer killTimer; QXmlStreamReader outputParser; QString deviceId; @@ -199,16 +199,63 @@ private: void processXml(); }; +/**************************************************************************** + * Flow to install an app on simulator:- + * +------------------+ + * | Transfer App | + * +--------+---------+ + * | + * v + * +---------+----------+ +--------------------------------+ + * | SimulatorRunning +---No------> +SimulatorControl::startSimulator| + * +---------+----------+ +--------+-----------------------+ + * Yes | + * | | + * v | + * +---------+--------------------+ | + * | SimulatorControl::installApp | <--------------+ + * +------------------------------+ + * + * + * + * Flow to launch an app on Simulator:- + * +---------+ + * | Run App | + * +----+----+ + * | + * v + * +-------------------+ +----------------------------- - --+ + * | SimulatorRunning? +---NO------> + SimulatorControl::startSimulator | + * +--------+----------+ +----------------+-----------------+ + * YES | + * | | + * v | + * +---------+-------------------------+ | + * | SimulatorControl::spawnAppProcess | <------------------+ + * +-----------------------------------+ + * | + * v + * +--------+-----------+ +-----------------------------+ + * | Debug Run ? +---YES------> + Wait for debugger to attach | + * +---------+----------+ +-----------+-----------------+ + * NO | + * | | + * v | + * +-----------------------------+ | + * | SimulatorControl::launchApp | <-------------------+ + * +-----------------------------+ + ***************************************************************************/ class IosSimulatorToolHandlerPrivate : public IosToolHandlerPrivate { public: explicit IosSimulatorToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q); + ~IosSimulatorToolHandlerPrivate(); // IosToolHandlerPrivate overrides public: - void requestTransferApp(const QString &bundlePath, const QString &deviceIdentifier, + void requestTransferApp(const QString &appBundlePath, const QString &deviceIdentifier, int timeout = 1000) override; - void requestRunApp(const QString &bundlePath, const QStringList &extraArgs, + void requestRunApp(const QString &appBundlePath, const QStringList &extraArgs, IosToolHandler::RunKind runKind, const QString &deviceIdentifier, int timeout = 1000) override; void requestDeviceInfo(const QString &deviceId, int timeout = 1000) override; @@ -216,15 +263,23 @@ public: void debuggerStateChanged(Debugger::DebuggerState state) override; private: + void installAppOnSimulator(); + void spawnAppOnSimulator(const QStringList &extraArgs); + void launchAppOnSimulator(); + + bool isResponseValid(const SimulatorControl::ResponseData &responseData); + void onResponseAppSpawn(const SimulatorControl::ResponseData &response); + void simAppProcessError(QProcess::ProcessError error); void simAppProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void simAppProcessHasData(); void simAppProcessHasErrorOutput(); - void launchAppOnSimulator(); private: qint64 appPId = -1; bool appLaunched = false; + SimulatorControl *simCtl; + QList> futureList; }; IosToolHandlerPrivate::IosToolHandlerPrivate(const IosDeviceType &devType, @@ -242,12 +297,6 @@ IosToolHandlerPrivate::IosToolHandlerPrivate(const IosDeviceType &devType, IosToolHandlerPrivate::~IosToolHandlerPrivate() { - if (isRunning()) { - process->terminate(); - if (!process->waitForFinished(1000)) - process->kill(); - } - delete process; } bool IosToolHandlerPrivate::isRunning() @@ -559,7 +608,12 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de IosToolHandler *q) : IosToolHandlerPrivate(devType, q) { - process = new QProcess; + auto deleter = [](QProcess *p) { + p->kill(); + p->waitForFinished(10000); + delete p; + }; + process = std::shared_ptr(new QProcess, deleter); // Prepare & set process Environment. QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); @@ -583,13 +637,13 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de qCDebug(toolHandlerLog) << "IosToolHandler runEnv:" << env.toStringList(); process->setProcessEnvironment(env); - QObject::connect(process, &QProcess::readyReadStandardOutput, + QObject::connect(process.get(), &QProcess::readyReadStandardOutput, std::bind(&IosDeviceToolHandlerPrivate::subprocessHasData,this)); - QObject::connect(process, static_cast(&QProcess::finished), + QObject::connect(process.get(), static_cast(&QProcess::finished), std::bind(&IosDeviceToolHandlerPrivate::subprocessFinished,this, _1,_2)); - QObject::connect(process, &QProcess::errorOccurred, + QObject::connect(process.get(), &QProcess::errorOccurred, std::bind(&IosDeviceToolHandlerPrivate::subprocessError, this, _1)); QObject::connect(&killTimer, &QTimer::timeout, std::bind(&IosDeviceToolHandlerPrivate::killProcess, this)); @@ -685,45 +739,56 @@ void IosDeviceToolHandlerPrivate::stop(int errorCode) IosSimulatorToolHandlerPrivate::IosSimulatorToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q) - : IosToolHandlerPrivate(devType, q) -{ } + : IosToolHandlerPrivate(devType, q), + simCtl(new SimulatorControl) +{ +} -void IosSimulatorToolHandlerPrivate::requestTransferApp(const QString &bundlePath, +IosSimulatorToolHandlerPrivate::~IosSimulatorToolHandlerPrivate() +{ + foreach (auto f, futureList) { + if (!f.isFinished()) + f.cancel(); + } + delete simCtl; +} +void IosSimulatorToolHandlerPrivate::requestTransferApp(const QString &appBundlePath, const QString &deviceIdentifier, int timeout) { Q_UNUSED(timeout); - this->bundlePath = bundlePath; - this->deviceId = deviceIdentifier; + bundlePath = appBundlePath; + deviceId = deviceIdentifier; isTransferringApp(bundlePath, deviceId, 0, 100, ""); - if (SimulatorControl::startSimulator(deviceId)) { - isTransferringApp(bundlePath, deviceId, 20, 100, ""); - QByteArray cmdOutput; - if (SimulatorControl::installApp(deviceId, Utils::FileName::fromString(bundlePath), cmdOutput)) { - isTransferringApp(bundlePath, deviceId, 100, 100, ""); - didTransferApp(bundlePath, deviceId, IosToolHandler::Success); + + auto onSimulatorStart = [this](const SimulatorControl::ResponseData &response) { + if (!isResponseValid(response)) + return; + + if (response.success) { + installAppOnSimulator(); } else { - errorMsg(IosToolHandler::tr("Application install on Simulator failed. %1").arg(QString::fromLocal8Bit(cmdOutput))); + errorMsg(IosToolHandler::tr("Application install on Simulator failed. Simulator not running.")); didTransferApp(bundlePath, deviceId, IosToolHandler::Failure); + emit q->finished(q); } - } else { - errorMsg(IosToolHandler::tr("Application install on Simulator failed. Simulator not running.")); - didTransferApp(bundlePath, deviceId, IosToolHandler::Failure); - } - emit q->finished(q); + }; + + if (SimulatorControl::isSimulatorRunning(deviceId)) + installAppOnSimulator(); + else + futureList << Utils::onResultReady(simCtl->startSimulator(deviceId), onSimulatorStart); } - -void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &bundlePath, +void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &appBundlePath, const QStringList &extraArgs, IosToolHandler::RunKind runType, const QString &deviceIdentifier, int timeout) { Q_UNUSED(timeout); Q_UNUSED(deviceIdentifier); - this->bundlePath = bundlePath; - this->deviceId = devType.identifier; - this->runKind = runType; - op = OpAppRun; + bundlePath = appBundlePath; + deviceId = devType.identifier; + runKind = runType; Utils::FileName appBundle = Utils::FileName::fromString(bundlePath); if (!appBundle.exists()) { @@ -733,62 +798,22 @@ void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &bundlePath, return; } - if (SimulatorControl::startSimulator(deviceId)) { - qint64 pId = -1; - bool debugRun = runType == IosToolHandler::DebugRun; - QProcess* controlProcess = SimulatorControl::spawnAppProcess(deviceId, appBundle, pId, debugRun, extraArgs); - if (controlProcess) { - Q_ASSERT(!process || !isRunning()); - if (process) { - delete process; - process = nullptr; - } - process = controlProcess; - QObject::connect(process, &QProcess::readyReadStandardOutput, - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasData,this)); - QObject::connect(process, &QProcess::readyReadStandardError, - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasErrorOutput,this)); - QObject::connect(process, static_cast(&QProcess::finished), - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessFinished,this, _1,_2)); - QObject::connect(process, &QProcess::errorOccurred, - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessError, this, _1)); - - appPId = pId; - gotInferiorPid(bundlePath,deviceId,pId); - - // For debug run, wait for the debugger to attach and then launch the app. - if (!debugRun) { - launchAppOnSimulator(); - } + auto onSimulatorStart = [this, extraArgs] (const SimulatorControl::ResponseData &response) { + if (isResponseValid(response)) + return; + if (response.success) { + spawnAppOnSimulator(extraArgs); } else { - errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed.")); + errorMsg(IosToolHandler::tr("Application launch on Simulator failed. Simulator not running.") + .arg(bundlePath)); didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); } - } else { - errorMsg(IosToolHandler::tr("Application launch on Simulator failed. Simulator not running.") - .arg(bundlePath)); - didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); - } -} + }; -void IosSimulatorToolHandlerPrivate::launchAppOnSimulator() -{ - // Wait for the app to reach a state when we can launch it on the simulator. - if (appPId != -1 && SimulatorControl::waitForProcessSpawn(appPId)) { - QByteArray commandOutput; - Utils::FileName appBundle = Utils::FileName::fromString(bundlePath); - if (SimulatorControl::launchApp(deviceId, SimulatorControl::bundleIdentifier(appBundle), &commandOutput) != -1) { - appLaunched = true; - didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Success); - } else { - errorMsg(IosToolHandler::tr("Application launch on Simulator failed. %1") - .arg(QString::fromLocal8Bit(commandOutput))); - didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); - } - } else { - errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed. Spawning timed out.")); - didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); - } + if (SimulatorControl::isSimulatorRunning(deviceId)) + spawnAppOnSimulator(extraArgs); + else + futureList << Utils::onResultReady(simCtl->startSimulator(deviceId), onSimulatorStart); } void IosSimulatorToolHandlerPrivate::requestDeviceInfo(const QString &deviceId, int timeout) @@ -799,19 +824,21 @@ void IosSimulatorToolHandlerPrivate::requestDeviceInfo(const QString &deviceId, void IosSimulatorToolHandlerPrivate::stop(int errorCode) { + if (process) { - if (isRunning()) { - process->terminate(); - if (!process->waitForFinished(1000)) - process->kill(); - } - process->deleteLater(); - process = nullptr; + QTC_ASSERT(process.unique(), process->kill(); qCDebug(toolHandlerLog)<<"App process is not unique."); + process.reset(); appPId = -1; appLaunched = false; } + foreach (auto f, futureList) { + if (!f.isFinished()) + f.cancel(); + } + toolExited(errorCode); + q->finished(q); } void IosSimulatorToolHandlerPrivate::debuggerStateChanged(Debugger::DebuggerState state) @@ -822,6 +849,112 @@ void IosSimulatorToolHandlerPrivate::debuggerStateChanged(Debugger::DebuggerStat } } +void IosSimulatorToolHandlerPrivate::installAppOnSimulator() +{ + auto onResponseAppInstall = [this](const SimulatorControl::ResponseData &response) { + if (!isResponseValid(response)) + return; + + if (response.success) { + isTransferringApp(bundlePath, deviceId, 100, 100, ""); + didTransferApp(bundlePath, deviceId, IosToolHandler::Success); + } else { + errorMsg(IosToolHandler::tr("Application install on Simulator failed. %1") + .arg(QString::fromLocal8Bit(response.commandOutput))); + didTransferApp(bundlePath, deviceId, IosToolHandler::Failure); + } + emit q->finished(q); + }; + + isTransferringApp(bundlePath, deviceId, 20, 100, ""); + futureList << Utils::onResultReady(simCtl->installApp(deviceId, Utils::FileName::fromString(bundlePath)), + onResponseAppInstall); +} + +void IosSimulatorToolHandlerPrivate::spawnAppOnSimulator(const QStringList &extraArgs) +{ + Utils::FileName appBundle = Utils::FileName::fromString(bundlePath); + bool debugRun = runKind == IosToolHandler::DebugRun; + futureList << Utils::onResultReady(simCtl->spawnAppProcess(deviceId, appBundle, debugRun, extraArgs), + std::bind(&IosSimulatorToolHandlerPrivate::onResponseAppSpawn, this, _1)); +} + +void IosSimulatorToolHandlerPrivate::launchAppOnSimulator() +{ + auto onResponseAppLaunch = [this](const SimulatorControl::ResponseData &response) { + if (!isResponseValid(response)) + return; + + if (response.pID != -1) { + appLaunched = true; + didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Success); + } else { + errorMsg(IosToolHandler::tr("Application launch on Simulator failed. %1") + .arg(QString::fromLocal8Bit(response.commandOutput))); + didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); + stop(-1); + q->finished(q); + } + }; + + if (appPId != -1) { + Utils::FileName appBundle = Utils::FileName::fromString(bundlePath); + futureList << Utils::onResultReady(simCtl->launchApp(deviceId, + SimulatorControl::bundleIdentifier(appBundle), appPId), + onResponseAppLaunch); + } else { + errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed. Spawning timed out.")); + didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); + } +} + +bool IosSimulatorToolHandlerPrivate::isResponseValid(const SimulatorControl::ResponseData &responseData) +{ + if (responseData.simUdid.compare(deviceId) != 0) { + errorMsg(IosToolHandler::tr("Invalid simulator response. Device Id mismatch. " + "Device Id = %1 Response Id = %2") + .arg(responseData.simUdid) + .arg(deviceId)); + emit q->finished(q); + return false; + } + return true; +} + +void IosSimulatorToolHandlerPrivate::onResponseAppSpawn(const SimulatorControl::ResponseData &response) +{ + if (!isResponseValid(response)) + return; + + if (response.processInstance) { + QTC_ASSERT(!process || !isRunning(), + qCDebug(toolHandlerLog) << "Spwaning app while an app instance exits."); + process = response.processInstance; + QObject::connect(process.get(), &QProcess::readyReadStandardOutput, + std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasData, this)); + QObject::connect(process.get(), &QProcess::readyReadStandardError, + std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasErrorOutput, this)); + QObject::connect(process.get(), static_cast(&QProcess::finished), + std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessFinished, this, _1, _2)); + QObject::connect(process.get(), &QProcess::errorOccurred, + std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessError, this, _1)); + + appPId = response.pID; + gotInferiorPid(bundlePath, deviceId, appPId); + + // For normal run. Launch app on Simulator. + // For debug run, wait for the debugger to attach and then launch the app. + if (runKind == IosToolHandler::NormalRun) + launchAppOnSimulator(); + } else { + errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed. %1") + .arg(QString::fromLocal8Bit(response.commandOutput))); + didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); + stop(-1); + q->finished(q); + } +} + void IosSimulatorToolHandlerPrivate::simAppProcessError(QProcess::ProcessError error) { errorMsg(IosToolHandler::tr("Simulator application process error %1").arg(error)); diff --git a/src/plugins/ios/simulatorcontrol.cpp b/src/plugins/ios/simulatorcontrol.cpp index 6746c27d789..4af05f00e3d 100644 --- a/src/plugins/ios/simulatorcontrol.cpp +++ b/src/plugins/ios/simulatorcontrol.cpp @@ -27,13 +27,16 @@ #include "iossimulator.h" #include "iosconfigurations.h" -#include +#include "utils/runextensions.h" +#include "utils/qtcassert.h" +#include "utils/synchronousprocess.h" #ifdef Q_OS_MAC #include #endif #include +#include #include #include @@ -47,6 +50,8 @@ #include #include +using namespace std; + namespace { Q_LOGGING_CATEGORY(simulatorLog, "qtc.ios.simulator") } @@ -55,29 +60,61 @@ namespace Ios { namespace Internal { static int COMMAND_TIMEOUT = 10000; -static int SIMULATOR_TIMEOUT = 60000; +static int SIMULATOR_START_TIMEOUT = 60000; +static QString SIM_UDID_TAG = QStringLiteral("SimUdid"); -static bool checkForTimeout(const std::chrono::time_point< std::chrono::high_resolution_clock, std::chrono::nanoseconds> &start, int msecs = COMMAND_TIMEOUT) +static bool checkForTimeout(const chrono::time_point< chrono::high_resolution_clock, chrono::nanoseconds> &start, int msecs = COMMAND_TIMEOUT) { bool timedOut = false; - auto end = std::chrono::high_resolution_clock::now(); - if (std::chrono::duration_cast(end-start).count() > msecs) + auto end = chrono::high_resolution_clock::now(); + if (chrono::duration_cast(end-start).count() > msecs) timedOut = true; return timedOut; } -static QByteArray runSimCtlCommand(QStringList args) +static bool runCommand(QString command, const QStringList &args, QByteArray *output) { - QProcess simCtlProcess; - args.prepend(QStringLiteral("simctl")); - simCtlProcess.start(QStringLiteral("xcrun"), args, QProcess::ReadOnly); - if (!simCtlProcess.waitForFinished()) - qCDebug(simulatorLog) << "simctl command failed." << simCtlProcess.errorString(); - return simCtlProcess.readAll(); + Utils::SynchronousProcess p; + Utils::SynchronousProcessResponse resp = p.runBlocking(command, args); + if (output) + *output = resp.allRawOutput(); + return resp.result == Utils::SynchronousProcessResponse::Finished; } -class SimulatorControlPrivate :QObject { - Q_OBJECT +static QByteArray runSimCtlCommand(QStringList args) +{ + QByteArray output; + args.prepend(QStringLiteral("simctl")); + runCommand(QStringLiteral("xcrun"), args, &output); + return output; +} + +static bool waitForProcessSpawn(qint64 processPId, QFutureInterface &fi) +{ + bool success = false; + if (processPId != -1) { + // Wait for app to reach intruptible sleep state. + const QStringList args = {QStringLiteral("-p"), QString::number(processPId), + QStringLiteral("-o"), QStringLiteral("wq=")}; + int wqCount = -1; + QByteArray wqStr; + auto begin = chrono::high_resolution_clock::now(); + do { + if (fi.isCanceled() || !runCommand(QStringLiteral("ps"), args, &wqStr)) + break; + bool validInt = false; + wqCount = wqStr.trimmed().toInt(&validInt); + if (!validInt) + wqCount = -1; + } while (wqCount < 0 && !checkForTimeout(begin)); + success = wqCount >= 0; + } else { + qCDebug(simulatorLog) << "Wait for spawned failed. Invalid Process ID." << processPId; + } + return success; +} + +class SimulatorControlPrivate { private: struct SimDeviceInfo { bool isBooted() const { return state.compare(QStringLiteral("Booted")) == 0; } @@ -89,27 +126,40 @@ private: QString sdk; }; - SimulatorControlPrivate(QObject *parent = nullptr); + SimulatorControlPrivate(); ~SimulatorControlPrivate(); - SimDeviceInfo deviceInfo(const QString &simUdid) const; - bool runCommand(QString command, const QStringList &args, QByteArray *output = nullptr); - QHash simulatorProcesses; - QReadWriteLock processDataLock; - QList availableDevices; + static SimDeviceInfo deviceInfo(const QString &simUdid); + static QString bundleIdentifier(const Utils::FileName &bundlePath); + static QString bundleExecutable(const Utils::FileName &bundlePath); + + void startSimulator(QFutureInterface &fi, const QString &simUdid); + void installApp(QFutureInterface &fi, const QString &simUdid, + const Utils::FileName &bundlePath); + void spawnAppProcess(QFutureInterface &fi, const QString &simUdid, + const Utils::FileName &bundlePath, bool waitForDebugger, QStringList extraArgs, + QThread *mainThread); + void launchApp(QFutureInterface &fi, const QString &simUdid, + const QString &bundleIdentifier, qint64 spawnedPID); + + static QList availableDevices; friend class SimulatorControl; }; -SimulatorControlPrivate *SimulatorControl::d = new SimulatorControlPrivate; - -SimulatorControl::SimulatorControl() +SimulatorControl::SimulatorControl(QObject *parent) : + QObject(parent), + d(new SimulatorControlPrivate) { +} +SimulatorControl::~SimulatorControl() +{ + delete d; } QList SimulatorControl::availableSimulators() { - return d->availableDevices; + return SimulatorControlPrivate::availableDevices; } static QList getAvailableSimulators() @@ -133,7 +183,7 @@ static QList getAvailableSimulators() } } } - std::stable_sort(availableDevices.begin(), availableDevices.end()); + stable_sort(availableDevices.begin(), availableDevices.end()); } else { qCDebug(simulatorLog) << "Error parsing json output from simctl. Output:" << output; } @@ -142,133 +192,59 @@ static QList getAvailableSimulators() void SimulatorControl::updateAvailableSimulators() { - QFuture> future = Utils::runAsync(getAvailableSimulators); - Utils::onResultReady(future, d, [](const QList &devices) { - SimulatorControl::d->availableDevices = devices; + QFuture< QList > future = Utils::runAsync(getAvailableSimulators); + Utils::onResultReady(future, [](const QList &devices) { + SimulatorControlPrivate::availableDevices = devices; }); } -// Blocks until simulators reaches "Booted" state. -bool SimulatorControl::startSimulator(const QString &simUdid) -{ - QWriteLocker locker(&d->processDataLock); - bool simulatorRunning = isSimulatorRunning(simUdid); - if (!simulatorRunning && d->deviceInfo(simUdid).isAvailable()) { - // Simulator is not running but it's available. Start the simulator. - QProcess *p = new QProcess; - QObject::connect(p, static_cast(&QProcess::finished), [simUdid]() { - QWriteLocker locker(&d->processDataLock); - d->simulatorProcesses[simUdid]->deleteLater(); - d->simulatorProcesses.remove(simUdid); - }); - - const QString cmd = IosConfigurations::developerPath().appendPath(QStringLiteral("/Applications/Simulator.app")).toString(); - const QStringList args({QStringLiteral("--args"), QStringLiteral("-CurrentDeviceUDID"), simUdid}); - p->start(cmd, args); - - if (p->waitForStarted()) { - d->simulatorProcesses[simUdid] = p; - // At this point the sim device exists, available and was not running. - // So the simulator is started and we'll wait for it to reach to a state - // where we can interact with it. - auto start = std::chrono::high_resolution_clock::now(); - SimulatorControlPrivate::SimDeviceInfo info; - do { - info = d->deviceInfo(simUdid); - } while (!info.isBooted() - && p->state() == QProcess::Running - && !checkForTimeout(start, SIMULATOR_TIMEOUT)); - simulatorRunning = info.isBooted(); - } else { - qCDebug(simulatorLog) << "Error starting simulator." << p->errorString(); - delete p; - } - } - return simulatorRunning; -} - bool SimulatorControl::isSimulatorRunning(const QString &simUdid) { if (simUdid.isEmpty()) return false; - return d->deviceInfo(simUdid).isBooted(); -} - -bool SimulatorControl::installApp(const QString &simUdid, const Utils::FileName &bundlePath, QByteArray &commandOutput) -{ - bool installed = false; - if (isSimulatorRunning(simUdid)) { - commandOutput = runSimCtlCommand(QStringList() << QStringLiteral("install") << simUdid << bundlePath.toString()); - installed = commandOutput.isEmpty(); - } else { - commandOutput = "Simulator device not running."; - } - return installed; -} - -qint64 SimulatorControl::launchApp(const QString &simUdid, const QString &bundleIdentifier, QByteArray* commandOutput) -{ - qint64 pId = -1; - pId = -1; - if (!bundleIdentifier.isEmpty() && isSimulatorRunning(simUdid)) { - const QStringList args({QStringLiteral("launch"), simUdid , bundleIdentifier}); - const QByteArray output = runSimCtlCommand(args); - const QByteArray pIdStr = output.trimmed().split(' ').last().trimmed(); - bool validInt = false; - pId = pIdStr.toLongLong(&validInt); - if (!validInt) { - // Launch Failed. - qCDebug(simulatorLog) << "Launch app failed. Process id returned is not valid. PID =" << pIdStr; - pId = -1; - if (commandOutput) - *commandOutput = output; - } - } - return pId; + return SimulatorControlPrivate::deviceInfo(simUdid).isBooted(); } QString SimulatorControl::bundleIdentifier(const Utils::FileName &bundlePath) { - QString bundleID; -#ifdef Q_OS_MAC - if (bundlePath.exists()) { - CFStringRef cFBundlePath = bundlePath.toString().toCFString(); - CFURLRef bundle_url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, cFBundlePath, kCFURLPOSIXPathStyle, true); - CFRelease(cFBundlePath); - CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, bundle_url); - CFRelease(bundle_url); - CFStringRef cFBundleID = CFBundleGetIdentifier(bundle); - bundleID = QString::fromCFString(cFBundleID).trimmed(); - CFRelease(bundle); - } -#else - Q_UNUSED(bundlePath) -#endif - return bundleID; + return SimulatorControlPrivate::bundleIdentifier(bundlePath); } QString SimulatorControl::bundleExecutable(const Utils::FileName &bundlePath) { - QString executable; -#ifdef Q_OS_MAC - if (bundlePath.exists()) { - CFStringRef cFBundlePath = bundlePath.toString().toCFString(); - CFURLRef bundle_url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, cFBundlePath, kCFURLPOSIXPathStyle, true); - CFRelease(cFBundlePath); - CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, bundle_url); - CFStringRef cFStrExecutableName = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleExecutableKey); - executable = QString::fromCFString(cFStrExecutableName).trimmed(); - CFRelease(bundle); - } -#else - Q_UNUSED(bundlePath) -#endif - return executable; + return SimulatorControlPrivate::bundleExecutable(bundlePath); } -SimulatorControlPrivate::SimulatorControlPrivate(QObject *parent): - QObject(parent), - processDataLock(QReadWriteLock::Recursive) +QFuture SimulatorControl::startSimulator(const QString &simUdid) +{ + return Utils::runAsync(&SimulatorControlPrivate::startSimulator, d, simUdid); +} + +QFuture +SimulatorControl::installApp(const QString &simUdid, const Utils::FileName &bundlePath) const +{ + return Utils::runAsync(&SimulatorControlPrivate::installApp, d, simUdid, bundlePath); +} + +QFuture +SimulatorControl::spawnAppProcess(const QString &simUdid, const Utils::FileName &bundlePath, + bool waitForDebugger, const QStringList &extraArgs) const +{ + return Utils::runAsync(&SimulatorControlPrivate::spawnAppProcess, d, simUdid, bundlePath, + waitForDebugger, extraArgs, QThread::currentThread()); +} + +QFuture +SimulatorControl::launchApp(const QString &simUdid, const QString &bundleIdentifier, + qint64 spawnedPID) const +{ + return Utils::runAsync(&SimulatorControlPrivate::launchApp, d, simUdid, + bundleIdentifier, spawnedPID); +} + +QList SimulatorControlPrivate::availableDevices; + +SimulatorControlPrivate::SimulatorControlPrivate() { } @@ -277,107 +253,11 @@ SimulatorControlPrivate::~SimulatorControlPrivate() } -// The simctl spawns the process and returns the pId but the application process might not have started, at least in a state where you can interrupt it. -// Use SimulatorControl::waitForProcessSpawn to be sure. -QProcess *SimulatorControl::spawnAppProcess(const QString &simUdid, const Utils::FileName &bundlePath, qint64 &pId, bool waitForDebugger, const QStringList &extraArgs) -{ - QProcess *simCtlProcess = nullptr; - if (isSimulatorRunning(simUdid)) { - QString bundleId = bundleIdentifier(bundlePath); - QString executableName = bundleExecutable(bundlePath); - QByteArray appPath = runSimCtlCommand(QStringList() << QStringLiteral("get_app_container") << simUdid << bundleId).trimmed(); - if (!appPath.isEmpty() && !executableName.isEmpty()) { - // Spawn the app. The spawned app is started in suspended mode. - appPath.append('/' + executableName.toLocal8Bit()); - simCtlProcess = new QProcess; - QStringList args; - args << QStringLiteral("simctl"); - args << QStringLiteral("spawn"); - if (waitForDebugger) - args << QStringLiteral("-w"); - args << simUdid; - args << QString::fromLocal8Bit(appPath); - args << extraArgs; - simCtlProcess->start(QStringLiteral("xcrun"), args); - if (!simCtlProcess->waitForStarted()){ - // Spawn command failed. - qCDebug(simulatorLog) << "Spawning the app failed." << simCtlProcess->errorString(); - delete simCtlProcess; - simCtlProcess = nullptr; - } - - // Find the process id of the the app process. - if (simCtlProcess) { - qint64 simctlPId = simCtlProcess->processId(); - pId = -1; - QByteArray commandOutput; - QStringList pGrepArgs; - pGrepArgs << QStringLiteral("-f") << QString::fromLocal8Bit(appPath); - auto begin = std::chrono::high_resolution_clock::now(); - // Find the pid of the spawned app. - while (pId == -1 && d->runCommand(QStringLiteral("pgrep"), pGrepArgs, &commandOutput)) { - foreach (auto pidStr, commandOutput.trimmed().split('\n')) { - qint64 parsedPId = pidStr.toLongLong(); - if (parsedPId != simctlPId) - pId = parsedPId; - } - if (checkForTimeout(begin)) { - qCDebug(simulatorLog) << "Spawning the app failed. Process timed out"; - break; - } - } - } - - if (pId == -1) { - // App process id can't be found. - qCDebug(simulatorLog) << "Spawning the app failed. PID not found."; - delete simCtlProcess; - simCtlProcess = nullptr; - } - } else { - qCDebug(simulatorLog) << "Spawning the app failed. Check installed app." << appPath; - } - } else { - qCDebug(simulatorLog) << "Spawning the app failed. Simulator not running." << simUdid; - } - return simCtlProcess; -} - -bool SimulatorControl::waitForProcessSpawn(qint64 processPId) -{ - bool success = true; - if (processPId != -1) { - // Wait for app to reach intruptible sleep state. - QByteArray wqStr; - QStringList args; - int wqCount = -1; - args << QStringLiteral("-p") << QString::number(processPId) << QStringLiteral("-o") << QStringLiteral("wq="); - auto begin = std::chrono::high_resolution_clock::now(); - do { - if (!d->runCommand(QStringLiteral("ps"), args, &wqStr)) { - success = false; - break; - } - bool validInt = false; - wqCount = wqStr.toInt(&validInt); - if (!validInt) { - wqCount = -1; - } - } while (wqCount < 0 && !checkForTimeout(begin)); - success = wqCount >= 0; - } else { - qCDebug(simulatorLog) << "Wait for spawned failed. Invalid Process ID." << processPId; - } - return success; -} - -SimulatorControlPrivate::SimDeviceInfo SimulatorControlPrivate::deviceInfo(const QString &simUdid) const +SimulatorControlPrivate::SimDeviceInfo SimulatorControlPrivate::deviceInfo(const QString &simUdid) { SimDeviceInfo info; bool found = false; if (!simUdid.isEmpty()) { - // It might happend that the simulator is not started by SimControl. - // Check of intances started externally. const QByteArray output = runSimCtlCommand({QLatin1String("list"), QLatin1String("-j"), QLatin1String("devices")}); QJsonDocument doc = QJsonDocument::fromJson(output); if (!doc.isNull()) { @@ -409,17 +289,208 @@ SimulatorControlPrivate::SimDeviceInfo SimulatorControlPrivate::deviceInfo(const return info; } -bool SimulatorControlPrivate::runCommand(QString command, const QStringList &args, QByteArray *output) +QString SimulatorControlPrivate::bundleIdentifier(const Utils::FileName &bundlePath) { - bool success = false; - QProcess process; - process.start(command, args); - success = process.waitForFinished(); - if (output) - *output = process.readAll().trimmed(); - return success; + QString bundleID; +#ifdef Q_OS_MAC + if (bundlePath.exists()) { + CFStringRef cFBundlePath = bundlePath.toString().toCFString(); + CFURLRef bundle_url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, cFBundlePath, kCFURLPOSIXPathStyle, true); + CFRelease(cFBundlePath); + CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, bundle_url); + CFRelease(bundle_url); + CFStringRef cFBundleID = CFBundleGetIdentifier(bundle); + bundleID = QString::fromCFString(cFBundleID).trimmed(); + CFRelease(bundle); + } +#else + Q_UNUSED(bundlePath) +#endif + return bundleID; +} + +QString SimulatorControlPrivate::bundleExecutable(const Utils::FileName &bundlePath) +{ + QString executable; +#ifdef Q_OS_MAC + if (bundlePath.exists()) { + CFStringRef cFBundlePath = bundlePath.toString().toCFString(); + CFURLRef bundle_url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, cFBundlePath, kCFURLPOSIXPathStyle, true); + CFRelease(cFBundlePath); + CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, bundle_url); + CFStringRef cFStrExecutableName = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleExecutableKey); + executable = QString::fromCFString(cFStrExecutableName).trimmed(); + CFRelease(bundle); + } +#else + Q_UNUSED(bundlePath) +#endif + return executable; +} + +void SimulatorControlPrivate::startSimulator(QFutureInterface &fi, + const QString &simUdid) +{ + SimulatorControl::ResponseData response(simUdid); + if (deviceInfo(simUdid).isAvailable()) { + // Simulator is available. + const QString cmd = IosConfigurations::developerPath() + .appendPath(QStringLiteral("/Applications/Simulator.app/Contents/MacOS/Simulator")) + .toString(); + const QStringList args({QStringLiteral("--args"), QStringLiteral("-CurrentDeviceUDID"), simUdid}); + + if (QProcess::startDetached(cmd, args)) { + if (fi.isCanceled()) + return; + // At this point the sim device exists, available and was not running. + // So the simulator is started and we'll wait for it to reach to a state + // where we can interact with it. + auto start = chrono::high_resolution_clock::now(); + SimulatorControlPrivate::SimDeviceInfo info; + do { + info = deviceInfo(simUdid); + if (fi.isCanceled()) + return; + } while (!info.isBooted() + && !checkForTimeout(start, SIMULATOR_START_TIMEOUT)); + if (info.isBooted()) { + response.success = true; + } + } else { + qCDebug(simulatorLog) << "Error starting simulator."; + } + } + + if (!fi.isCanceled()) { + fi.reportResult(response); + } +} + +void SimulatorControlPrivate::installApp(QFutureInterface &fi, + const QString &simUdid, const Utils::FileName &bundlePath) +{ + QTC_CHECK(bundlePath.exists()); + QByteArray output = runSimCtlCommand({QStringLiteral("install"), simUdid, bundlePath.toString()}); + SimulatorControl::ResponseData response(simUdid); + response.success = output.isEmpty(); + response.commandOutput = output; + + if (!fi.isCanceled()) { + fi.reportResult(response); + } +} + +void SimulatorControlPrivate::spawnAppProcess(QFutureInterface &fi, + const QString &simUdid, const Utils::FileName &bundlePath, + bool waitForDebugger, QStringList extraArgs, QThread *mainThread) +{ + SimulatorControl::ResponseData response(simUdid); + + // Find the path of the installed app. + QString bundleId = bundleIdentifier(bundlePath); + QByteArray appContainer = runSimCtlCommand({QStringLiteral("get_app_container"), simUdid, bundleId}); + QString appPath = QString::fromLocal8Bit(appContainer.trimmed()); + + if (fi.isCanceled()) + return; + + QString executableName = bundleExecutable(bundlePath); + if (!appPath.isEmpty() && !executableName.isEmpty()) { + appPath.append('/' + executableName); + QStringList args = {QStringLiteral("simctl"), QStringLiteral("spawn"), simUdid, appPath}; + if (waitForDebugger) + args.insert(2, QStringLiteral("-w")); + args << extraArgs; + + // Spawn the app. The spawned app is started in suspended mode. + shared_ptr simCtlProcess(new QProcess, [](QProcess *p) { + if (p->state() != QProcess::NotRunning) { + p->kill(); + p->waitForFinished(COMMAND_TIMEOUT); + } + delete p; + }); + simCtlProcess->start(QStringLiteral("xcrun"), args); + if (simCtlProcess->waitForStarted()) { + if (fi.isCanceled()) + return; + // Find the process id of the spawned app. + qint64 simctlPId = simCtlProcess->processId(); + QByteArray commandOutput; + const QStringList pGrepArgs = {QStringLiteral("-f"), appPath}; + auto begin = chrono::high_resolution_clock::now(); + int processID = -1; + while (processID == -1 && runCommand(QStringLiteral("pgrep"), pGrepArgs, &commandOutput)) { + if (fi.isCanceled()) { + qCDebug(simulatorLog) <<"Spawning the app failed. Future cancelled."; + return; + } + foreach (auto pidStr, commandOutput.trimmed().split('\n')) { + qint64 parsedPId = pidStr.toLongLong(); + if (parsedPId != simctlPId) + processID = parsedPId; + } + if (checkForTimeout(begin)) { + qCDebug(simulatorLog) << "Spawning the app failed. Process timed out"; + break; + } + } + + if (processID == -1) { + qCDebug(simulatorLog) << "Spawning the app failed. App PID not found."; + simCtlProcess->waitForReadyRead(COMMAND_TIMEOUT); + response.commandOutput = simCtlProcess->readAllStandardError(); + } else { + response.processInstance = simCtlProcess; + response.processInstance->moveToThread(mainThread); + response.pID = processID; + response.success = true; + } + } else { + qCDebug(simulatorLog) << "Spawning the app failed." << simCtlProcess->errorString(); + response.commandOutput = simCtlProcess->errorString().toLatin1(); + } + } else { + qCDebug(simulatorLog) << "Spawning the app failed. Check installed app." << appPath; + } + + if (!fi.isCanceled()) { + fi.reportResult(response); + } +} + +void SimulatorControlPrivate::launchApp(QFutureInterface &fi, + const QString &simUdid, const QString &bundleIdentifier, + qint64 spawnedPID) +{ + SimulatorControl::ResponseData response(simUdid); + if (!bundleIdentifier.isEmpty()) { + bool processSpawned = true; + // Wait for the process to be spawned properly before launching app. + if (spawnedPID > -1) + processSpawned = waitForProcessSpawn(spawnedPID, fi); + + if (fi.isCanceled()) + return; + + if (processSpawned) { + const QStringList args({QStringLiteral("launch"), simUdid , bundleIdentifier}); + response.commandOutput = runSimCtlCommand(args); + const QByteArray pIdStr = response.commandOutput.trimmed().split(' ').last().trimmed(); + bool validInt = false; + response.pID = pIdStr.toLongLong(&validInt); + if (!validInt) { + // Launch Failed. + qCDebug(simulatorLog) << "Launch app failed. Process id returned is not valid. PID =" << pIdStr; + response.pID = -1; + } + } + } + + if (!fi.isCanceled()) { + fi.reportResult(response); + } } } // namespace Internal } // namespace Ios -#include "simulatorcontrol.moc" diff --git a/src/plugins/ios/simulatorcontrol.h b/src/plugins/ios/simulatorcontrol.h index 1a674d644eb..4680350c48b 100644 --- a/src/plugins/ios/simulatorcontrol.h +++ b/src/plugins/ios/simulatorcontrol.h @@ -22,10 +22,10 @@ ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ -#ifndef SIMULATORCONTROL_H -#define SIMULATORCONTROL_H +#pragma once -#include +#include +#include #include "utils/fileutils.h" QT_BEGIN_NAMESPACE @@ -38,29 +38,44 @@ namespace Internal { class IosDeviceType; class SimulatorControlPrivate; -class SimulatorControl +class SimulatorControl : public QObject { - explicit SimulatorControl(); + Q_OBJECT +public: + struct ResponseData { + ResponseData(const QString & udid): + simUdid(udid) { } + + QString simUdid; + bool success = false; + qint64 pID = -1; + QByteArray commandOutput = ""; + // For response type APP_SPAWN, the processInstance represents the control process of the spwaned app + // For other response types its null. + std::shared_ptr processInstance; + }; + +public: + explicit SimulatorControl(QObject* parent = nullptr); + ~SimulatorControl(); public: static QList availableSimulators(); static void updateAvailableSimulators(); - - static bool startSimulator(const QString &simUdid); static bool isSimulatorRunning(const QString &simUdid); - - static bool installApp(const QString &simUdid, const Utils::FileName &bundlePath, QByteArray &commandOutput); - static QProcess* spawnAppProcess(const QString &simUdid, const Utils::FileName &bundlePath, qint64 &pId, - bool waitForDebugger, const QStringList &extraArgs); - - static qint64 launchApp(const QString &simUdid, const QString &bundleIdentifier, QByteArray *commandOutput = nullptr); static QString bundleIdentifier(const Utils::FileName &bundlePath); static QString bundleExecutable(const Utils::FileName &bundlePath); - static bool waitForProcessSpawn(qint64 processPId); + +public: + QFuture startSimulator(const QString &simUdid); + QFuture installApp(const QString &simUdid, const Utils::FileName &bundlePath) const; + QFuture spawnAppProcess(const QString &simUdid, const Utils::FileName &bundlePath, + bool waitForDebugger, const QStringList &extraArgs) const; + QFuture launchApp(const QString &simUdid, const QString &bundleIdentifier, + qint64 spawnedPID = -1) const; private: - static SimulatorControlPrivate *d; + SimulatorControlPrivate *d; }; } // namespace Internal } // namespace Ios -#endif // SIMULATORCONTROL_H From 569f4499c038f4186d511d15d2b626d57b57fcd1 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 16 Nov 2016 09:45:27 +0100 Subject: [PATCH 26/33] iOS: Fix build Include for std::shared_ptr. Change-Id: I549eef8e8dc42b58b07e3528d55193ed8c54dd7e Reviewed-by: Eike Ziller (cherry picked from commit 6614b7a276941892f08f6250c4acecb9721fab6c) --- src/plugins/ios/simulatorcontrol.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/ios/simulatorcontrol.h b/src/plugins/ios/simulatorcontrol.h index 4680350c48b..2c3b2cd296e 100644 --- a/src/plugins/ios/simulatorcontrol.h +++ b/src/plugins/ios/simulatorcontrol.h @@ -28,6 +28,8 @@ #include #include "utils/fileutils.h" +#include + QT_BEGIN_NAMESPACE class QProcess; QT_END_NAMESPACE From 36d4d01cd374a21a8b7c229b261c5f1a23d1184e Mon Sep 17 00:00:00 2001 From: Denis Klychkov Date: Wed, 2 Nov 2016 12:21:54 +0300 Subject: [PATCH 27/33] Clang: Take precompiled headers into account when parsing source files Task-number: QTCREATORBUG-15590 Change-Id: Icbfce4ffd6e9f9802641d35d898fa1dc1c4c18ee Reviewed-by: Nikolai Kosjar --- .../clangeditordocumentprocessor.cpp | 23 +++++++++++++++- src/plugins/clangcodemodel/clangutils.cpp | 21 --------------- src/plugins/clangcodemodel/clangutils.h | 1 - .../refactoringcompileroptionsbuilder.cpp | 4 ++- .../refactoringcompileroptionsbuilder.h | 3 ++- .../clangrefactoring/refactoringengine.cpp | 5 +++- .../clangstaticanalyzerruncontrol.cpp | 17 +++++++++--- .../cpptools/compileroptionsbuilder.cpp | 27 +++++++++++++++++-- src/plugins/cpptools/compileroptionsbuilder.h | 7 +++++ src/plugins/cpptools/cpptoolsreuse.cpp | 8 ++++++ src/plugins/cpptools/cpptoolsreuse.h | 4 +++ 11 files changed, 89 insertions(+), 31 deletions(-) diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 82f06b59949..769d2d0e377 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -401,9 +401,30 @@ static QStringList warningOptions(CppTools::ProjectPart *projectPart) return CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineOptions(); } +static QStringList precompiledHeaderOptions( + const QString& filePath, + CppTools::ProjectPart *projectPart) +{ + using namespace CppTools; + + if (CppTools::getPchUsage() == CompilerOptionsBuilder::PchUsage::None) + return QStringList(); + + if (projectPart->precompiledHeaders.contains(filePath)) + return QStringList(); + + const CppTools::ProjectPart theProjectPart = projectPartForLanguageOption(projectPart); + CppTools::CompilerOptionsBuilder builder(theProjectPart); + builder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::Use); + + return builder.options(); +} + static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart *projectPart) { - return languageOptions(filePath, projectPart) + warningOptions(projectPart); + return languageOptions(filePath, projectPart) + + warningOptions(projectPart) + + precompiledHeaderOptions(filePath, projectPart); } ClangBackEnd::FileContainer diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 1d704c8a88b..5bdf36051d3 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -192,27 +192,6 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind return LibClangOptionsBuilder::build(pPart, fileKind); } -/// @return Option to speed up parsing with precompiled header -QStringList createPCHInclusionOptions(const QStringList &pchFiles) -{ - QStringList opts; - - foreach (const QString &pchFile, pchFiles) { - if (QFile(pchFile).exists()) { - opts += QLatin1String("-include-pch"); - opts += pchFile; - } - } - - return opts; -} - -/// @return Option to speed up parsing with precompiled header -QStringList createPCHInclusionOptions(const QString &pchFile) -{ - return createPCHInclusionOptions(QStringList() << pchFile); -} - ProjectPart::Ptr projectPartForFile(const QString &filePath) { if (const auto parser = CppTools::BaseEditorDocumentParser::get(filePath)) diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 4bdc6c00d43..dcec4491397 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -34,7 +34,6 @@ QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart, CppTools::ProjectFile::Kind fileKind); QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart, const QString &fileName = QString()); -QStringList createPCHInclusionOptions(const QString &pchFile); CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath); CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &filePath); diff --git a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp index 5fa28940f5a..4500d011156 100644 --- a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp +++ b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp @@ -117,7 +117,8 @@ void RefactoringCompilerOptionsBuilder::addExtraOptions() } Utils::SmallStringVector RefactoringCompilerOptionsBuilder::build(CppTools::ProjectPart *projectPart, - CppTools::ProjectFile::Kind fileKind) + CppTools::ProjectFile::Kind fileKind, + PchUsage pchUsage) { if (projectPart == nullptr) return Utils::SmallStringVector(); @@ -138,6 +139,7 @@ Utils::SmallStringVector RefactoringCompilerOptionsBuilder::build(CppTools::Proj optionsBuilder.addPredefinedMacrosAndHeaderPathsOptions(); optionsBuilder.addWrappedQtHeadersIncludePath(); optionsBuilder.addHeaderPathOptions(); + optionsBuilder.addPrecompiledHeaderOptions(pchUsage); optionsBuilder.addProjectConfigFileInclude(); optionsBuilder.addMsvcCompatibilityVersion(); diff --git a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.h b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.h index 9a11573e8d0..74532dea162 100644 --- a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.h +++ b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.h @@ -41,7 +41,8 @@ class RefactoringCompilerOptionsBuilder : public CppTools::CompilerOptionsBuilde { public: static Utils::SmallStringVector build(CppTools::ProjectPart *projectPart, - CppTools::ProjectFile::Kind fileKind); + CppTools::ProjectFile::Kind fileKind, + PchUsage pchUsage); private: RefactoringCompilerOptionsBuilder(CppTools::ProjectPart *projectPart); diff --git a/src/plugins/clangrefactoring/refactoringengine.cpp b/src/plugins/clangrefactoring/refactoringengine.cpp index fe33c82c09d..ea930c20297 100644 --- a/src/plugins/clangrefactoring/refactoringengine.cpp +++ b/src/plugins/clangrefactoring/refactoringengine.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include #include @@ -89,7 +91,8 @@ void RefactoringEngine::startLocalRenaming(const QTextCursor &textCursor, client.setLocalRenamingCallback(std::move(renameSymbolsCallback)); auto commandLine = RefactoringCompilerOptionsBuilder::build(projectPart, - fileKind(projectPart, filePath.toString())); + fileKind(projectPart, filePath.toString()), + CppTools::getPchUsage()); commandLine.push_back(filePath.toString()); qDebug() << commandLine.join(" "); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 10cb6115ba5..2a8a5f58c9d 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -165,7 +166,8 @@ class ClangStaticAnalyzerOptionsBuilder : public CompilerOptionsBuilder { public: static QStringList build(const CppTools::ProjectPart &projectPart, - CppTools::ProjectFile::Kind fileKind) + CppTools::ProjectFile::Kind fileKind, + PchUsage pchUsage) { ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart); @@ -184,6 +186,7 @@ public: optionsBuilder.undefineClangVersionMacrosForMsvc(); optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); optionsBuilder.addHeaderPathOptions(); + optionsBuilder.addPrecompiledHeaderOptions(pchUsage); optionsBuilder.addMsvcCompatibilityVersion(); if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) @@ -243,10 +246,17 @@ private: QString includeOption() const override { if (m_isMsvcToolchain) - return QLatin1String("/I"); + return QLatin1String("/FI"); return CompilerOptionsBuilder::includeOption(); } + QString includeDirOption() const override + { + if (m_isMsvcToolchain) + return QLatin1String("/I"); + return CompilerOptionsBuilder::includeDirOption(); + } + QString defineOption() const override { if (m_isMsvcToolchain) @@ -376,8 +386,9 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QList continue; QTC_CHECK(file.kind != ProjectFile::Unclassified); if (ProjectFile::isSource(file.kind)) { + const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage(); const QStringList arguments - = ClangStaticAnalyzerOptionsBuilder::build(*projectPart.data(), file.kind); + = ClangStaticAnalyzerOptionsBuilder::build(*projectPart.data(), file.kind, pchUsage); unitsToAnalyze << AnalyzeUnit(file.path, arguments); } } diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 01378ec88e2..d99692536dd 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -112,7 +112,7 @@ void CompilerOptionsBuilder::enableExceptions() void CompilerOptionsBuilder::addHeaderPathOptions() { typedef ProjectPartHeaderPath HeaderPath; - const QString defaultPrefix = includeOption(); + const QString defaultPrefix = includeDirOption(); QStringList result; @@ -141,6 +141,24 @@ void CompilerOptionsBuilder::addHeaderPathOptions() m_options.append(result); } +void CompilerOptionsBuilder::addPrecompiledHeaderOptions(PchUsage pchUsage) +{ + if (pchUsage == PchUsage::None) + return; + + QStringList result; + + const QString includeOptionString = includeOption(); + foreach (const QString &pchFile, m_projectPart.precompiledHeaders) { + if (QFile::exists(pchFile)) { + result += includeOptionString; + result += QDir::toNativeSeparators(pchFile); + } + } + + m_options.append(result); +} + void CompilerOptionsBuilder::addToolchainAndProjectDefines() { addDefines(m_projectPart.toolchainDefines); @@ -376,7 +394,7 @@ void CompilerOptionsBuilder::addDefineFloat128ForMingw() addDefine("#define __float128 void"); } -QString CompilerOptionsBuilder::includeOption() const +QString CompilerOptionsBuilder::includeDirOption() const { return QLatin1String("-I"); } @@ -399,6 +417,11 @@ QString CompilerOptionsBuilder::undefineOption() const return QLatin1String("-U"); } +QString CompilerOptionsBuilder::includeOption() const +{ + return QLatin1String("-include"); +} + static bool isGccOrMinGwToolchain(const Core::Id &toolchainType) { return toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index ced3c0af1ba..75b0c4f530d 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -34,6 +34,11 @@ namespace CppTools { class CPPTOOLS_EXPORT CompilerOptionsBuilder { public: + enum class PchUsage { + None, + Use + }; + CompilerOptionsBuilder(const ProjectPart &projectPart); virtual ~CompilerOptionsBuilder() {} @@ -48,6 +53,7 @@ public: virtual void addTargetTriple(); virtual void enableExceptions(); void addHeaderPathOptions(); + void addPrecompiledHeaderOptions(PchUsage pchUsage); void addToolchainAndProjectDefines(); void addDefines(const QByteArray &defineDirectives); virtual void addLanguageOption(ProjectFile::Kind fileKind); @@ -67,6 +73,7 @@ protected: virtual QString defineOption() const; virtual QString undefineOption() const; virtual QString includeOption() const; + virtual QString includeDirOption() const; const ProjectPart m_projectPart; diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp index 7a21b4c6da6..fcb3c8b878e 100644 --- a/src/plugins/cpptools/cpptoolsreuse.cpp +++ b/src/plugins/cpptools/cpptoolsreuse.cpp @@ -288,4 +288,12 @@ bool fileSizeExceedsLimit(const QFileInfo &fileInfo, int sizeLimitInMb) return false; } +CompilerOptionsBuilder::PchUsage getPchUsage() +{ + const QSharedPointer cms = codeModelSettings(); + if (cms->pchUsage() == CppCodeModelSettings::PchUse_None) + return CompilerOptionsBuilder::PchUsage::None; + return CompilerOptionsBuilder::PchUsage::Use; +} + } // CppTools diff --git a/src/plugins/cpptools/cpptoolsreuse.h b/src/plugins/cpptools/cpptoolsreuse.h index b60eceeb64c..46ef50d7b16 100644 --- a/src/plugins/cpptools/cpptoolsreuse.h +++ b/src/plugins/cpptools/cpptoolsreuse.h @@ -29,6 +29,8 @@ #include +#include + #include QT_BEGIN_NAMESPACE @@ -72,6 +74,8 @@ void CPPTOOLS_EXPORT switchHeaderSource(); class CppCodeModelSettings; QSharedPointer CPPTOOLS_EXPORT codeModelSettings(); +CompilerOptionsBuilder::PchUsage CPPTOOLS_EXPORT getPchUsage(); + int indexerFileSizeLimitInMb(); bool fileSizeExceedsLimit(const QFileInfo &fileInfo, int sizeLimitInMb); From b26400e8efc5a582e92ff6ad3226bf22eab5f7c2 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 14 Nov 2016 16:22:42 +0100 Subject: [PATCH 28/33] Debugger: Workaround gdb.lookup_symbol ignoring QArrayData::shared_null There have been cases observed where 'p QArrayData::shared_null' finds valid symbols that are not found using gdb.lookup_symbols. The cause for that is unknown. Apply an expensive workaround by checking for (the equivalent of) a working 'p QArrayData::shared_null' but execute it only when a libQt5Core was found. This keeps the overhead for non-Qt setups at a bearable (unsuccessful) iteration over known shared object names. Change-Id: Id398673b938d3c3a72c24317abdbefbe793e54df Reviewed-by: Christian Stenger --- share/qtcreator/debugger/gdbbridge.py | 44 +++++++++++++++------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 9877c54c290..3612dcdb4fb 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1014,30 +1014,34 @@ class Dumper(DumperBase): if not self.currentQtNamespaceGuess is None: return self.currentQtNamespaceGuess - # This only works when called from a valid frame. - try: - cand = 'QArrayData::shared_null' - symbol = gdb.lookup_symbol(cand)[0] - if symbol: - ns = symbol.name[:-len(cand)] - self.qtNamespaceToReport = ns - self.qtNamespace = lambda: ns - return ns - except: - pass + for objfile in gdb.objfiles(): + name = objfile.filename + if name.find('/libQt5Core') >= 0: + ns = '' - try: - # This is Qt, but not 5.x. - cand = 'QByteArray::shared_null' - symbol = gdb.lookup_symbol(cand)[0] - if symbol: - ns = symbol.name[:-len(cand)] + # This only works when called from a valid frame. + try: + cand = 'QArrayData::shared_null' + symbol = gdb.lookup_symbol(cand)[0] + if symbol: + ns = symbol.name[:-len(cand)] + except: + try: + # Some GDB 7.11.1 on Arch Linux. + cand = 'QArrayData::shared_null[0]' + val = gdb.parse_and_eval(cand) + if val.type is not None: + typeobj = val.type.unqualified() + ns = typeobj.name[:-len('QArrayData')] + except: + pass + + # This might be wrong, but we can't do better: We found + # a libQt5Core and could not extract a namespace. + # The best guess is that there isn't any. self.qtNamespaceToReport = ns self.qtNamespace = lambda: ns - self.fallbackQtVersion = 0x40800 return ns - except: - pass self.currentQtNamespaceGuess = '' return '' From f42d44a481df755da88dbffdcdb6225f0be80fdf Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 15 Nov 2016 11:11:21 +0100 Subject: [PATCH 29/33] Debugger: Recognize '-' as start of numeric template argument Change-Id: Ibc0fd730655378dca3dc231dbad36981364ccf70 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 91053ceced6..259cad968a7 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -574,7 +574,7 @@ class DumperBase: res = [] for item in targs[::-1]: c = ord(item[0]) - if c == '-' or (c >= 48 and c < 58): + if c in (45, 46) or (c >= 48 and c < 58): # '-', '.' or digit. if item.find('.') > -1: res.append(float(item)) else: From d7408f1fa8e5bcb85ab2818ab56528a4825b18fc Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 15 Nov 2016 13:11:39 +0100 Subject: [PATCH 30/33] Debugger: Make std::set::iterator dumper test pass for libc++ Change-Id: Ib5f9a0d71c130dcbcc14719b85f13582bbeaf74e Reviewed-by: Christian Stenger --- share/qtcreator/debugger/stdtypes.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index 77fc8812bb7..5fa4522cfe5 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -511,10 +511,17 @@ def qdump__std____1__map__const_iterator(d, value): def qdump__std____1__set__iterator(d, value): d.putEmptyValue() + d.putNumChild(1) + if value.type.name.endswith("::iterator"): + treeTypeName = value.type.name[:-len("::iterator")] + elif value.type.name.endswith("::const_iterator"): + treeTypeName = value.type.name[:-len("::const_iterator")] + treeType = d.lookupType(treeTypeName) + keyType = treeType[0] if d.isExpanded(): with Children(d): node = value['__ptr_'].dereference()['__value_'] - node = node.cast(value.type[0]) + node = node.cast(keyType) d.putSubItem('value', node) def qdump__std____1__set_const_iterator(d, value): From f0115b666493aade88b917fb3a26d395d0f654c9 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 16 Nov 2016 10:46:48 +0100 Subject: [PATCH 31/33] Debugger: Disable some of the LLDB inheritance dumper Both LLDB 3.8/Linux and 360.x/Mac cannot display the contents of a virtual base class when accessed to a 'secondary' path. The problem is with LLDB itself, so don't expect Creator tests to pass in those cases. Change-Id: I25b005d66fa9f64766a4cc0aaaa2c865b6df8c5f Reviewed-by: Christian Stenger --- tests/auto/debugger/tst_dumpers.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 1c4f3cb808f..5bf80148b6b 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -5986,19 +5986,20 @@ void tst_Dumpers::dumper_data() + Check("tt.@2.@1.v", "45", "int") % LldbEngine + Check("dd.@1.@1.a", "1", "int") // B::a - + Check("dd.@2.@1.a", "1", "int") // C::a + // C::a - fails with command line LLDB 3.8/360.x + + Check("dd.@2.@1.a", "1", "int") % NoLldbEngine // C::a + Check("dd.@1.b", "2", "int") + Check("dd.@2.c", "3", "int") + Check("dd.d", "4", "int") + Check("dp.@1.@1.a", "1", "int") // B::a - + Check("dp.@2.@1.a", "1", "int") // C::a + + Check("dp.@2.@1.a", "1", "int") % NoLldbEngine // C::a + Check("dp.@1.b", "2", "int") + Check("dp.@2.c", "3", "int") + Check("dp.d", "4", "int") + Check("dr.@1.@1.a", "1", "int") // B::a - + Check("dr.@2.@1.a", "1", "int") // C::a + + Check("dr.@2.@1.a", "1", "int") % NoLldbEngine // C::a + Check("dr.@1.b", "2", "int") + Check("dr.@2.c", "3", "int") + Check("dr.d", "4", "int"); From ab16549024c67f55f61e1c2f2d4b8a9f5e48b37a Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 15 Nov 2016 09:52:30 +0100 Subject: [PATCH 32/33] Document building QtC with system qbs Change-Id: I551d2a909db7875183b74160cedc958b4a1d5e8c Reviewed-by: Leena Miettinen --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ab907a13ed6..ad73f244a13 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Prerequisites: * On Mac OS X: latest Xcode * On Linux: g++ 4.8 or later * LLVM 3.9.0 or later (optional, needed for the Clang Code Model) +* Qbs 1.7.x (optional, sources also contain Qbs itself) The installed toolchains have to match the one Qt was compiled with. @@ -33,6 +34,8 @@ You can build Qt Creator with # Optional, needed for the Clang Code Model: export LLVM_INSTALL_DIR=/path/to/llvm (or "set" on Windows) + # Optional, needed to let the QbsProjectManager plugin use system Qbs: + export QBS_INSTALL_DIR=/path/to/qbs cd $SOURCE_DIRECTORY qmake -r From 82818cb90bde1dcc4dd1fa6c0c2c9608e61429c2 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 16 Nov 2016 11:29:57 +0100 Subject: [PATCH 33/33] Debugger: Improve QAtomicPointer dumper More compact display and arbitrary inner types. Change-Id: I68bc1f5cc88f51e993e6e8a91556d9d745a2574a Reviewed-by: Christian Stenger --- share/qtcreator/debugger/qttypes.py | 10 +++------- tests/auto/debugger/tst_dumpers.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index ed94f51ad36..65f4e1fbdd9 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -38,13 +38,9 @@ def qdump__QBasicAtomicInt(d, value): def qdump__QAtomicPointer(d, value): - d.putType(value.type) - p = value.extractPointer() - d.putValue('@0x%x' % p) - d.putNumChild(1 if p else 0) - if d.isExpanded(): - with Children(d): - d.putSubItem('[pointee]', value.dereference()) + d.putItem(value.cast(value.type[0].pointer())) + d.putBetterType(value.type) + def qform__QByteArray(): return [Latin1StringFormat, SeparateLatin1StringFormat, diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 5bf80148b6b..0c78e88ff63 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2935,6 +2935,31 @@ void tst_Dumpers::dumper_data() " QSharedDataPointer d;\n" " };\n"; + QTest::newRow("QAtomicPointer") + << Data("#include \n" + "#include \n\n" + "template struct Pointer : QAtomicPointer {\n" + " Pointer(T *value = 0) : QAtomicPointer(value) {}\n" + "};\n\n" + "struct SomeStruct {\n" + " int a = 1;\n" + " long b = 2;\n" + " double c = 3.0;\n" + " QString d = \"4\";\n" + " QList e = {\"5\", \"6\" };\n" + "};\n\n" + "typedef Pointer SomeStructPointer;\n\n", + + "SomeStruct *s = new SomeStruct; unused(s);\n" + "SomeStructPointer p(s); unused(p);\n" + "Pointer pp(s); unused(pp);\n" + "QAtomicPointer ppp(s); unused(ppp);\n") + + Cxx11Profile() + + Check("p.@1.a", "1", "int") + + Check("p.@1.e", "<2 items>", "@QList<@QString>") + + Check("pp.@1.a", "1", "int") + + Check("ppp.a", "1", "int"); + QTest::newRow("QScopedPointer") << Data("#include \n"