1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "librarydetailscontroller.h"
27 #include "ui_librarydetailswidget.h"
28 #include "qmakebuildconfiguration.h"
29 #include "qmakeparsernodes.h"
30 #include "qmakeproject.h"
31
32 #include <projectexplorer/projectexplorer.h>
33 #include <projectexplorer/session.h>
34 #include <projectexplorer/target.h>
35 #include <utils/hostosinfo.h>
36 #include <utils/qtcprocess.h>
37
38 #include <QFileInfo>
39 #include <QDir>
40 #include <QTextStream>
41
42 using namespace ProjectExplorer;
43 using namespace QmakeProjectManager;
44 using namespace QmakeProjectManager::Internal;
45
fillLibraryPlatformTypes(QComboBox * comboBox)46 static void fillLibraryPlatformTypes(QComboBox *comboBox)
47 {
48 comboBox->clear();
49 comboBox->addItem("Windows (*.lib lib*.a)", int(Utils::OsTypeWindows));
50 comboBox->addItem("Linux (lib*.so lib*.a)", int(Utils::OsTypeLinux));
51 comboBox->addItem("macOS (*.dylib *.a *.framework)", int(Utils::OsTypeMac));
52 const int currentIndex = comboBox->findData(int(Utils::HostOsInfo::hostOs()));
53 comboBox->setCurrentIndex(std::max(0, currentIndex));
54 }
55
LibraryDetailsController(Ui::LibraryDetailsWidget * libraryDetails,const QString & proFile,QObject * parent)56 LibraryDetailsController::LibraryDetailsController(
57 Ui::LibraryDetailsWidget *libraryDetails,
58 const QString &proFile, QObject *parent) :
59 QObject(parent),
60 m_proFile(proFile),
61 m_libraryDetailsWidget(libraryDetails)
62 {
63 fillLibraryPlatformTypes(m_libraryDetailsWidget->libraryTypeComboBox);
64 setPlatformsVisible(true);
65 setLinkageGroupVisible(true);
66 setMacLibraryGroupVisible(true);
67 setPackageLineEditVisible(false);
68 const bool isMacOs = libraryPlatformType() == Utils::OsTypeMac;
69 const bool isWindows = libraryPlatformType() == Utils::OsTypeWindows;
70 setMacLibraryRadiosVisible(!isMacOs);
71 setLinkageRadiosVisible(isWindows);
72
73 connect(m_libraryDetailsWidget->includePathChooser, &Utils::PathChooser::rawPathChanged,
74 this, &LibraryDetailsController::slotIncludePathChanged);
75 connect(m_libraryDetailsWidget->frameworkRadio, &QAbstractButton::clicked,
76 this, &LibraryDetailsController::slotMacLibraryTypeChanged);
77 connect(m_libraryDetailsWidget->libraryRadio, &QAbstractButton::clicked,
78 this, &LibraryDetailsController::slotMacLibraryTypeChanged);
79 connect(m_libraryDetailsWidget->useSubfoldersCheckBox, &QAbstractButton::toggled,
80 this, &LibraryDetailsController::slotUseSubfoldersChanged);
81 connect(m_libraryDetailsWidget->addSuffixCheckBox, &QAbstractButton::toggled,
82 this, &LibraryDetailsController::slotAddSuffixChanged);
83 connect(m_libraryDetailsWidget->linCheckBox, &QAbstractButton::clicked,
84 this, &LibraryDetailsController::slotPlatformChanged);
85 connect(m_libraryDetailsWidget->macCheckBox, &QAbstractButton::clicked,
86 this, &LibraryDetailsController::slotPlatformChanged);
87 connect(m_libraryDetailsWidget->winCheckBox, &QAbstractButton::clicked,
88 this, &LibraryDetailsController::slotPlatformChanged);
89 }
90
libraryDetailsWidget() const91 Ui::LibraryDetailsWidget *LibraryDetailsController::libraryDetailsWidget() const
92 {
93 return m_libraryDetailsWidget;
94 }
95
platforms() const96 AddLibraryWizard::Platforms LibraryDetailsController::platforms() const
97 {
98 return m_platforms;
99 }
100
linkageType() const101 AddLibraryWizard::LinkageType LibraryDetailsController::linkageType() const
102 {
103 return m_linkageType;
104 }
105
macLibraryType() const106 AddLibraryWizard::MacLibraryType LibraryDetailsController::macLibraryType() const
107 {
108 return m_macLibraryType;
109 }
110
libraryPlatformType() const111 Utils::OsType LibraryDetailsController::libraryPlatformType() const
112 {
113 return Utils::OsType(m_libraryDetailsWidget->libraryTypeComboBox->currentData().value<int>());
114 }
115
libraryPlatformFilter() const116 QString LibraryDetailsController::libraryPlatformFilter() const
117 {
118 return m_libraryDetailsWidget->libraryTypeComboBox->currentText();
119 }
120
updateGui()121 void LibraryDetailsController::updateGui()
122 {
123 // read values from gui
124 m_platforms = {};
125 if (libraryDetailsWidget()->linCheckBox->isChecked())
126 m_platforms |= AddLibraryWizard::LinuxPlatform;
127 if (libraryDetailsWidget()->macCheckBox->isChecked())
128 m_platforms |= AddLibraryWizard::MacPlatform;
129 if (libraryDetailsWidget()->winCheckBox->isChecked())
130 m_platforms |= AddLibraryWizard::WindowsMinGWPlatform
131 | AddLibraryWizard::WindowsMSVCPlatform;
132
133 bool macLibraryTypeUpdated = false;
134 if (!m_linkageRadiosVisible) {
135 m_linkageType = suggestedLinkageType();
136 if (m_linkageType == AddLibraryWizard::StaticLinkage) {
137 m_macLibraryType = AddLibraryWizard::LibraryType;
138 macLibraryTypeUpdated = true;
139 }
140 } else {
141 m_linkageType = AddLibraryWizard::DynamicLinkage; // the default
142 if (libraryDetailsWidget()->staticRadio->isChecked())
143 m_linkageType = AddLibraryWizard::StaticLinkage;
144 }
145
146 if (!macLibraryTypeUpdated) {
147 if (!m_macLibraryRadiosVisible) {
148 m_macLibraryType = suggestedMacLibraryType();
149 } else {
150 m_macLibraryType = AddLibraryWizard::LibraryType; // the default
151 if (libraryDetailsWidget()->frameworkRadio->isChecked())
152 m_macLibraryType = AddLibraryWizard::FrameworkType;
153 }
154 }
155
156 // enable or disable some parts of gui
157 libraryDetailsWidget()->macGroupBox->setEnabled(platforms()
158 & AddLibraryWizard::MacPlatform);
159 updateWindowsOptionsEnablement();
160 const bool macRadiosEnabled = m_linkageRadiosVisible ||
161 linkageType() != AddLibraryWizard::StaticLinkage;
162 libraryDetailsWidget()->libraryRadio->setEnabled(macRadiosEnabled);
163 libraryDetailsWidget()->frameworkRadio->setEnabled(macRadiosEnabled);
164
165 // update values in gui
166 setIgnoreGuiSignals(true);
167
168 showLinkageType(linkageType());
169 showMacLibraryType(macLibraryType());
170 if (!m_includePathChanged)
171 libraryDetailsWidget()->includePathChooser->setPath(suggestedIncludePath());
172
173 setIgnoreGuiSignals(false);
174
175 // UGLY HACK BEGIN
176 //
177 // We need to invoke QWizardPrivate::updateLayout() method to properly
178 // recalculate the new minimum size for the whole wizard.
179 // This is done internally by QWizard e.g. when a new wizard page is being shown.
180 // Unfortunately, QWizard doesn't expose this method currently.
181 // Since the current implementation of QWizard::setTitleFormat() sets the
182 // format and calls QWizardPrivate::updateLayout() unconditionally
183 // we use it as a hacky solution to the above issue.
184 // For reference please see: QTBUG-88666
185 if (!m_wizard) {
186 QWidget *widget = libraryDetailsWidget()->detailsLayout->parentWidget();
187 while (widget) {
188 QWizard *wizard = qobject_cast<QWizard *>(widget);
189 if (wizard) {
190 m_wizard = wizard;
191 break;
192 }
193 widget = widget->parentWidget();
194 }
195 }
196 QTC_ASSERT(m_wizard, return);
197 m_wizard->setTitleFormat(m_wizard->titleFormat());
198 // UGLY HACK END
199 }
200
proFile() const201 QString LibraryDetailsController::proFile() const
202 {
203 return m_proFile;
204 }
205
isIncludePathChanged() const206 bool LibraryDetailsController::isIncludePathChanged() const
207 {
208 return m_includePathChanged;
209 }
210
setIgnoreGuiSignals(bool ignore)211 void LibraryDetailsController::setIgnoreGuiSignals(bool ignore)
212 {
213 m_ignoreGuiSignals = ignore;
214 }
215
guiSignalsIgnored() const216 bool LibraryDetailsController::guiSignalsIgnored() const
217 {
218 return m_ignoreGuiSignals;
219 }
220
showLinkageType(AddLibraryWizard::LinkageType linkageType)221 void LibraryDetailsController::showLinkageType(
222 AddLibraryWizard::LinkageType linkageType)
223 {
224 const QString linkage(tr("Linkage:"));
225 QString linkageTitle;
226 switch (linkageType) {
227 case AddLibraryWizard::DynamicLinkage:
228 libraryDetailsWidget()->dynamicRadio->setChecked(true);
229 linkageTitle = tr("%1 Dynamic").arg(linkage);
230 break;
231 case AddLibraryWizard::StaticLinkage:
232 libraryDetailsWidget()->staticRadio->setChecked(true);
233 linkageTitle = tr("%1 Static").arg(linkage);
234 break;
235 default:
236 libraryDetailsWidget()->dynamicRadio->setChecked(false);
237 libraryDetailsWidget()->staticRadio->setChecked(false);
238 linkageTitle = linkage;
239 break;
240 }
241 libraryDetailsWidget()->linkageGroupBox->setTitle(linkageTitle);
242 }
243
showMacLibraryType(AddLibraryWizard::MacLibraryType libType)244 void LibraryDetailsController::showMacLibraryType(
245 AddLibraryWizard::MacLibraryType libType)
246 {
247 const QString libraryType(tr("Mac:"));
248 QString libraryTypeTitle;
249 switch (libType) {
250 case AddLibraryWizard::FrameworkType:
251 libraryDetailsWidget()->frameworkRadio->setChecked(true);
252 libraryTypeTitle = tr("%1 Framework").arg(libraryType);
253 break;
254 case AddLibraryWizard::LibraryType:
255 libraryDetailsWidget()->libraryRadio->setChecked(true);
256 libraryTypeTitle = tr("%1 Library").arg(libraryType);
257 break;
258 default:
259 libraryDetailsWidget()->frameworkRadio->setChecked(false);
260 libraryDetailsWidget()->libraryRadio->setChecked(false);
261 libraryTypeTitle = libraryType;
262 break;
263 }
264 libraryDetailsWidget()->macGroupBox->setTitle(libraryTypeTitle);
265 }
266
setPlatformsVisible(bool ena)267 void LibraryDetailsController::setPlatformsVisible(bool ena)
268 {
269 libraryDetailsWidget()->platformGroupBox->setVisible(ena);
270 }
271
setLinkageRadiosVisible(bool ena)272 void LibraryDetailsController::setLinkageRadiosVisible(bool ena)
273 {
274 m_linkageRadiosVisible = ena;
275 libraryDetailsWidget()->staticRadio->setVisible(ena);
276 libraryDetailsWidget()->dynamicRadio->setVisible(ena);
277 }
278
setLinkageGroupVisible(bool ena)279 void LibraryDetailsController::setLinkageGroupVisible(bool ena)
280 {
281 setLinkageRadiosVisible(ena);
282 libraryDetailsWidget()->linkageGroupBox->setVisible(ena);
283 }
284
setMacLibraryRadiosVisible(bool ena)285 void LibraryDetailsController::setMacLibraryRadiosVisible(bool ena)
286 {
287 m_macLibraryRadiosVisible = ena;
288 libraryDetailsWidget()->frameworkRadio->setVisible(ena);
289 libraryDetailsWidget()->libraryRadio->setVisible(ena);
290 }
291
setMacLibraryGroupVisible(bool ena)292 void LibraryDetailsController::setMacLibraryGroupVisible(bool ena)
293 {
294 setMacLibraryRadiosVisible(ena);
295 libraryDetailsWidget()->macGroupBox->setVisible(ena);
296 }
297
setLibraryPathChooserVisible(bool ena)298 void LibraryDetailsController::setLibraryPathChooserVisible(bool ena)
299 {
300 libraryDetailsWidget()->libraryTypeComboBox->setVisible(ena);
301 libraryDetailsWidget()->libraryTypeLabel->setVisible(ena);
302 libraryDetailsWidget()->libraryPathChooser->setVisible(ena);
303 libraryDetailsWidget()->libraryFileLabel->setVisible(ena);
304 }
305
setLibraryComboBoxVisible(bool ena)306 void LibraryDetailsController::setLibraryComboBoxVisible(bool ena)
307 {
308 libraryDetailsWidget()->libraryComboBox->setVisible(ena);
309 libraryDetailsWidget()->libraryLabel->setVisible(ena);
310 }
311
setPackageLineEditVisible(bool ena)312 void LibraryDetailsController::setPackageLineEditVisible(bool ena)
313 {
314 libraryDetailsWidget()->packageLineEdit->setVisible(ena);
315 libraryDetailsWidget()->packageLabel->setVisible(ena);
316 }
317
setIncludePathVisible(bool ena)318 void LibraryDetailsController::setIncludePathVisible(bool ena)
319 {
320 m_includePathVisible = ena;
321 libraryDetailsWidget()->includeLabel->setVisible(ena);
322 libraryDetailsWidget()->includePathChooser->setVisible(ena);
323 }
324
setWindowsGroupVisible(bool ena)325 void LibraryDetailsController::setWindowsGroupVisible(bool ena)
326 {
327 m_windowsGroupVisible = ena;
328 libraryDetailsWidget()->winGroupBox->setVisible(ena);
329 }
330
setRemoveSuffixVisible(bool ena)331 void LibraryDetailsController::setRemoveSuffixVisible(bool ena)
332 {
333 libraryDetailsWidget()->removeSuffixCheckBox->setVisible(ena);
334 }
335
isMacLibraryRadiosVisible() const336 bool LibraryDetailsController::isMacLibraryRadiosVisible() const
337 {
338 return m_macLibraryRadiosVisible;
339 }
340
isIncludePathVisible() const341 bool LibraryDetailsController::isIncludePathVisible() const
342 {
343 return m_includePathVisible;
344 }
345
isWindowsGroupVisible() const346 bool LibraryDetailsController::isWindowsGroupVisible() const
347 {
348 return m_windowsGroupVisible;
349 }
350
slotIncludePathChanged()351 void LibraryDetailsController::slotIncludePathChanged()
352 {
353 if (m_ignoreGuiSignals)
354 return;
355 m_includePathChanged = true;
356 }
357
slotPlatformChanged()358 void LibraryDetailsController::slotPlatformChanged()
359 {
360 updateGui();
361 emit completeChanged();
362 }
363
slotMacLibraryTypeChanged()364 void LibraryDetailsController::slotMacLibraryTypeChanged()
365 {
366 if (guiSignalsIgnored())
367 return;
368
369 if (m_linkageRadiosVisible
370 && libraryDetailsWidget()->frameworkRadio->isChecked()) {
371 setIgnoreGuiSignals(true);
372 libraryDetailsWidget()->dynamicRadio->setChecked(true);
373 setIgnoreGuiSignals(false);
374 }
375
376 updateGui();
377 }
378
slotUseSubfoldersChanged(bool ena)379 void LibraryDetailsController::slotUseSubfoldersChanged(bool ena)
380 {
381 if (ena) {
382 libraryDetailsWidget()->addSuffixCheckBox->setChecked(false);
383 libraryDetailsWidget()->removeSuffixCheckBox->setChecked(false);
384 }
385 }
386
slotAddSuffixChanged(bool ena)387 void LibraryDetailsController::slotAddSuffixChanged(bool ena)
388 {
389 if (ena) {
390 libraryDetailsWidget()->useSubfoldersCheckBox->setChecked(false);
391 libraryDetailsWidget()->removeSuffixCheckBox->setChecked(false);
392 }
393 }
394
395 // quote only when the string contains spaces
smartQuote(const QString & aString)396 static QString smartQuote(const QString &aString)
397 {
398 // The OS type is not important in that case, but use always the same
399 // in order not to generate different quoting depending on host platform
400 return Utils::ProcessArgs::quoteArg(aString, Utils::OsTypeLinux);
401 }
402
appendSeparator(const QString & aString)403 static QString appendSeparator(const QString &aString)
404 {
405 if (aString.isEmpty())
406 return aString;
407 if (aString.at(aString.size() - 1) == QLatin1Char('/'))
408 return aString;
409 return aString + QLatin1Char('/');
410 }
411
windowsScopes(AddLibraryWizard::Platforms scopes)412 static QString windowsScopes(AddLibraryWizard::Platforms scopes)
413 {
414 QString scopesString;
415 QTextStream str(&scopesString);
416 AddLibraryWizard::Platforms windowsPlatforms = scopes
417 & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform);
418 if (windowsPlatforms == AddLibraryWizard::WindowsMinGWPlatform)
419 str << "win32-g++"; // mingw only
420 else if (windowsPlatforms == AddLibraryWizard::WindowsMSVCPlatform)
421 str << "win32:!win32-g++"; // msvc only
422 else if (windowsPlatforms)
423 str << "win32"; // both mingw and msvc
424 return scopesString;
425 }
426
commonScopes(AddLibraryWizard::Platforms scopes,AddLibraryWizard::Platforms excludedScopes)427 static QString commonScopes(AddLibraryWizard::Platforms scopes,
428 AddLibraryWizard::Platforms excludedScopes)
429 {
430 QString scopesString;
431 QTextStream str(&scopesString);
432 AddLibraryWizard::Platforms common = scopes | excludedScopes;
433 bool unixLikeScopes = false;
434 if (scopes & ~QFlags<AddLibraryWizard::Platform>(AddLibraryWizard::WindowsMinGWPlatform
435 | AddLibraryWizard::WindowsMSVCPlatform)) {
436 unixLikeScopes = true;
437 if (common & AddLibraryWizard::LinuxPlatform) {
438 str << "unix";
439 if (!(common & AddLibraryWizard::MacPlatform))
440 str << ":!macx";
441 } else {
442 if (scopes & AddLibraryWizard::MacPlatform)
443 str << "macx";
444 }
445 }
446 AddLibraryWizard::Platforms windowsPlatforms = scopes
447 & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform);
448 if (windowsPlatforms) {
449 if (unixLikeScopes)
450 str << "|";
451 str << windowsScopes(windowsPlatforms);
452 }
453 return scopesString;
454 }
455
generateLibsSnippet(AddLibraryWizard::Platforms platforms,AddLibraryWizard::MacLibraryType macLibraryType,const QString & libName,const QString & targetRelativePath,const QString & pwd,bool useSubfolders,bool addSuffix,bool generateLibPath)456 static QString generateLibsSnippet(AddLibraryWizard::Platforms platforms,
457 AddLibraryWizard::MacLibraryType macLibraryType,
458 const QString &libName,
459 const QString &targetRelativePath, const QString &pwd,
460 bool useSubfolders, bool addSuffix, bool generateLibPath)
461 {
462 const QDir targetRelativeDir(targetRelativePath);
463 QString libraryPathSnippet;
464 if (targetRelativeDir.isRelative()) {
465 // it contains: $$[pwd]/
466 libraryPathSnippet = QLatin1String("$$") + pwd + QLatin1Char('/');
467 }
468
469 AddLibraryWizard::Platforms commonPlatforms = platforms;
470 if (macLibraryType == AddLibraryWizard::FrameworkType) // we will generate a separate -F -framework line
471 commonPlatforms &= ~QFlags<AddLibraryWizard::Platform>(AddLibraryWizard::MacPlatform);
472 if (useSubfolders || addSuffix) // we will generate a separate debug/release conditions
473 commonPlatforms &= ~QFlags<AddLibraryWizard::Platform>(AddLibraryWizard::WindowsMinGWPlatform
474 | AddLibraryWizard::WindowsMSVCPlatform);
475
476 AddLibraryWizard::Platforms diffPlatforms = platforms ^ commonPlatforms;
477 AddLibraryWizard::Platforms generatedPlatforms;
478
479 QString snippetMessage;
480 QTextStream str(&snippetMessage);
481
482 AddLibraryWizard::Platforms windowsPlatforms = diffPlatforms
483 & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform);
484 if (windowsPlatforms) {
485 QString windowsString = windowsScopes(windowsPlatforms);
486 str << windowsString << ":CONFIG(release, debug|release): LIBS += ";
487 if (useSubfolders) {
488 if (generateLibPath)
489 str << "-L" << libraryPathSnippet << smartQuote(targetRelativePath + QLatin1String("release/")) << ' ';
490 str << "-l" << libName << "\n";
491 } else if (addSuffix) {
492 if (generateLibPath)
493 str << "-L" << libraryPathSnippet << smartQuote(targetRelativePath) << ' ';
494 str << "-l" << libName << "\n";
495 }
496
497 str << "else:" << windowsString << ":CONFIG(debug, debug|release): LIBS += ";
498 if (useSubfolders) {
499 if (generateLibPath)
500 str << "-L" << libraryPathSnippet << smartQuote(targetRelativePath + QLatin1String("debug/")) << ' ';
501 str << "-l" << libName << "\n";
502 } else if (addSuffix) {
503 if (generateLibPath)
504 str << "-L" << libraryPathSnippet << smartQuote(targetRelativePath) << ' ';
505 str << "-l" << libName << "d\n";
506 }
507 generatedPlatforms |= windowsPlatforms;
508 }
509 if (diffPlatforms & AddLibraryWizard::MacPlatform) {
510 if (generatedPlatforms)
511 str << "else:";
512 str << "mac: LIBS += ";
513 if (generateLibPath)
514 str << "-F" << libraryPathSnippet << smartQuote(targetRelativePath) << ' ';
515 str << "-framework " << libName << "\n";
516 generatedPlatforms |= AddLibraryWizard::MacPlatform;
517 }
518
519 if (commonPlatforms) {
520 if (generatedPlatforms)
521 str << "else:";
522 str << commonScopes(commonPlatforms, generatedPlatforms) << ": LIBS += ";
523 if (generateLibPath)
524 str << "-L" << libraryPathSnippet << smartQuote(targetRelativePath) << ' ';
525 str << "-l" << libName << "\n";
526 }
527 return snippetMessage;
528 }
529
generateIncludePathSnippet(const QString & includeRelativePath)530 static QString generateIncludePathSnippet(const QString &includeRelativePath)
531 {
532 const QDir includeRelativeDir(includeRelativePath);
533 QString includePathSnippet;
534 if (includeRelativeDir.isRelative()) {
535 includePathSnippet = QLatin1String("$$PWD/");
536 }
537 includePathSnippet += smartQuote(includeRelativePath) + QLatin1Char('\n');
538
539 return QLatin1String("\nINCLUDEPATH += ") + includePathSnippet
540 + QLatin1String("DEPENDPATH += ") + includePathSnippet;
541 }
542
generatePreTargetDepsSnippet(AddLibraryWizard::Platforms platforms,AddLibraryWizard::LinkageType linkageType,const QString & libName,const QString & targetRelativePath,const QString & pwd,bool useSubfolders,bool addSuffix)543 static QString generatePreTargetDepsSnippet(AddLibraryWizard::Platforms platforms,
544 AddLibraryWizard::LinkageType linkageType,
545 const QString &libName,
546 const QString &targetRelativePath, const QString &pwd,
547 bool useSubfolders, bool addSuffix)
548 {
549 if (linkageType != AddLibraryWizard::StaticLinkage)
550 return QString();
551
552 const QDir targetRelativeDir(targetRelativePath);
553
554 QString preTargetDepsSnippet = QLatin1String("PRE_TARGETDEPS += ");
555 if (targetRelativeDir.isRelative()) {
556 // it contains: PRE_TARGETDEPS += $$[pwd]/
557 preTargetDepsSnippet += QLatin1String("$$") + pwd + QLatin1Char('/');
558 }
559
560 QString snippetMessage;
561 QTextStream str(&snippetMessage);
562 str << "\n";
563 AddLibraryWizard::Platforms generatedPlatforms;
564 AddLibraryWizard::Platforms windowsPlatforms = platforms
565 & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform);
566 AddLibraryWizard::Platforms commonPlatforms = platforms;
567 if (useSubfolders || addSuffix) // we will generate a separate debug/release conditions, otherwise mingw is unix like
568 commonPlatforms &= ~QFlags<AddLibraryWizard::Platform>(AddLibraryWizard::WindowsMinGWPlatform);
569 commonPlatforms &= ~QFlags<AddLibraryWizard::Platform>(AddLibraryWizard::WindowsMSVCPlatform); // this case is different from all platforms
570 if (windowsPlatforms) {
571 if (useSubfolders || addSuffix) {
572 if (windowsPlatforms & AddLibraryWizard::WindowsMinGWPlatform) {
573 str << "win32-g++:CONFIG(release, debug|release): "
574 << preTargetDepsSnippet;
575 if (useSubfolders)
576 str << smartQuote(targetRelativePath + QLatin1String("release/lib") + libName + QLatin1String(".a")) << '\n';
577 else if (addSuffix)
578 str << smartQuote(targetRelativePath + QLatin1String("lib") + libName + QLatin1String(".a")) << '\n';
579
580 str << "else:win32-g++:CONFIG(debug, debug|release): "
581 << preTargetDepsSnippet;
582 if (useSubfolders)
583 str << smartQuote(targetRelativePath + QLatin1String("debug/lib") + libName + QLatin1String(".a")) << '\n';
584 else if (addSuffix)
585 str << smartQuote(targetRelativePath + QLatin1String("lib") + libName + QLatin1String("d.a")) << '\n';
586 }
587 if (windowsPlatforms & AddLibraryWizard::WindowsMSVCPlatform) {
588 if (windowsPlatforms & AddLibraryWizard::WindowsMinGWPlatform)
589 str << "else:";
590 str << "win32:!win32-g++:CONFIG(release, debug|release): "
591 << preTargetDepsSnippet;
592 if (useSubfolders)
593 str << smartQuote(targetRelativePath + QLatin1String("release/") + libName + QLatin1String(".lib")) << '\n';
594 else if (addSuffix)
595 str << smartQuote(targetRelativePath + libName + QLatin1String(".lib")) << '\n';
596
597 str << "else:win32:!win32-g++:CONFIG(debug, debug|release): "
598 << preTargetDepsSnippet;
599 if (useSubfolders)
600 str << smartQuote(targetRelativePath + QLatin1String("debug/") + libName + QLatin1String(".lib")) << '\n';
601 else if (addSuffix)
602 str << smartQuote(targetRelativePath + libName + QLatin1String("d.lib")) << '\n';
603 }
604 generatedPlatforms |= windowsPlatforms;
605 } else {
606 if (windowsPlatforms & AddLibraryWizard::WindowsMSVCPlatform) {
607 str << "win32:!win32-g++: " << preTargetDepsSnippet
608 << smartQuote(targetRelativePath + libName + QLatin1String(".lib")) << "\n";
609 generatedPlatforms |= AddLibraryWizard::WindowsMSVCPlatform; // mingw will be handled with common scopes
610 }
611 // mingw not generated yet, will be joined with unix like
612 }
613 }
614 if (commonPlatforms) {
615 if (generatedPlatforms)
616 str << "else:";
617 str << commonScopes(commonPlatforms, generatedPlatforms) << ": "
618 << preTargetDepsSnippet << smartQuote(targetRelativePath + QLatin1String("lib") + libName + QLatin1String(".a")) << "\n";
619 }
620 return snippetMessage;
621 }
622
NonInternalLibraryDetailsController(Ui::LibraryDetailsWidget * libraryDetails,const QString & proFile,QObject * parent)623 NonInternalLibraryDetailsController::NonInternalLibraryDetailsController(
624 Ui::LibraryDetailsWidget *libraryDetails,
625 const QString &proFile, QObject *parent) :
626 LibraryDetailsController(libraryDetails, proFile, parent)
627 {
628 setLibraryComboBoxVisible(false);
629 setLibraryPathChooserVisible(true);
630
631 connect(libraryDetailsWidget()->libraryPathChooser, &Utils::PathChooser::validChanged,
632 this, &LibraryDetailsController::completeChanged);
633 connect(libraryDetailsWidget()->libraryPathChooser, &Utils::PathChooser::rawPathChanged,
634 this, &NonInternalLibraryDetailsController::slotLibraryPathChanged);
635 connect(libraryDetailsWidget()->removeSuffixCheckBox, &QAbstractButton::toggled,
636 this, &NonInternalLibraryDetailsController::slotRemoveSuffixChanged);
637 connect(libraryDetailsWidget()->dynamicRadio, &QAbstractButton::clicked,
638 this, &NonInternalLibraryDetailsController::slotLinkageTypeChanged);
639 connect(libraryDetailsWidget()->staticRadio, &QAbstractButton::clicked,
640 this, &NonInternalLibraryDetailsController::slotLinkageTypeChanged);
641 connect(libraryDetailsWidget()->libraryTypeComboBox, &QComboBox::currentTextChanged,
642 this, &NonInternalLibraryDetailsController::slotLibraryTypeChanged);
643 handleLibraryTypeChange();
644 }
645
suggestedLinkageType() const646 AddLibraryWizard::LinkageType NonInternalLibraryDetailsController::suggestedLinkageType() const
647 {
648 AddLibraryWizard::LinkageType type = AddLibraryWizard::NoLinkage;
649 if (libraryPlatformType() != Utils::OsTypeWindows) {
650 if (libraryDetailsWidget()->libraryPathChooser->isValid()) {
651 QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
652 if (fi.suffix() == QLatin1String("a"))
653 type = AddLibraryWizard::StaticLinkage;
654 else
655 type = AddLibraryWizard::DynamicLinkage;
656 }
657 }
658 return type;
659 }
660
suggestedMacLibraryType() const661 AddLibraryWizard::MacLibraryType NonInternalLibraryDetailsController::suggestedMacLibraryType() const
662 {
663 AddLibraryWizard::MacLibraryType type = AddLibraryWizard::NoLibraryType;
664 if (libraryPlatformType() == Utils::OsTypeMac) {
665 if (libraryDetailsWidget()->libraryPathChooser->isValid()) {
666 QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
667 if (fi.suffix() == QLatin1String("framework"))
668 type = AddLibraryWizard::FrameworkType;
669 else
670 type = AddLibraryWizard::LibraryType;
671 }
672 }
673 return type;
674 }
675
suggestedIncludePath() const676 QString NonInternalLibraryDetailsController::suggestedIncludePath() const
677 {
678 QString includePath;
679 if (libraryDetailsWidget()->libraryPathChooser->isValid()) {
680 QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
681 includePath = fi.absolutePath();
682 QFileInfo dfi(includePath);
683 // TODO: Win: remove debug or release folder first if appropriate
684 if (dfi.fileName() == QLatin1String("lib")) {
685 QDir dir = dfi.absoluteDir();
686 includePath = dir.absolutePath();
687 QDir includeDir(dir.absoluteFilePath(QLatin1String("include")));
688 if (includeDir.exists())
689 includePath = includeDir.absolutePath();
690 }
691 }
692 return includePath;
693 }
694
updateWindowsOptionsEnablement()695 void NonInternalLibraryDetailsController::updateWindowsOptionsEnablement()
696 {
697 bool ena = platforms() & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform);
698 if (libraryPlatformType() == Utils::OsTypeWindows) {
699 libraryDetailsWidget()->addSuffixCheckBox->setEnabled(ena);
700 ena = true;
701 }
702 libraryDetailsWidget()->winGroupBox->setEnabled(ena);
703 }
704
handleLinkageTypeChange()705 void NonInternalLibraryDetailsController::handleLinkageTypeChange()
706 {
707 if (isMacLibraryRadiosVisible()
708 && libraryDetailsWidget()->staticRadio->isChecked()) {
709 setIgnoreGuiSignals(true);
710 libraryDetailsWidget()->libraryRadio->setChecked(true);
711 setIgnoreGuiSignals(false);
712 }
713 }
714
slotLinkageTypeChanged()715 void NonInternalLibraryDetailsController::slotLinkageTypeChanged()
716 {
717 if (guiSignalsIgnored())
718 return;
719
720 handleLinkageTypeChange();
721 updateGui();
722 }
723
slotRemoveSuffixChanged(bool ena)724 void NonInternalLibraryDetailsController::slotRemoveSuffixChanged(bool ena)
725 {
726 if (ena) {
727 libraryDetailsWidget()->useSubfoldersCheckBox->setChecked(false);
728 libraryDetailsWidget()->addSuffixCheckBox->setChecked(false);
729 }
730 }
731
handleLibraryTypeChange()732 void NonInternalLibraryDetailsController::handleLibraryTypeChange()
733 {
734 libraryDetailsWidget()->libraryPathChooser->setPromptDialogFilter(libraryPlatformFilter());
735 const bool isMacOs = libraryPlatformType() == Utils::OsTypeMac;
736 const bool isWindows = libraryPlatformType() == Utils::OsTypeWindows;
737 libraryDetailsWidget()->libraryPathChooser->setExpectedKind(isMacOs ? Utils::PathChooser::Any
738 : Utils::PathChooser::File);
739 setMacLibraryRadiosVisible(!isMacOs);
740 setLinkageRadiosVisible(isWindows);
741 setRemoveSuffixVisible(isWindows);
742 handleLibraryPathChange();
743 handleLinkageTypeChange();
744 }
745
slotLibraryTypeChanged()746 void NonInternalLibraryDetailsController::slotLibraryTypeChanged()
747 {
748 handleLibraryTypeChange();
749 updateGui();
750 emit completeChanged();
751 }
752
handleLibraryPathChange()753 void NonInternalLibraryDetailsController::handleLibraryPathChange()
754 {
755 if (libraryPlatformType() == Utils::OsTypeWindows) {
756 bool subfoldersEnabled = true;
757 bool removeSuffixEnabled = true;
758 if (libraryDetailsWidget()->libraryPathChooser->isValid()) {
759 QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
760 QFileInfo dfi(fi.absolutePath());
761 const QString parentFolderName = dfi.fileName().toLower();
762 if (parentFolderName != QLatin1String("debug") &&
763 parentFolderName != QLatin1String("release"))
764 subfoldersEnabled = false;
765 const QString baseName = fi.completeBaseName();
766
767 if (baseName.isEmpty() || baseName.at(baseName.size() - 1).toLower() != QLatin1Char('d'))
768 removeSuffixEnabled = false;
769
770 if (subfoldersEnabled)
771 libraryDetailsWidget()->useSubfoldersCheckBox->setChecked(true);
772 else if (removeSuffixEnabled)
773 libraryDetailsWidget()->removeSuffixCheckBox->setChecked(true);
774 else
775 libraryDetailsWidget()->addSuffixCheckBox->setChecked(true);
776 }
777 }
778 }
779
slotLibraryPathChanged()780 void NonInternalLibraryDetailsController::slotLibraryPathChanged()
781 {
782 handleLibraryPathChange();
783 updateGui();
784 emit completeChanged();
785 }
786
isComplete() const787 bool NonInternalLibraryDetailsController::isComplete() const
788 {
789 return libraryDetailsWidget()->libraryPathChooser->isValid() &&
790 platforms();
791 }
792
snippet() const793 QString NonInternalLibraryDetailsController::snippet() const
794 {
795 QString libPath = libraryDetailsWidget()->libraryPathChooser->filePath().toString();
796 QFileInfo fi(libPath);
797 QString libName;
798 const bool removeSuffix = isWindowsGroupVisible()
799 && libraryDetailsWidget()->removeSuffixCheckBox->isChecked();
800 if (libraryPlatformType() == Utils::OsTypeWindows) {
801 libName = fi.completeBaseName();
802 if (removeSuffix && !libName.isEmpty()) // remove last letter which needs to be "d"
803 libName = libName.left(libName.size() - 1);
804 if (fi.completeSuffix() == QLatin1String("a")) // the mingw lib case
805 libName = libName.mid(3); // cut the "lib" prefix
806 } else if (libraryPlatformType() == Utils::OsTypeMac) {
807 if (macLibraryType() == AddLibraryWizard::FrameworkType)
808 libName = fi.completeBaseName();
809 else
810 libName = fi.completeBaseName().mid(3); // cut the "lib" prefix
811 } else {
812 libName = fi.completeBaseName().mid(3); // cut the "lib" prefix
813 }
814
815 bool useSubfolders = false;
816 bool addSuffix = false;
817 if (isWindowsGroupVisible()) {
818 // when we are on Win but we don't generate the code for Win
819 // we still need to remove "debug" or "release" subfolder
820 const bool useSubfoldersCondition = (libraryPlatformType() == Utils::OsTypeWindows)
821 ? true : platforms() & (AddLibraryWizard::WindowsMinGWPlatform
822 | AddLibraryWizard::WindowsMSVCPlatform);
823 if (useSubfoldersCondition)
824 useSubfolders = libraryDetailsWidget()->useSubfoldersCheckBox->isChecked();
825 if (platforms() & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform))
826 addSuffix = libraryDetailsWidget()->addSuffixCheckBox->isChecked() || removeSuffix;
827 }
828
829 QString targetRelativePath;
830 QString includeRelativePath;
831 if (isIncludePathVisible()) { // generate also the path to lib
832 QFileInfo pfi(proFile());
833 QDir pdir = pfi.absoluteDir();
834 QString absoluteLibraryPath = fi.absolutePath();
835 if (libraryPlatformType() == Utils::OsTypeWindows && useSubfolders) { // drop last subfolder which needs to be "debug" or "release"
836 QFileInfo libfi(absoluteLibraryPath);
837 absoluteLibraryPath = libfi.absolutePath();
838 }
839 targetRelativePath = appendSeparator(pdir.relativeFilePath(absoluteLibraryPath));
840
841 const QString includePath = libraryDetailsWidget()->includePathChooser->filePath().toString();
842 if (!includePath.isEmpty())
843 includeRelativePath = pdir.relativeFilePath(includePath);
844 }
845
846 QString snippetMessage;
847 QTextStream str(&snippetMessage);
848 str << "\n";
849 str << generateLibsSnippet(platforms(), macLibraryType(), libName,
850 targetRelativePath, QLatin1String("PWD"),
851 useSubfolders, addSuffix, isIncludePathVisible());
852 if (isIncludePathVisible()) {
853 str << generateIncludePathSnippet(includeRelativePath);
854 str << generatePreTargetDepsSnippet(platforms(), linkageType(), libName,
855 targetRelativePath, QLatin1String("PWD"),
856 useSubfolders, addSuffix);
857 }
858 return snippetMessage;
859 }
860
861 /////////////
862
PackageLibraryDetailsController(Ui::LibraryDetailsWidget * libraryDetails,const QString & proFile,QObject * parent)863 PackageLibraryDetailsController::PackageLibraryDetailsController(
864 Ui::LibraryDetailsWidget *libraryDetails,
865 const QString &proFile, QObject *parent)
866 : NonInternalLibraryDetailsController(libraryDetails, proFile, parent)
867 {
868 setPlatformsVisible(false);
869 setIncludePathVisible(false);
870 setWindowsGroupVisible(false);
871 setLinkageGroupVisible(false);
872 setMacLibraryGroupVisible(false);
873 setLibraryPathChooserVisible(false);
874 setPackageLineEditVisible(true);
875
876 connect(libraryDetailsWidget()->packageLineEdit, &QLineEdit::textChanged,
877 this, &LibraryDetailsController::completeChanged);
878
879 updateGui();
880 }
881
isComplete() const882 bool PackageLibraryDetailsController::isComplete() const
883 {
884 return !libraryDetailsWidget()->packageLineEdit->text().isEmpty();
885 }
886
snippet() const887 QString PackageLibraryDetailsController::snippet() const
888 {
889 QString snippetMessage;
890 QTextStream str(&snippetMessage);
891 str << "\n";
892 if (!isLinkPackageGenerated())
893 str << "unix: CONFIG += link_pkgconfig\n";
894 str << "unix: PKGCONFIG += " << libraryDetailsWidget()->packageLineEdit->text() << "\n";
895 return snippetMessage;
896 }
897
isLinkPackageGenerated() const898 bool PackageLibraryDetailsController::isLinkPackageGenerated() const
899 {
900 const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(proFile()));
901 if (!project)
902 return false;
903
904 const ProjectNode *projectNode = project->findNodeForBuildKey(proFile());
905 if (!projectNode)
906 return false;
907
908 const QmakeProFileNode *currentProject =
909 dynamic_cast<const QmakeProFileNode *>(projectNode);
910 if (!currentProject)
911 return false;
912
913 const QStringList configVar = currentProject->variableValue(Variable::Config);
914 if (configVar.contains(QLatin1String("link_pkgconfig")))
915 return true;
916
917 return false;
918 }
919
920 /////////////
921
SystemLibraryDetailsController(Ui::LibraryDetailsWidget * libraryDetails,const QString & proFile,QObject * parent)922 SystemLibraryDetailsController::SystemLibraryDetailsController(
923 Ui::LibraryDetailsWidget *libraryDetails,
924 const QString &proFile, QObject *parent)
925 : NonInternalLibraryDetailsController(libraryDetails, proFile, parent)
926 {
927 setIncludePathVisible(false);
928 setWindowsGroupVisible(false);
929
930 updateGui();
931 }
932
933 /////////////
934
ExternalLibraryDetailsController(Ui::LibraryDetailsWidget * libraryDetails,const QString & proFile,QObject * parent)935 ExternalLibraryDetailsController::ExternalLibraryDetailsController(
936 Ui::LibraryDetailsWidget *libraryDetails,
937 const QString &proFile, QObject *parent)
938 : NonInternalLibraryDetailsController(libraryDetails, proFile, parent)
939 {
940 setIncludePathVisible(true);
941 setWindowsGroupVisible(true);
942
943 updateGui();
944 }
945
updateWindowsOptionsEnablement()946 void ExternalLibraryDetailsController::updateWindowsOptionsEnablement()
947 {
948 NonInternalLibraryDetailsController::updateWindowsOptionsEnablement();
949
950 bool subfoldersEnabled = true;
951 bool removeSuffixEnabled = true;
952 if (libraryPlatformType() == Utils::OsTypeWindows
953 && libraryDetailsWidget()->libraryPathChooser->isValid()) {
954 QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
955 QFileInfo dfi(fi.absolutePath());
956 const QString parentFolderName = dfi.fileName().toLower();
957 if (parentFolderName != QLatin1String("debug") &&
958 parentFolderName != QLatin1String("release"))
959 subfoldersEnabled = false;
960 const QString baseName = fi.completeBaseName();
961
962 if (baseName.isEmpty() || baseName.at(baseName.size() - 1).toLower() != QLatin1Char('d'))
963 removeSuffixEnabled = false;
964 }
965 libraryDetailsWidget()->useSubfoldersCheckBox->setEnabled(subfoldersEnabled);
966 libraryDetailsWidget()->removeSuffixCheckBox->setEnabled(removeSuffixEnabled);
967 }
968
969 /////////////
970
InternalLibraryDetailsController(Ui::LibraryDetailsWidget * libraryDetails,const QString & proFile,QObject * parent)971 InternalLibraryDetailsController::InternalLibraryDetailsController(
972 Ui::LibraryDetailsWidget *libraryDetails,
973 const QString &proFile, QObject *parent)
974 : LibraryDetailsController(libraryDetails, proFile, parent)
975 {
976 setLinkageRadiosVisible(false);
977 setLibraryPathChooserVisible(false);
978 setLibraryComboBoxVisible(true);
979 setIncludePathVisible(true);
980 setWindowsGroupVisible(true);
981 setRemoveSuffixVisible(false);
982
983 if (Utils::HostOsInfo::isWindowsHost())
984 libraryDetailsWidget()->useSubfoldersCheckBox->setEnabled(true);
985
986 connect(libraryDetailsWidget()->libraryComboBox,
987 QOverload<int>::of(&QComboBox::currentIndexChanged),
988 this, &InternalLibraryDetailsController::slotCurrentLibraryChanged);
989
990 updateProFile();
991 updateGui();
992 }
993
suggestedLinkageType() const994 AddLibraryWizard::LinkageType InternalLibraryDetailsController::suggestedLinkageType() const
995 {
996 const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex();
997 AddLibraryWizard::LinkageType type = AddLibraryWizard::NoLinkage;
998 if (currentIndex >= 0) {
999 QmakeProFile *proFile = m_proFiles.at(currentIndex);
1000 const QStringList configVar = proFile->variableValue(Variable::Config);
1001 if (configVar.contains(QLatin1String("staticlib"))
1002 || configVar.contains(QLatin1String("static")))
1003 type = AddLibraryWizard::StaticLinkage;
1004 else
1005 type = AddLibraryWizard::DynamicLinkage;
1006 }
1007 return type;
1008 }
1009
suggestedMacLibraryType() const1010 AddLibraryWizard::MacLibraryType InternalLibraryDetailsController::suggestedMacLibraryType() const
1011 {
1012 const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex();
1013 AddLibraryWizard::MacLibraryType type = AddLibraryWizard::NoLibraryType;
1014 if (currentIndex >= 0) {
1015 QmakeProFile *proFile = m_proFiles.at(currentIndex);
1016 const QStringList configVar = proFile->variableValue(Variable::Config);
1017 if (configVar.contains(QLatin1String("lib_bundle")))
1018 type = AddLibraryWizard::FrameworkType;
1019 else
1020 type = AddLibraryWizard::LibraryType;
1021 }
1022 return type;
1023 }
1024
suggestedIncludePath() const1025 QString InternalLibraryDetailsController::suggestedIncludePath() const
1026 {
1027 const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex();
1028 if (currentIndex >= 0) {
1029 QmakeProFile *proFile = m_proFiles.at(currentIndex);
1030 return proFile->filePath().toFileInfo().absolutePath();
1031 }
1032 return QString();
1033 }
1034
updateWindowsOptionsEnablement()1035 void InternalLibraryDetailsController::updateWindowsOptionsEnablement()
1036 {
1037 if (Utils::HostOsInfo::isWindowsHost())
1038 libraryDetailsWidget()->addSuffixCheckBox->setEnabled(true);
1039 libraryDetailsWidget()->winGroupBox->setEnabled(platforms()
1040 & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform));
1041 }
1042
updateProFile()1043 void InternalLibraryDetailsController::updateProFile()
1044 {
1045 m_rootProjectPath.clear();
1046 m_proFiles.clear();
1047 libraryDetailsWidget()->libraryComboBox->clear();
1048
1049 const QmakeProject *project
1050 = dynamic_cast<QmakeProject *>(SessionManager::projectForFile(Utils::FilePath::fromString(proFile())));
1051 if (!project)
1052 return;
1053
1054 setIgnoreGuiSignals(true);
1055
1056 m_rootProjectPath = project->projectDirectory().toString();
1057
1058 auto t = project->activeTarget();
1059 auto bs = dynamic_cast<QmakeBuildSystem *>(t ? t->buildSystem() : nullptr);
1060 QTC_ASSERT(bs, return);
1061
1062 QDir rootDir(m_rootProjectPath);
1063 foreach (QmakeProFile *proFile, bs->rootProFile()->allProFiles()) {
1064 QmakeProjectManager::ProjectType type = proFile->projectType();
1065 if (type != ProjectType::SharedLibraryTemplate && type != ProjectType::StaticLibraryTemplate)
1066 continue;
1067
1068 const QStringList configVar = proFile->variableValue(Variable::Config);
1069 if (!configVar.contains(QLatin1String("plugin"))) {
1070 const QString relProFilePath = rootDir.relativeFilePath(proFile->filePath().toString());
1071 TargetInformation targetInfo = proFile->targetInformation();
1072 const QString itemToolTip = QString::fromLatin1("%1 (%2)").arg(targetInfo.target).arg(relProFilePath);
1073 m_proFiles.append(proFile);
1074
1075 libraryDetailsWidget()->libraryComboBox->addItem(targetInfo.target);
1076 libraryDetailsWidget()->libraryComboBox->setItemData(
1077 libraryDetailsWidget()->libraryComboBox->count() - 1,
1078 itemToolTip, Qt::ToolTipRole);
1079 }
1080 }
1081
1082 setIgnoreGuiSignals(false);
1083 }
1084
slotCurrentLibraryChanged()1085 void InternalLibraryDetailsController::slotCurrentLibraryChanged()
1086 {
1087 const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex();
1088 if (currentIndex >= 0) {
1089 libraryDetailsWidget()->libraryComboBox->setToolTip(
1090 libraryDetailsWidget()->libraryComboBox->itemData(
1091 currentIndex, Qt::ToolTipRole).toString());
1092 QmakeProFile *proFile = m_proFiles.at(currentIndex);
1093 const QStringList configVar = proFile->variableValue(Variable::Config);
1094 if (Utils::HostOsInfo::isWindowsHost()) {
1095 bool useSubfolders = false;
1096 if (configVar.contains(QLatin1String("debug_and_release"))
1097 && configVar.contains(QLatin1String("debug_and_release_target")))
1098 useSubfolders = true;
1099 libraryDetailsWidget()->useSubfoldersCheckBox->setChecked(useSubfolders);
1100 libraryDetailsWidget()->addSuffixCheckBox->setChecked(!useSubfolders);
1101 }
1102 }
1103
1104 if (guiSignalsIgnored())
1105 return;
1106
1107 updateGui();
1108
1109 emit completeChanged();
1110 }
1111
isComplete() const1112 bool InternalLibraryDetailsController::isComplete() const
1113 {
1114 return libraryDetailsWidget()->libraryComboBox->count() && platforms();
1115 }
1116
snippet() const1117 QString InternalLibraryDetailsController::snippet() const
1118 {
1119 const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex();
1120
1121 if (currentIndex < 0)
1122 return QString();
1123
1124 if (m_rootProjectPath.isEmpty())
1125 return QString();
1126
1127
1128 // dir of the root project
1129 QDir rootDir(m_rootProjectPath);
1130
1131 // relative path for the project for which we insert the snippet,
1132 // it's relative to the root project
1133 const QString proRelavitePath = rootDir.relativeFilePath(proFile());
1134
1135 // project for which we insert the snippet
1136 const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(proFile()));
1137
1138 // the build directory of the active build configuration
1139 QDir rootBuildDir = rootDir; // If the project is unconfigured use the project dir
1140 if (ProjectExplorer::Target *t = project->activeTarget())
1141 if (ProjectExplorer::BuildConfiguration *bc = t->activeBuildConfiguration())
1142 rootBuildDir.setPath(bc->buildDirectory().toString());
1143
1144 // the project for which we insert the snippet inside build tree
1145 QFileInfo pfi(rootBuildDir.filePath(proRelavitePath));
1146 // the project dir for which we insert the snippet inside build tree
1147 QDir projectBuildDir(pfi.absolutePath());
1148
1149 // current project node from combobox
1150 QFileInfo fi(proFile());
1151 QDir projectSrcDir(fi.absolutePath());
1152
1153 // project node which we want to link against
1154 TargetInformation targetInfo = m_proFiles.at(currentIndex)->targetInformation();
1155
1156 const QString targetRelativePath = appendSeparator(projectBuildDir.relativeFilePath(targetInfo.buildDir.toString()));
1157 const QString includeRelativePath = projectSrcDir.relativeFilePath(libraryDetailsWidget()->includePathChooser->filePath().toString());
1158
1159 const bool useSubfolders = libraryDetailsWidget()->useSubfoldersCheckBox->isChecked();
1160 const bool addSuffix = libraryDetailsWidget()->addSuffixCheckBox->isChecked();
1161
1162 QString snippetMessage;
1163 QTextStream str(&snippetMessage);
1164 str << "\n";
1165
1166 // replace below to "PRI_OUT_PWD" when task QTBUG-13057 is done
1167 // (end enable adding libraries into .pri files as well).
1168 const QString outPwd = QLatin1String("OUT_PWD");
1169 str << generateLibsSnippet(platforms(), macLibraryType(), targetInfo.target,
1170 targetRelativePath, outPwd,
1171 useSubfolders, addSuffix, true);
1172 str << generateIncludePathSnippet(includeRelativePath);
1173 str << generatePreTargetDepsSnippet(platforms(), linkageType(), targetInfo.target,
1174 targetRelativePath, outPwd,
1175 useSubfolders, addSuffix);
1176 return snippetMessage;
1177 }
1178