Merge remote-tracking branch 'origin/3.3'

Change-Id: I0ab4982e229d475b8e3575414b4bebbfea07498d
This commit is contained in:
Eike Ziller
2014-11-12 12:55:00 +01:00
217 changed files with 2087 additions and 1620 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -457,7 +457,7 @@
\li To continue running the program, press \key{F5}.
\li To run to the line containing the cursor, press \ke{yCtrl+F10}
\li To run to the line containing the cursor, press \key{Ctrl+F10}
(\key{Shift+F8} on OS X).
\li To run to the selected function when you are stepping into a nested

View File

@@ -94,11 +94,6 @@
You can change the configuration of preconfigured tools and configure
additional tools in \QC \gui Options.
You can use \QC variables in the fields that you can select from
lists of available \QC variables (1).
\image qtcreator-external-tools.png "External Tools options"
To configure external tools:
\list 1

View File

@@ -612,7 +612,7 @@
\li Alt+Z, Alt+C
\li Alt+C, Alt+C
\li Alt+G, Alt+C
\li Alt+H, Alt+C
\li Alt+G, Alt+C
\li Alt+P, Alt+S
\li Alt+S, Alt+C
\row
@@ -620,7 +620,7 @@
\li Alt+Z, Alt+D
\li Alt+C, Alt+D
\li Alt+G, Alt+D
\li Alt+H, Alt+D
\li Alt+G, Alt+D
\li
\li Alt+S, Alt+D
\row
@@ -644,7 +644,7 @@
\li Alt+Z, Alt+L
\li
\li Alt+G, Alt+L
\li Alt+H, Alt+L
\li Alt+G, Alt+L
\li Alt+P, Alt+F
\li
\row
@@ -660,7 +660,7 @@
\li Alt+Z, Alt+S
\li
\li
\li Alt+H, Alt+S
\li Alt+G, Alt+S
\li
\li
\row

View File

@@ -96,17 +96,10 @@
You can use \QC variables in arguments, executable paths, and working
directories. The variables take care of quoting their expansions, so you do
not need to put them in quotes.
The following \QC variables are available:
\list
\li %{buildDir}
\li %{sourceDir}
\endlist
not need to put them in quotes. Select the
\inlineimage qtcreator-variables-button.png
(\gui {Variables}) button in a field to select from a list of variables that
are available in a particular context.
\section1 Build Steps

View File

@@ -31,7 +31,7 @@
\title Qt Quick UI Forms
You can use \QC wizards to create UI forms tha have the filename extension
You can use \QC wizards to create UI forms that have the filename extension
\e .ui.qml. The UI forms contain a purely declarative subset of the QML
language. It is recommended that you edit the forms in the \gui Design mode.
\QC enforces the use of the supported QML features by displaying error

View File

@@ -1,6 +1,5 @@
import qbs
import qbs.FileInfo
import QtcProduct
QtcProduct {
type: "application"

View File

@@ -1,6 +1,5 @@
import qbs 1.0
import QtcFunctions
import QtcProduct
QtcProduct {
type: "dynamiclibrary"

View File

@@ -1,7 +1,6 @@
import qbs 1.0
import qbs.FileInfo
import QtcFunctions
import QtcProduct
QtcProduct {
type: ["dynamiclibrary", "pluginSpec"]

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcProduct
QtcProduct {
type: "application" // no Mac app bundle

View File

@@ -1582,6 +1582,12 @@ def qdump__QRegion(d, value):
ns = d.qtNamespace()
rectType = d.lookupType(ns + "QRect")
d.putIntItem("numRects", n)
if d.qtVersion() >= 0x050400:
# Changed in ee324e4ed
d.putSubItem("extents", d.createValue(pp + 8 + v, rectType))
d.putSubItem("innerRect", d.createValue(pp + 8 + v + rectType.sizeof, rectType))
d.putIntItem("innerArea", d.extractInt(pp + 4))
else:
d.putSubItem("extents", d.createValue(pp + 2 * v, rectType))
d.putSubItem("innerRect", d.createValue(pp + 2 * v + rectType.sizeof, rectType))
d.putIntItem("innerArea", d.extractInt(pp + 2 * v + 2 * rectType.sizeof))
@@ -1589,7 +1595,7 @@ def qdump__QRegion(d, value):
try:
# Can fail if QVector<QRect> debuginfo is missing.
vectType = d.lookupType("%sQVector<%sQRect>" % (ns, ns))
d.putSubItem("rects", d.createValue(pp + v, vectType))
d.putSubItem("rects", d.createValue(pp + 8, vectType))
except:
with SubItem(d, "rects"):
d.putItemCount(n)

View File

@@ -1,6 +1,6 @@
Label {
text: "%1"
toolTip: "%1"
tooltip: "%1"
}
CheckBox {

View File

@@ -1,6 +1,6 @@
Label {
text: "%1"
toolTip: "%1"
tooltip: "%1"
}
SpinBox {
maximumValue: 9999999

View File

@@ -1,6 +1,6 @@
Label {
text: "%1"
toolTip: "%1"
tooltip: "%1"
}
SpinBox {
maximumValue: 9999999

View File

@@ -1,6 +1,6 @@
Label {
text: "%1"
toolTip: "%1"
tooltip: "%1"
}
LineEdit {
backendValue: backendValues.%2

View File

@@ -1,6 +1,6 @@
Label {
text: "%1"
toolTip: "%1"
tooltip: "%1"
}
LineEdit {
backendValue: backendValues.%2

View File

@@ -50,7 +50,7 @@ Column {
ComboBox {
model: ["LeftToRight", "TopToBottom"]
backendValue: backendValues.flow
scope: "Qt"
scope: "Flow"
}
ExpandingSpacer {

View File

@@ -85,7 +85,7 @@ Column {
model: ["LeftToRight", "TopToBottom"]
backendValue: backendValues.flow
Layout.fillWidth: true
scope: "Qt"
scope: "Grid"
}
}

View File

@@ -45,6 +45,11 @@
"source": "file.pro",
"target": "%{ProFileName}",
"openAsProject": true
},
{
"source": "../git.ignore",
"target": "%{ProjectDirectory}/.gitignore",
"condition": "%{JS: ('%{VersionControl}%{IsSubproject}' === 'G.Git') ? 'yes' : ''}"
}
]
}

View File

@@ -0,0 +1,72 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe

View File

@@ -73,8 +73,8 @@ ProgressBarColorFinished=ff5aaa3c
ProgressBarColorNormal=hoverBackground
ProgressBarTitleColor=text
QtOutputFormatter_LinkTextColor=ff0000ff
SearchResultWidgetBackgroundColor=shadowBackground
SearchResultWidgetTextColor=text
InfoBarBackground=shadowBackground
InfoBarText=text
TextColorDisabled=textDisabled
TextColorHighlight=ffff0000
TextColorNormal=text
@@ -84,7 +84,8 @@ ToolBarBackgroundColor=shadowBackground
TreeViewArrowColorNormal=hoverBackground
TreeViewArrowColorSelected=text
Welcome_BackgroundColorNormal=normalBackground
Welcome_Button_BorderColor=0
Welcome_Button_BorderColorNormal=0
Welcome_Button_BorderColorPressed=0
Welcome_Button_TextColorNormal=ffe7e7e7
Welcome_Button_TextColorPressed=ffffffff
Welcome_Caption_TextColorNormal=ff4acb47

View File

@@ -67,8 +67,8 @@ ProgressBarColorFinished=ff5aaa3c
ProgressBarColorNormal=b4ffffff
ProgressBarTitleColor=ffffffff
QtOutputFormatter_LinkTextColor=ff0000aa
SearchResultWidgetBackgroundColor=ffffffff
SearchResultWidgetTextColor=ff000000
InfoBarBackground=ffffffe1
InfoBarText=ff000000
TextColorDisabled=ff000000
TextColorHighlight=ffa0a0a4
TextColorNormal=ff000000
@@ -78,7 +78,8 @@ ToolBarBackgroundColor=ffff0000
TreeViewArrowColorNormal=ffff0000
TreeViewArrowColorSelected=ffff0000
Welcome_BackgroundColorNormal=ffffffff
Welcome_Button_BorderColor=ff737373
Welcome_Button_BorderColorNormal=ff737373
Welcome_Button_BorderColorPressed=ff333333
Welcome_Button_TextColorNormal=ff000000
Welcome_Button_TextColorPressed=ffc0c0c0
Welcome_Caption_TextColorNormal=ff328930

View File

@@ -40,7 +40,7 @@ Controls.ScrollView {
Item {
id: canvas
implicitWidth: childrenRect.width + 200
implicitWidth: childrenRect.width
implicitHeight: childrenRect.height
Button {
@@ -97,8 +97,6 @@ Controls.ScrollView {
anchors.top: recentProjectsTitle.bottom
anchors.topMargin: 20
anchors.right: parent.right
anchors.rightMargin: 60
model: projectList
}

View File

@@ -86,7 +86,7 @@ Button {
color: (creatorTheme.WidgetStyle === 'StyleFlat') ? "#232323" : "#eeeeee"
}
}
border.color: creatorTheme.Welcome_Button_BorderColor
border.color: creatorTheme.Welcome_Button_BorderColorNormal
}
Rectangle {
@@ -114,7 +114,7 @@ Button {
color: (creatorTheme.WidgetStyle === 'StyleFlat') ? "#151515" : "#424242"
}
}
border.color: creatorTheme.Welcome_Button_BorderColor
border.color: creatorTheme.Welcome_Button_BorderColorPressed
}
}

View File

@@ -34,6 +34,7 @@ import QtQuick.Controls 1.0
Rectangle {
id: projectList
height: column.height + 200
width: column.width
color: creatorTheme.Welcome_BackgroundColorNormal
property alias model: repeater.model

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "Aggregation"

View File

@@ -493,8 +493,12 @@ void Document::setGlobalNamespace(Namespace *globalNamespace)
*
* \param line the line number, starting with line 1
* \param column the column number, starting with column 1
* \param lineOpeningDeclaratorParenthesis optional output parameter, the line of the opening
parenthesis of the declarator starting with 1
* \param lineClosingBrace optional output parameter, the line of the closing brace starting with 1
*/
QString Document::functionAt(int line, int column) const
QString Document::functionAt(int line, int column, int *lineOpeningDeclaratorParenthesis,
int *lineClosingBrace) const
{
if (line < 1 || column < 1)
return QString();
@@ -505,10 +509,8 @@ QString Document::functionAt(int line, int column) const
// Find the enclosing function scope (which might be several levels up, or we might be standing
// on it)
Scope *scope;
if (symbol->isScope())
scope = symbol->asScope();
else
Scope *scope = symbol->asScope();
if (!scope)
scope = symbol->enclosingScope();
while (scope && !scope->isFunction() )
@@ -517,22 +519,21 @@ QString Document::functionAt(int line, int column) const
if (!scope)
return QString();
// We found the function scope, extract its name.
const Overview o;
QString rc = o.prettyName(scope->name());
// We found the function scope
if (lineOpeningDeclaratorParenthesis) {
unsigned line;
translationUnit()->getPosition(scope->startOffset(), &line);
*lineOpeningDeclaratorParenthesis = static_cast<int>(line);
}
// Prepend namespace "Foo::Foo::foo()" up to empty root namespace
for (const Symbol *owner = scope->enclosingNamespace();
owner; owner = owner->enclosingNamespace()) {
const QString name = o.prettyName(owner->name());
if (name.isEmpty()) {
break;
} else {
rc.prepend(QLatin1String("::"));
rc.prepend(name);
if (lineClosingBrace) {
unsigned line;
translationUnit()->getPosition(scope->endOffset(), &line);
*lineClosingBrace = static_cast<int>(line);
}
}
return rc;
const QList<const Name *> fullyQualifiedName = LookupContext::fullyQualifiedName(scope);
return Overview().prettyName(fullyQualifiedName);
}
Scope *Document::scopeAt(unsigned line, unsigned column)

View File

@@ -101,7 +101,8 @@ public:
QList<Macro> definedMacros() const
{ return _definedMacros; }
QString functionAt(int line, int column) const;
QString functionAt(int line, int column, int *lineOpeningDeclaratorParenthesis = 0,
int *lineClosingBrace = 0) const;
Symbol *lastVisibleSymbolAt(unsigned line, unsigned column = 0) const;
Scope *scopeAt(unsigned line, unsigned column = 0);

View File

@@ -200,6 +200,36 @@ private:
ClassOrNamespace *_binding;
};
static int evaluateFunctionArgument(const FullySpecifiedType &actualTy,
const FullySpecifiedType &formalTy)
{
int score = 0;
if (actualTy.type()->match(formalTy.type())) {
++score;
if (actualTy.isConst() == formalTy.isConst())
++score;
} else if (actualTy.simplified().type()->match(formalTy.simplified().type())) {
++score;
if (actualTy.simplified().isConst() == formalTy.simplified().isConst())
++score;
} else {
PointerType *actualAsPointer = actualTy.type()->asPointerType();
PointerType *formalAsPointer = formalTy.type()->asPointerType();
if (actualAsPointer && formalAsPointer) {
FullySpecifiedType actualElementType = actualAsPointer->elementType();
FullySpecifiedType formalElementType = formalAsPointer->elementType();
if (actualElementType.type()->match(formalElementType.type())) {
++score;
if (actualElementType.isConst() == formalElementType.isConst())
++score;
}
}
}
return score;
}
} // end of anonymous namespace
/////////////////////////////////////////////////////////////////////
@@ -771,15 +801,6 @@ bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgu
return funTy->maybeValidPrototype(actualArgumentCount);
}
bool ResolveExpression::implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const
{
if (sourceTy.match(targetTy))
return true;
else if (sourceTy.simplified().match(targetTy.simplified()))
return true;
return false;
}
bool ResolveExpression::visit(CallAST *ast)
{
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
@@ -820,11 +841,13 @@ bool ResolveExpression::visit(CallAST *ast)
continue;
actualTy = actual.first().type();
} else
} else {
actualTy = formalTy;
score += 2;
continue;
}
if (implicitConversion(actualTy, formalTy))
++score;
score += evaluateFunctionArgument(actualTy, formalTy);
}
sortedResults.insert(LookupMap::value_type(-score, base));

View File

@@ -77,7 +77,6 @@ protected:
void addResults(const QList<LookupItem> &items);
static bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount);
bool implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const;
using ASTVisitor::visit;

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "CPlusPlus"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "ExtensionSystem"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "GLSL"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "LanguageUtils"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "QmlDebug"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "QmlEditorWidgets"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "QmlJS"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "QtcSsh"

View File

@@ -200,22 +200,49 @@ struct RemoveCvAndReference
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
};
template<typename F, typename T>
struct ResultOfFunctionWithoutCvAndReference
// abstraction to treat Container<T> and QStringList similarly
template<typename T>
struct ContainerType
{
typedef typename RemoveCvAndReference<decltype(declval<F>()(declval<T>()))>::type type;
};
// actual implementation of transform
template<template<typename> class C, // result container type
template<typename> class SC, // input container type
typename T, // element type of input container
typename F> // function type
Q_REQUIRED_RESULT
auto transform_impl(const SC<T> &container, F function)
-> C<typename ResultOfFunctionWithoutCvAndReference<F, T>::type>
// specialization for qt container T_Container<T_Type>
template<template<typename> class T_Container, typename T_Type>
struct ContainerType<T_Container<T_Type>> {
typedef T_Type ElementType;
template<class NewElementType>
struct WithElementType
{
C<typename ResultOfFunctionWithoutCvAndReference<F, T>::type> result;
typedef T_Container<NewElementType> type;
};
};
// specialization for QStringList
template<>
struct ContainerType<QStringList>
{
typedef QString ElementType;
template<class NewElementType>
struct WithElementType
{
typedef QList<NewElementType> type;
};
};
}
// actual implementation of transform
template<typename C, // result container type
typename SC> // input container type
struct TransformImpl {
template <typename F>
Q_REQUIRED_RESULT
static C call(const SC &container, F function)
{
C result;
result.reserve(container.size());
std::transform(container.begin(), container.end(),
inserter(result),
@@ -223,72 +250,87 @@ auto transform_impl(const SC<T> &container, F function)
return result;
}
template <typename R, typename S>
Q_REQUIRED_RESULT
static C call(const SC &container, R (S::*p)() const)
{
return call(container, std::mem_fn(p));
}
// transform taking a member function pointer
template<template<typename> class C,
typename T,
};
// same container type for input and output, e.g. transforming a QList<QString> into QList<int>
// or QStringList -> QList<>
template<typename C, // container
typename F>
Q_REQUIRED_RESULT
auto transform(const C &container, F function)
-> typename ContainerType<C>::template WithElementType< // the type C<stripped return type of F>
typename RemoveCvAndReference< // the return type of F stripped
decltype(declval<F>()(declval<typename ContainerType<C>::ElementType>())) // the return type of F
>::type
>::type
{
return TransformImpl<
typename ContainerType<C>::template WithElementType< // the type C<stripped return type>
typename RemoveCvAndReference< // the return type stripped
decltype(declval<F>()(declval<typename ContainerType<C>::ElementType>())) // the return type of F
>::type
>::type,
C
>::call(container, function);
}
// same container type for member function pointer
template<typename C,
typename R,
typename S>
Q_REQUIRED_RESULT
auto transform(const C<T> &container, R (S::*p)() const)
-> C<typename RemoveCvAndReference<R>::type>
auto transform(const C &container, R (S::*p)() const)
->typename ContainerType<C>::template WithElementType<typename RemoveCvAndReference<R>::type>::type
{
C<typename RemoveCvAndReference<R>::type> result;
result.reserve(container.size());
std::transform(container.begin(), container.end(),
std::back_inserter(result),
std::mem_fn(p));
return result;
}
// same container type for input and output, e.g. transforming a QList<QString> into QList<int>
template<template<typename> class C, // container
typename T, // element type
typename F> // function type
Q_REQUIRED_RESULT
auto transform(const C<T> &container, F function)
-> C<typename RemoveCvAndReference<decltype(declval<F>()(declval<T>()))>::type>
{
return transform_impl<QList>(container, function);
return TransformImpl<
typename ContainerType<C>::template WithElementType< // the type C<stripped R>
typename RemoveCvAndReference<R>::type // stripped R
>::type,
C
>::call(container, p);
}
// different container types for input and output, e.g. transforming a QList into a QSet
template<template<typename> class C, // result container type
template<typename> class SC, // input container type
typename T, // element type of input container
typename SC, // input container type
typename F> // function type
Q_REQUIRED_RESULT
auto transform(const SC<T> &container, F function)
-> C<typename RemoveCvAndReference<decltype(declval<F>()(declval<T>()))>::type>
auto transform(const SC &container, F function)
-> C< // container C<stripped return type of F>
typename RemoveCvAndReference< // stripped return type of F
decltype(declval<F>()(declval<typename ContainerType<SC>::ElementType>())) // return type of F
>::type>
{
return transform_impl(container, function);
return TransformImpl<
C< // result container type
typename RemoveCvAndReference< // stripped
decltype(declval<F>()(declval<typename ContainerType<SC>::ElementType>())) // return type of F
>::type>,
SC
>::call(container, function);
}
//////////
// transform for QStringList, because that isn't a specialization but a separate type
// and g++ doesn't want to use the above templates for that
// clang and msvc do find the base class QList<QString>
//////////
// QStringList -> QList<>
template<typename F> // function type
Q_REQUIRED_RESULT
auto transform(const QStringList &container, F function)
-> QList<typename RemoveCvAndReference<decltype(declval<F>()(declval<QString>()))>::type>
{
return transform_impl<QList>(QList<QString>(container), function);
}
// QStringList -> any container type
// different container types for input and output, e.g. transforming a QList into a QSet
// for member function pointers
template<template<typename> class C, // result container type
typename F> // function type
typename SC, // input container type
typename R,
typename S>
Q_REQUIRED_RESULT
auto transform(const QStringList &container, F function)
-> C<typename RemoveCvAndReference<decltype(declval<F>()(declval<QString>()))>::type>
auto transform(const SC &container, R (S::*p)())
-> C<typename RemoveCvAndReference<R>::type>
{
return transform_impl<C>(QList<QString>(container), function);
return TransformImpl<
C<typename RemoveCvAndReference<R>::type>,
SC
>::call(container, p);
}
//////////////////

View File

@@ -701,6 +701,8 @@ FileName FileName::relativeChildPath(const FileName &parent) const
/// Appends \a s, ensuring a / between the parts
FileName &FileName::appendPath(const QString &s)
{
if (s.isEmpty())
return *this;
if (!isEmpty() && !QString::endsWith(QLatin1Char('/')))
appendString(QLatin1Char('/'));
appendString(s);

View File

@@ -358,23 +358,27 @@ void MacroExpander::registerIntVariable(const QByteArray &variable,
* \sa registerVariable(), registerIntVariable(), registerPrefix()
*/
void MacroExpander::registerFileVariables(const QByteArray &prefix,
const QString &heading, const StringFunction &base)
const QString &heading, const StringFunction &base, bool visibleInChooser)
{
registerVariable(prefix + kFilePathPostfix,
tr("%1: Full path including file name.").arg(heading),
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).filePath(); });
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).filePath(); },
visibleInChooser);
registerVariable(prefix + kPathPostfix,
tr("%1: Full path excluding file name.").arg(heading),
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).path(); });
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).path(); },
visibleInChooser);
registerVariable(prefix + kFileNamePostfix,
tr("%1: File name without path.").arg(heading),
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).fileName(); });
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).fileName(); },
visibleInChooser);
registerVariable(prefix + kFileBaseNamePostfix,
tr("%1: File base name without path and suffix.").arg(heading),
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).baseName(); });
[base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : QFileInfo(tmp).baseName(); },
visibleInChooser);
}
void MacroExpander::registerExtraResolver(const MacroExpander::ResolverFunction &value)

View File

@@ -81,7 +81,8 @@ public:
const QString &description, const IntFunction &value);
void registerFileVariables(const QByteArray &prefix,
const QString &heading, const StringFunction &value);
const QString &heading, const StringFunction &value,
bool visibleInChooser = true);
void registerExtraResolver(const ResolverFunction &value);

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcTool
QtcTool {
name: "qtcreator_ctrlc_stub"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcTool
QtcTool {
name: "qtcreator_process_stub"

View File

@@ -174,6 +174,8 @@ void ProxyAction::updateToolTipWithKeySequence()
QString ProxyAction::stringWithAppendedShortcut(const QString &str, const QKeySequence &shortcut)
{
QString s = str;
s.replace(QLatin1String("&&"), QLatin1String("&"));
return QString::fromLatin1("%1 <span style=\"color: gray; font-size: small\">%2</span>").
arg(str, shortcut.toString(QKeySequence::NativeText));
arg(s, shortcut.toString(QKeySequence::NativeText));
}

View File

@@ -111,8 +111,8 @@ public:
ProgressBarColorError,
ProgressBarColorFinished,
ProgressBarColorNormal,
SearchResultWidgetBackgroundColor,
SearchResultWidgetTextColor,
InfoBarBackground,
InfoBarText,
TextColorDisabled,
TextColorHighlight,
TextColorNormal,
@@ -136,7 +136,8 @@ public:
Welcome_TextColorHeading, // #535353 // Sessions, Recent Projects
Welcome_BackgroundColorNormal, // #ffffff
Welcome_DividerColor, // #737373
Welcome_Button_BorderColor,
Welcome_Button_BorderColorNormal,
Welcome_Button_BorderColorPressed,
Welcome_Button_TextColorNormal,
Welcome_Button_TextColorPressed,
Welcome_Link_TextColorNormal,

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcLibrary
QtcLibrary {
name: "Utils"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "AnalyzerBase"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "Android"

View File

@@ -131,6 +131,33 @@ namespace {
}
return res;
}
static bool is32BitUserSpace()
{
// Do the exact same check as android's emulator is doing:
if (Utils::HostOsInfo::isLinuxHost()) {
if (QSysInfo::WordSize == 32 ) {
Utils::Environment env = Utils::Environment::systemEnvironment();
QString executable = env.searchInPath(QLatin1String("file")).toString();
QString shell = env.value(QLatin1String("SHELL"));
if (executable.isEmpty() || shell.isEmpty())
return true; // we can't detect, but creator is 32bit so assume 32bit
QProcess proc;
proc.setProcessChannelMode(QProcess::MergedChannels);
proc.start(executable, QStringList() << shell);
if (!proc.waitForFinished(2000)) {
proc.kill();
return true;
}
if (proc.readAll().contains("x86-64"))
return false;
return true;
}
}
return false;
}
}
//////////////////////////////////
@@ -660,9 +687,13 @@ bool AndroidConfig::startAVDAsync(const QString &avdName) const
avdProcess->connect(avdProcess, SIGNAL(finished(int)), avdProcess, SLOT(deleteLater()));
// start the emulator
avdProcess->start(emulatorToolPath().toString(),
QStringList() << QLatin1String("-partition-size") << QString::number(partitionSize())
<< QLatin1String("-avd") << avdName);
QStringList arguments;
if (AndroidConfigurations::force32bitEmulator())
arguments << QLatin1String("-force-32bit");
arguments << QLatin1String("-partition-size") << QString::number(partitionSize())
<< QLatin1String("-avd") << avdName;
avdProcess->start(emulatorToolPath().toString(), arguments);
if (!avdProcess->waitForStarted(-1)) {
delete avdProcess;
return false;
@@ -1166,6 +1197,11 @@ void AndroidConfigurations::updateAutomaticKitList()
}
}
bool AndroidConfigurations::force32bitEmulator()
{
return m_instance->m_force32bit;
}
/**
* Workaround for '????????????' serial numbers
* @return ("-d") for buggy devices, ("-s", <serial no>) for normal
@@ -1203,6 +1239,8 @@ AndroidConfigurations::AndroidConfigurations(QObject *parent)
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)),
this, SLOT(clearDefaultDevices(ProjectExplorer::Project*)));
m_force32bit = is32BitUserSpace();
m_instance = this;
}

View File

@@ -215,6 +215,7 @@ public slots:
static void clearDefaultDevices(ProjectExplorer::Project *project);
static void updateToolChainList();
static void updateAutomaticKitList();
static bool force32bitEmulator();
signals:
void updated();
@@ -228,6 +229,7 @@ private:
AndroidConfig m_config;
QMap<ProjectExplorer::Project *, QMap<QString, QString> > m_defaultDeviceForAbi;
bool m_force32bit;
};
} // namespace Android

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "AutotoolsProjectManager"

View File

@@ -1,7 +1,5 @@
import qbs
import QtcPlugin
QtcPlugin {
name: "BareMetal"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "Bazaar"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "Beautifier"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "BinEditor"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "Bookmarks"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "ClassView"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "ClearCase"

View File

@@ -869,6 +869,20 @@ void CMakeCbpParser::sortFiles()
CMakeBuildTarget *last = 0;
Utils::FileName parentDirectory;
// find a good build target to fall back
int fallbackIndex = 0;
{
int bestIncludeCount = -1;
for (int i = 0; i < m_buildTargets.size(); ++i) {
const CMakeBuildTarget &target = m_buildTargets.at(i);
if (target.sourceDirectory == m_sourceDirectory
&& target.includeFiles.count() > bestIncludeCount) {
bestIncludeCount = target.includeFiles.count();
fallbackIndex = i;
}
}
}
foreach (const Utils::FileName &fileName, fileNames) {
if (fileName.parentDir() == parentDirectory && last) {
// easy case, same parent directory as last file
@@ -891,7 +905,7 @@ void CMakeCbpParser::sortFiles()
}
if (bestIndex == -1 && !m_buildTargets.isEmpty())
bestIndex = 0;
bestIndex = fallbackIndex;
if (bestIndex != -1) {
m_buildTargets[bestIndex].files.append(fileName.toString());

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "CMakeProjectManager"

View File

@@ -307,6 +307,18 @@ Command *ActionContainerPrivate::addSeparator(const Context &context, Id group,
return cmd;
}
void ActionContainerPrivate::setEnabled(bool enabled)
{
foreach (const Group &group, m_groups) {
foreach (QObject *item, group.items) {
if (Command *command = qobject_cast<Command *>(item))
command->action()->setEnabled(enabled);
else if (ActionContainer *container = qobject_cast<ActionContainer *>(item))
container->setEnabled(enabled);
}
}
}
void ActionContainerPrivate::clear()
{
QMutableListIterator<Group> it(m_groups);

View File

@@ -72,6 +72,7 @@ public:
virtual void addMenu(ActionContainer *menu, Id group = Id()) = 0;
virtual void addMenu(ActionContainer *before, ActionContainer *menu, Id group = Id()) = 0;
virtual Command *addSeparator(const Context &context, Id group = Id(), QAction **outSeparator = 0) = 0;
virtual void setEnabled(bool enabled) = 0;
// This clears this menu and submenus from all actions and submenus.
// It does not destroy the submenus and commands, just removes them from their parents.

View File

@@ -64,6 +64,7 @@ public:
void addMenu(ActionContainer *menu, Id group = Id());
void addMenu(ActionContainer *before, ActionContainer *menu, Id group = Id());
Command *addSeparator(const Context &context, Id group = Id(), QAction **outSeparator = 0);
void setEnabled(bool enabled);
virtual void clear();
Id id() const;

View File

@@ -313,6 +313,10 @@ void Action::addOverrideAction(QAction *action, const Core::Context &context, bo
{
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)
action->setMenuRole(QAction::NoRole);
if (isEmpty())
m_action->initialize(action);
if (context.isEmpty()) {

View File

@@ -95,6 +95,7 @@ void CorePlugin::parseArguments(const QStringList &arguments)
QString themeName = QLatin1String("default");
QColor overrideColor;
bool overrideTheme = false;
bool presentationMode = false;
for (int i = 0; i < arguments.size(); ++i) {
if (arguments.at(i) == QLatin1String("-color")) {
@@ -103,7 +104,7 @@ void CorePlugin::parseArguments(const QStringList &arguments)
i++; // skip the argument
}
if (arguments.at(i) == QLatin1String("-presentationMode"))
ActionManager::setPresentationModeEnabled(true);
presentationMode = true;
if (arguments.at(i) == QLatin1String("-theme")) {
overrideTheme = true;
themeName = arguments.at(i + 1);
@@ -137,6 +138,7 @@ void CorePlugin::parseArguments(const QStringList &arguments)
// defer creation of these widgets until here,
// because they need a valid theme set
m_mainWindow = new MainWindow;
ActionManager::setPresentationModeEnabled(presentationMode);
m_findPlugin = new FindPlugin;
m_locator = new Locator;

View File

@@ -17,6 +17,7 @@ SOURCES += corejsextensions.cpp \
fancytabwidget.cpp \
generalsettings.cpp \
themesettings.cpp \
themesettingswidget.cpp \
id.cpp \
icontext.cpp \
jsexpander.cpp \
@@ -121,6 +122,7 @@ HEADERS += corejsextensions.h \
fancytabwidget.h \
generalsettings.h \
themesettings.h \
themesettingswidget.h \
id.h \
jsexpander.h \
messagemanager.h \

View File

@@ -1,6 +1,5 @@
import qbs 1.0
import qbs.FileInfo
import QtcPlugin
QtcPlugin {
name: "Core"
@@ -98,9 +97,8 @@ QtcPlugin {
"styleanimator.cpp", "styleanimator.h",
"tabpositionindicator.cpp", "tabpositionindicator.h",
"textdocument.cpp", "textdocument.h",
"themesettings.cpp",
"themesettings.h",
"themesettings.ui",
"themesettings.cpp", "themesettings.h", "themesettings.ui",
"themesettingswidget.cpp", "themesettingswidget.h",
"toolsettings.cpp", "toolsettings.h",
"variablechooser.cpp", "variablechooser.h",
"vcsmanager.cpp", "vcsmanager.h",

View File

@@ -200,7 +200,7 @@ DocumentManagerPrivate::DocumentManagerPrivate() :
m_linkWatcher(0),
m_blockActivated(false),
m_lastVisitedDirectory(QDir::currentPath()),
m_useProjectsDirectory(Utils::HostOsInfo::isMacHost()), // Creator is in bizarre places when launched via finder.
m_useProjectsDirectory(true),
m_blockedIDocument(0)
{
}

View File

@@ -225,12 +225,12 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
m_ui.replaceButton->setDefaultAction(m_localReplaceAction);
m_replaceNextAction = new QAction(tr("Replace && Find"), this);
m_replaceNextAction->setIconText(tr("Replace && Find")); // work around bug in Qt that kills ampersands in tool button
cmd = Core::ActionManager::registerAction(m_replaceNextAction, Constants::REPLACE_NEXT, globalcontext);
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+=")));
mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
connect(m_replaceNextAction, SIGNAL(triggered()), this, SLOT(invokeGlobalReplaceNext()));
m_localReplaceNextAction = new QAction(m_replaceNextAction->text(), this);
m_localReplaceNextAction->setIconText(m_replaceNextAction->text()); // Workaround QTBUG-23396
cmd = ActionManager::registerAction(m_localReplaceNextAction, Constants::REPLACE_NEXT, findcontext);
cmd->augmentActionWithShortcutToolTip(m_localReplaceNextAction);
connect(m_localReplaceNextAction, &QAction::triggered, this, &FindToolBar::invokeReplaceNext);

View File

@@ -96,8 +96,8 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) :
QFrame *topWidget = new QFrame;
QPalette pal;
pal.setColor(QPalette::Window, creatorTheme()->color(Theme::SearchResultWidgetBackgroundColor));
pal.setColor(QPalette::WindowText, creatorTheme()->color(Theme::SearchResultWidgetTextColor));
pal.setColor(QPalette::Window, creatorTheme()->color(Theme::InfoBarBackground));
pal.setColor(QPalette::WindowText, creatorTheme()->color(Theme::InfoBarText));
topWidget->setPalette(pal);
if (creatorTheme()->flag(Theme::DrawSearchResultWidgetFrame)) {
topWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);

View File

@@ -73,6 +73,16 @@
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="themeLabel">
<property name="text">
<string>Theme:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Core::Internal::ThemeSettingsWidget" name="themeWidget" native="true"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="languageLabel">
<property name="text">
@@ -334,6 +344,12 @@
<signal>browsingFinished()</signal>
</slots>
</customwidget>
<customwidget>
<class>Core::Internal::ThemeSettingsWidget</class>
<extends>QWidget</extends>
<header location="global">coreplugin/themesettingswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="core.qrc"/>

View File

@@ -33,6 +33,8 @@
#include "coreconstants.h"
#include "icore.h"
#include <utils/theme/theme.h>
#include <QFrame>
#include <QHBoxLayout>
#include <QLabel>
@@ -40,6 +42,8 @@
static const char C_SUPPRESSED_WARNINGS[] = "SuppressedWarnings";
using namespace Utils;
namespace Core {
QSet<Id> InfoBar::globallySuppressed;
@@ -202,8 +206,8 @@ void InfoBarDisplay::update()
QFrame *infoWidget = new QFrame;
QPalette pal;
pal.setColor(QPalette::Window, QColor(255, 255, 225));
pal.setColor(QPalette::WindowText, Qt::black);
pal.setColor(QPalette::Window, creatorTheme()->color(Theme::InfoBarBackground));
pal.setColor(QPalette::WindowText, Theme::InfoBarText);
infoWidget->setPalette(pal);
infoWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);

View File

@@ -132,7 +132,6 @@ MainWindow::MainWindow() :
m_rightPaneWidget(0),
m_versionDialog(0),
m_generalSettings(new GeneralSettings),
m_themeSettings(new ThemeSettings),
m_shortcutSettings(new ShortcutSettings),
m_toolSettings(new ToolSettings),
m_mimeTypeSettings(new MimeTypeSettings),
@@ -256,7 +255,6 @@ MainWindow::~MainWindow()
ExtensionSystem::PluginManager::removeObject(m_shortcutSettings);
ExtensionSystem::PluginManager::removeObject(m_generalSettings);
ExtensionSystem::PluginManager::removeObject(m_themeSettings);
ExtensionSystem::PluginManager::removeObject(m_toolSettings);
ExtensionSystem::PluginManager::removeObject(m_mimeTypeSettings);
ExtensionSystem::PluginManager::removeObject(m_systemEditor);
@@ -268,8 +266,6 @@ MainWindow::~MainWindow()
m_shortcutSettings = 0;
delete m_generalSettings;
m_generalSettings = 0;
delete m_themeSettings;
m_themeSettings = 0;
delete m_toolSettings;
m_toolSettings = 0;
delete m_mimeTypeSettings;
@@ -327,7 +323,6 @@ bool MainWindow::init(QString *errorMessage)
m_progressManager->init(); // needs the status bar manager
ExtensionSystem::PluginManager::addObject(m_generalSettings);
ExtensionSystem::PluginManager::addObject(m_themeSettings);
ExtensionSystem::PluginManager::addObject(m_shortcutSettings);
ExtensionSystem::PluginManager::addObject(m_toolSettings);
ExtensionSystem::PluginManager::addObject(m_mimeTypeSettings);
@@ -567,9 +562,9 @@ void MainWindow::registerDefaultActions()
// Exit Action
icon = QIcon::fromTheme(QLatin1String("application-exit"));
m_exitAction = new QAction(icon, tr("E&xit"), this);
m_exitAction->setMenuRole(QAction::QuitRole);
cmd = ActionManager::registerAction(m_exitAction, Constants::EXIT, globalContext);
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Q")));
cmd->action()->setMenuRole(QAction::QuitRole);
mfile->addAction(cmd, Constants::G_FILE_OTHER);
connect(m_exitAction, SIGNAL(triggered()), this, SLOT(exit()));
@@ -638,11 +633,9 @@ void MainWindow::registerDefaultActions()
mtools->addSeparator(globalContext, Constants::G_TOOLS_OPTIONS);
m_optionsAction = new QAction(tr("&Options..."), this);
m_optionsAction->setMenuRole(QAction::PreferencesRole);
cmd = ActionManager::registerAction(m_optionsAction, Constants::OPTIONS, globalContext);
if (UseMacShortcuts) {
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+,")));
cmd->action()->setMenuRole(QAction::PreferencesRole);
}
cmd->setDefaultKeySequence(QKeySequence::Preferences);
mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
connect(m_optionsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog()));
@@ -665,7 +658,6 @@ void MainWindow::registerDefaultActions()
// Full Screen Action
QAction *toggleFullScreenAction = new QAction(tr("Full Screen"), this);
toggleFullScreenAction->setMenuRole(QAction::NoRole);
toggleFullScreenAction->setCheckable(!Utils::HostOsInfo::isMacHost());
toggleFullScreenAction->setEnabled(false); // actual implementation in WindowSupport
cmd = ActionManager::registerAction(toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext);
@@ -721,18 +713,16 @@ void MainWindow::registerDefaultActions()
tmpaction = new QAction(icon, tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
else
tmpaction = new QAction(icon, tr("About &Qt Creator..."), this);
tmpaction->setMenuRole(QAction::AboutRole);
cmd = ActionManager::registerAction(tmpaction, Constants::ABOUT_QTCREATOR, globalContext);
if (Utils::HostOsInfo::isMacHost())
cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
tmpaction->setEnabled(true);
connect(tmpaction, SIGNAL(triggered()), this, SLOT(aboutQtCreator()));
//About Plugins Action
tmpaction = new QAction(tr("About &Plugins..."), this);
tmpaction->setMenuRole(QAction::ApplicationSpecificRole);
cmd = ActionManager::registerAction(tmpaction, Constants::ABOUT_PLUGINS, globalContext);
if (Utils::HostOsInfo::isMacHost())
cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
tmpaction->setEnabled(true);
connect(tmpaction, SIGNAL(triggered()), this, SLOT(aboutPlugins()));

View File

@@ -72,7 +72,6 @@ namespace Internal {
class ActionManagerPrivate;
class FancyTabWidget;
class GeneralSettings;
class ThemeSettings;
class ProgressManagerPrivate;
class ShortcutSettings;
class ToolSettings;
@@ -192,7 +191,6 @@ private:
QMap<QWidget *, IContext *> m_contextWidgets;
GeneralSettings *m_generalSettings;
ThemeSettings *m_themeSettings;
ShortcutSettings *m_shortcutSettings;
ToolSettings *m_toolSettings;
MimeTypeSettings *m_mimeTypeSettings;

View File

@@ -45,7 +45,7 @@ ThemeColorsTableView::ThemeColorsTableView(QWidget *parent)
void ThemeColorsTableView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
if ((editTriggers() & NoEditTriggers) && (event->button() == Qt::LeftButton)) {
QModelIndex index = indexAt(event->pos());
if (model()->flags(index) & Qt::ItemIsEditable && index.column() == 1) {
setCurrentIndex(index);

View File

@@ -79,6 +79,8 @@ ThemeEditorWidget::~ThemeEditorWidget()
void ThemeEditorWidget::changeColor(const QModelIndex &index)
{
if (!(m_ui->tableView->editTriggers() & QAbstractItemView::DoubleClicked))
return;
if (m_model->inSectionBody(index.row()) != ThemeSettingsTableModel::SectionColors)
return;
if (index.column() == 1)
@@ -114,7 +116,9 @@ void ThemeEditorWidget::changeColor(const QModelIndex &index)
void ThemeEditorWidget::setReadOnly(bool readOnly)
{
m_readOnly = readOnly;
m_ui->tableView->setEnabled(!readOnly);
m_ui->tableView->setEditTriggers(
readOnly ? QAbstractItemView::NoEditTriggers
: QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
m_ui->filter->setEnabled(!readOnly);
}

View File

@@ -29,436 +29,46 @@
****************************************************************************/
#include "themesettings.h"
#include "themesettingswidget.h"
#include "coreconstants.h"
#include "icore.h"
#include "editormanager/editormanager_p.h"
#include "themeeditor/themesettingstablemodel.h"
#include <utils/qtcassert.h>
#include <QDebug>
#include <QDir>
#include <QInputDialog>
#include <QMessageBox>
#include <QSettings>
#include "ui_themesettings.h"
using namespace Utils;
#include <QCoreApplication>
namespace Core {
namespace Internal {
const char themeNameKey[] = "ThemeName";
static QString customThemesPath()
{
QString path = Core::ICore::userResourcePath();
path.append(QLatin1String("/themes/"));
return path;
}
static QString createThemeFileName(const QString &pattern)
{
const QString stylesPath = customThemesPath();
QString baseFileName = stylesPath;
baseFileName += pattern;
// Find an available file name
int i = 1;
QString fileName;
do {
fileName = baseFileName.arg((i == 1) ? QString() : QString::number(i));
++i;
} while (QFile::exists(fileName));
// Create the base directory when it doesn't exist
if (!QFile::exists(stylesPath) && !QDir().mkpath(stylesPath)) {
qWarning() << "Failed to create theme directory:" << stylesPath;
return QString();
}
return fileName;
}
struct ThemeEntry
{
ThemeEntry() {}
ThemeEntry(const QString &fileName, bool readOnly):
m_fileName(fileName),
m_readOnly(readOnly)
{ }
QString fileName() const { return m_fileName; }
QString name() const;
bool readOnly() const { return m_readOnly; }
private:
QString m_fileName;
bool m_readOnly;
};
QString ThemeEntry::name() const
{
QSettings settings(m_fileName, QSettings::IniFormat);
QString n = settings.value(QLatin1String(themeNameKey), QCoreApplication::tr("unnamed")).toString();
return m_readOnly ? QCoreApplication::tr("%1 (built-in)").arg(n) : n;
}
class ThemeListModel : public QAbstractListModel
{
public:
ThemeListModel(QObject *parent = 0):
QAbstractListModel(parent)
{
}
int rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_themes.size();
}
QVariant data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
return m_themes.at(index.row()).name();
return QVariant();
}
void removeTheme(int index)
{
beginRemoveRows(QModelIndex(), index, index);
m_themes.removeAt(index);
endRemoveRows();
}
void setThemes(const QList<ThemeEntry> &themes)
{
beginResetModel();
m_themes = themes;
endResetModel();
}
const ThemeEntry &themeAt(int index) const
{
return m_themes.at(index);
}
private:
QList<ThemeEntry> m_themes;
};
class ThemeSettingsPrivate
{
public:
ThemeSettingsPrivate();
~ThemeSettingsPrivate();
public:
ThemeListModel *m_themeListModel;
bool m_refreshingThemeList;
Ui::ThemeSettings *m_ui;
QPointer<QWidget> m_widget;
ThemeEntry m_currentTheme;
};
ThemeSettingsPrivate::ThemeSettingsPrivate()
: m_themeListModel(new ThemeListModel)
, m_refreshingThemeList(false)
, m_ui(0)
{
m_currentTheme = ThemeEntry(creatorTheme()->fileName(), true);
}
ThemeSettingsPrivate::~ThemeSettingsPrivate()
{
delete m_themeListModel;
}
ThemeSettings::ThemeSettings()
ThemeSettings::ThemeSettings() :
m_widget(0)
{
setId(Core::Constants::SETTINGS_ID_ENVIRONMENT);
setDisplayName(tr("Theme"));
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::SETTINGS_TR_CATEGORY_CORE));
setCategoryIcon(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE_ICON));
d = new ThemeSettingsPrivate();
}
ThemeSettings::~ThemeSettings()
{
delete d;
}
void ThemeSettings::refreshThemeList()
{
QList<ThemeEntry> themes;
QString resourcePath = Core::ICore::resourcePath();
QDir themeDir(resourcePath + QLatin1String("/themes"));
themeDir.setNameFilters(QStringList() << QLatin1String("*.creatortheme"));
themeDir.setFilter(QDir::Files);
int selected = 0;
QStringList themeList = themeDir.entryList();
QString defaultTheme = QFileInfo(defaultThemeFileName()).fileName();
if (themeList.removeAll(defaultTheme))
themeList.prepend(defaultTheme);
foreach (const QString &file, themeList) {
const QString fileName = themeDir.absoluteFilePath(file);
if (d->m_currentTheme.fileName() == fileName)
selected = themes.size();
themes.append(ThemeEntry(fileName, true));
}
if (themes.isEmpty())
qWarning() << "Warning: no themes found in path:" << themeDir.path();
themeDir.setPath(customThemesPath());
foreach (const QString &file, themeDir.entryList()) {
const QString fileName = themeDir.absoluteFilePath(file);
if (d->m_currentTheme.fileName() == fileName)
selected = themes.size();
themes.append(ThemeEntry(fileName, false));
}
d->m_currentTheme = themes[selected];
d->m_refreshingThemeList = true;
d->m_themeListModel->setThemes(themes);
d->m_ui->themeComboBox->setCurrentIndex(selected);
d->m_refreshingThemeList = false;
}
QString ThemeSettings::defaultThemeFileName(const QString &fileName)
{
QString defaultScheme = Core::ICore::resourcePath();
defaultScheme += QLatin1String("/themes/");
if (!fileName.isEmpty() && QFile::exists(defaultScheme + fileName))
defaultScheme += fileName;
else
defaultScheme += QLatin1String("default.creatortheme");
return defaultScheme;
}
void ThemeSettings::themeSelected(int index)
{
bool readOnly = true;
if (index != -1) {
// Check whether we're switching away from a changed theme
if (!d->m_refreshingThemeList)
maybeSaveTheme();
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
readOnly = entry.readOnly();
d->m_currentTheme = entry;
QSettings settings(entry.fileName(), QSettings::IniFormat);
Theme theme;
theme.readSettings(settings);
d->m_ui->editor->initFrom(&theme);
}
d->m_ui->copyButton->setEnabled(index != -1);
d->m_ui->deleteButton->setEnabled(!readOnly);
d->m_ui->renameButton->setEnabled(!readOnly);
d->m_ui->editor->setReadOnly(readOnly);
delete m_widget;
}
QWidget *ThemeSettings::widget()
{
if (!d->m_widget) {
d->m_widget = new QWidget;
d->m_ui = new Ui::ThemeSettings();
d->m_ui->setupUi(d->m_widget);
d->m_ui->themeComboBox->setModel(d->m_themeListModel);
connect(d->m_ui->themeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &ThemeSettings::themeSelected);
connect(d->m_ui->copyButton, &QAbstractButton::clicked, this, &ThemeSettings::copyTheme);
connect(d->m_ui->renameButton, &QAbstractButton::clicked, this, &ThemeSettings::renameTheme);
connect(d->m_ui->deleteButton, &QAbstractButton::clicked, this, &ThemeSettings::confirmDeleteTheme);
refreshThemeList();
}
return d->m_widget;
}
void ThemeSettings::confirmDeleteTheme()
{
const int index = d->m_ui->themeComboBox->currentIndex();
if (index == -1)
return;
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
if (entry.readOnly())
return;
QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
tr("Delete Theme"),
tr("Are you sure you want to delete the theme '%1' permanently?").arg(entry.name()),
QMessageBox::Discard | QMessageBox::Cancel,
d->m_ui->deleteButton->window());
// Change the text and role of the discard button
QPushButton *deleteButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
deleteButton->setText(tr("Delete"));
messageBox->addButton(deleteButton, QMessageBox::AcceptRole);
messageBox->setDefaultButton(deleteButton);
connect(deleteButton, &QAbstractButton::clicked, messageBox, &QDialog::accept);
connect(messageBox, &QDialog::accepted, this, &ThemeSettings::deleteTheme);
messageBox->setAttribute(Qt::WA_DeleteOnClose);
messageBox->open();
}
void ThemeSettings::deleteTheme()
{
const int index = d->m_ui->themeComboBox->currentIndex();
QTC_ASSERT(index != -1, return);
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
QTC_ASSERT(!entry.readOnly(), return);
if (QFile::remove(entry.fileName()))
d->m_themeListModel->removeTheme(index);
}
void ThemeSettings::copyTheme()
{
QInputDialog *dialog = new QInputDialog(d->m_ui->copyButton->window());
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setInputMode(QInputDialog::TextInput);
dialog->setWindowTitle(tr("Copy Theme"));
dialog->setLabelText(tr("Theme name:"));
//TODO
//dialog->setTextValue(tr("%1 (copy)").arg(d_ptr->m_value.colorScheme().displayName()));
connect(dialog, &QInputDialog::textValueSelected, this, &ThemeSettings::copyThemeByName);
dialog->open();
}
void ThemeSettings::maybeSaveTheme()
{
if (!d->m_ui->editor->model()->hasChanges())
return;
QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
tr("Theme Changed"),
tr("The theme \"%1\" was modified, do you want to save the changes?")
.arg(d->m_currentTheme.name()),
QMessageBox::Discard | QMessageBox::Save,
d->m_ui->themeComboBox->window());
// Change the text of the discard button
QPushButton *discardButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
discardButton->setText(tr("Discard"));
messageBox->addButton(discardButton, QMessageBox::DestructiveRole);
messageBox->setDefaultButton(QMessageBox::Save);
if (messageBox->exec() == QMessageBox::Save) {
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.writeSettings(d->m_currentTheme.fileName());
}
}
void ThemeSettings::renameTheme()
{
int index = d->m_ui->themeComboBox->currentIndex();
if (index == -1)
return;
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
maybeSaveTheme();
QInputDialog *dialog = new QInputDialog(d->m_ui->renameButton->window());
dialog->setInputMode(QInputDialog::TextInput);
dialog->setWindowTitle(tr("Rename Theme"));
dialog->setLabelText(tr("Theme name:"));
dialog->setTextValue(d->m_ui->editor->model()->m_name);
int ret = dialog->exec();
QString newName = dialog->textValue();
delete dialog;
if (ret != QDialog::Accepted || newName.isEmpty())
return;
// overwrite file with new name
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.setName(newName);
newTheme.writeSettings(entry.fileName());
refreshThemeList();
}
void ThemeSettings::copyThemeByName(const QString &name)
{
int index = d->m_ui->themeComboBox->currentIndex();
if (index == -1)
return;
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
QString baseFileName = QFileInfo(entry.fileName()).completeBaseName();
baseFileName += QLatin1String("_copy%1.creatortheme");
QString fileName = createThemeFileName(baseFileName);
if (fileName.isEmpty())
return;
// Ask about saving any existing modifactions
maybeSaveTheme();
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.setName(name);
newTheme.writeSettings(fileName);
d->m_currentTheme = ThemeEntry(fileName, true);
refreshThemeList();
if (!m_widget)
m_widget = new ThemeSettingsWidget;
return m_widget;
}
void ThemeSettings::apply()
{
if (!d->m_ui) // wasn't shown, can't be changed
return;
{
d->m_ui->editor->model()->toTheme(creatorTheme());
if (creatorTheme()->flag(Theme::ApplyThemePaletteGlobally))
QApplication::setPalette(creatorTheme()->palette(QApplication::palette()));
foreach (QWidget *w, QApplication::topLevelWidgets())
w->update();
}
// save definition of theme
if (!d->m_currentTheme.readOnly()) {
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.writeSettings(d->m_currentTheme.fileName());
}
// save filename of selected theme in global config
QSettings *settings = Core::ICore::settings();
settings->setValue(QLatin1String(Core::Constants::SETTINGS_THEME), d->m_currentTheme.fileName());
if (m_widget)
m_widget->apply();
}
void ThemeSettings::finish()
{
delete d->m_widget;
if (!d->m_ui) // page was never shown
return
delete d->m_ui;
d->m_ui = 0;
delete m_widget;
m_widget = 0;
}
} // namespace Internal

View File

@@ -36,7 +36,7 @@
namespace Core {
namespace Internal {
class ThemeSettingsPrivate;
class ThemeSettingsWidget;
class ThemeSettings : public IOptionsPage
{
@@ -50,20 +50,7 @@ public:
void apply();
void finish();
static QString defaultThemeFileName(const QString &fileName = QString());
private slots:
void themeSelected(int index);
void copyTheme();
void renameTheme();
void copyThemeByName(const QString &);
void confirmDeleteTheme();
void deleteTheme();
void maybeSaveTheme();
private:
void refreshThemeList();
ThemeSettingsPrivate *d;
ThemeSettingsWidget *m_widget;
};
} // namespace Internal

View File

@@ -2,15 +2,19 @@
<ui version="4.0">
<class>Core::Internal::ThemeSettings</class>
<widget class="QWidget" name="Core::Internal::ThemeSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>527</width>
<height>359</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -66,8 +70,6 @@
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="core.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,440 @@
/****************************************************************************
**
** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "themesettingswidget.h"
#include "coreconstants.h"
#include "icore.h"
#include "themeeditor/themesettingstablemodel.h"
#include <utils/theme/theme.h>
#include <utils/qtcassert.h>
#include <QDebug>
#include <QDir>
#include <QInputDialog>
#include <QMessageBox>
#include <QSettings>
#include "ui_themesettings.h"
using namespace Utils;
namespace Core {
namespace Internal {
const char themeNameKey[] = "ThemeName";
static QString customThemesPath()
{
QString path = Core::ICore::userResourcePath();
path.append(QLatin1String("/themes/"));
return path;
}
static QString createThemeFileName(const QString &pattern)
{
const QString stylesPath = customThemesPath();
QString baseFileName = stylesPath;
baseFileName += pattern;
// Find an available file name
int i = 1;
QString fileName;
do {
fileName = baseFileName.arg((i == 1) ? QString() : QString::number(i));
++i;
} while (QFile::exists(fileName));
// Create the base directory when it doesn't exist
if (!QFile::exists(stylesPath) && !QDir().mkpath(stylesPath)) {
qWarning() << "Failed to create theme directory:" << stylesPath;
return QString();
}
return fileName;
}
struct ThemeEntry
{
ThemeEntry() {}
ThemeEntry(const QString &fileName, bool readOnly):
m_fileName(fileName),
m_readOnly(readOnly)
{ }
QString fileName() const { return m_fileName; }
QString name() const;
bool readOnly() const { return m_readOnly; }
private:
QString m_fileName;
bool m_readOnly;
};
QString ThemeEntry::name() const
{
QSettings settings(m_fileName, QSettings::IniFormat);
QString n = settings.value(QLatin1String(themeNameKey), QCoreApplication::tr("unnamed")).toString();
return m_readOnly ? QCoreApplication::tr("%1 (built-in)").arg(n) : n;
}
class ThemeListModel : public QAbstractListModel
{
public:
ThemeListModel(QObject *parent = 0):
QAbstractListModel(parent)
{
}
int rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_themes.size();
}
QVariant data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
return m_themes.at(index.row()).name();
return QVariant();
}
void removeTheme(int index)
{
beginRemoveRows(QModelIndex(), index, index);
m_themes.removeAt(index);
endRemoveRows();
}
void setThemes(const QList<ThemeEntry> &themes)
{
beginResetModel();
m_themes = themes;
endResetModel();
}
const ThemeEntry &themeAt(int index) const
{
return m_themes.at(index);
}
private:
QList<ThemeEntry> m_themes;
};
class ThemeSettingsPrivate
{
public:
ThemeSettingsPrivate(QWidget *widget);
~ThemeSettingsPrivate();
public:
ThemeListModel *m_themeListModel;
bool m_refreshingThemeList;
Ui::ThemeSettings *m_ui;
ThemeEntry m_currentTheme;
};
ThemeSettingsPrivate::ThemeSettingsPrivate(QWidget *widget)
: m_themeListModel(new ThemeListModel)
, m_refreshingThemeList(false)
, m_ui(new Ui::ThemeSettings)
{
m_currentTheme = ThemeEntry(creatorTheme()->fileName(), true);
m_ui->setupUi(widget);
m_ui->editor->hide(); // TODO: Restore after improving the editor
m_ui->themeComboBox->setModel(m_themeListModel);
}
ThemeSettingsPrivate::~ThemeSettingsPrivate()
{
delete m_themeListModel;
delete m_ui;
}
ThemeSettingsWidget::ThemeSettingsWidget(QWidget *parent) :
QWidget(parent)
{
d = new ThemeSettingsPrivate(this);
connect(d->m_ui->themeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &ThemeSettingsWidget::themeSelected);
connect(d->m_ui->copyButton, &QAbstractButton::clicked, this, &ThemeSettingsWidget::copyTheme);
connect(d->m_ui->renameButton, &QAbstractButton::clicked, this, &ThemeSettingsWidget::renameTheme);
connect(d->m_ui->deleteButton, &QAbstractButton::clicked, this, &ThemeSettingsWidget::confirmDeleteTheme);
refreshThemeList();
}
ThemeSettingsWidget::~ThemeSettingsWidget()
{
delete d;
}
void ThemeSettingsWidget::refreshThemeList()
{
QList<ThemeEntry> themes;
QString resourcePath = Core::ICore::resourcePath();
QDir themeDir(resourcePath + QLatin1String("/themes"));
themeDir.setNameFilters(QStringList() << QLatin1String("*.creatortheme"));
themeDir.setFilter(QDir::Files);
int selected = 0;
QStringList themeList = themeDir.entryList();
QString defaultTheme = QFileInfo(defaultThemeFileName()).fileName();
if (themeList.removeAll(defaultTheme))
themeList.prepend(defaultTheme);
foreach (const QString &file, themeList) {
const QString fileName = themeDir.absoluteFilePath(file);
if (d->m_currentTheme.fileName() == fileName)
selected = themes.size();
themes.append(ThemeEntry(fileName, true));
}
if (themes.isEmpty())
qWarning() << "Warning: no themes found in path:" << themeDir.path();
themeDir.setPath(customThemesPath());
foreach (const QString &file, themeDir.entryList()) {
const QString fileName = themeDir.absoluteFilePath(file);
if (d->m_currentTheme.fileName() == fileName)
selected = themes.size();
themes.append(ThemeEntry(fileName, false));
}
d->m_currentTheme = themes[selected];
d->m_refreshingThemeList = true;
d->m_themeListModel->setThemes(themes);
d->m_ui->themeComboBox->setCurrentIndex(selected);
d->m_refreshingThemeList = false;
}
QString ThemeSettingsWidget::defaultThemeFileName(const QString &fileName)
{
QString defaultScheme = Core::ICore::resourcePath();
defaultScheme += QLatin1String("/themes/");
if (!fileName.isEmpty() && QFile::exists(defaultScheme + fileName))
defaultScheme += fileName;
else
defaultScheme += QLatin1String("default.creatortheme");
return defaultScheme;
}
void ThemeSettingsWidget::themeSelected(int index)
{
bool readOnly = true;
if (index != -1) {
// Check whether we're switching away from a changed theme
if (!d->m_refreshingThemeList)
maybeSaveTheme();
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
readOnly = entry.readOnly();
d->m_currentTheme = entry;
QSettings settings(entry.fileName(), QSettings::IniFormat);
Theme theme;
theme.readSettings(settings);
d->m_ui->editor->initFrom(&theme);
}
d->m_ui->copyButton->setEnabled(index != -1);
d->m_ui->deleteButton->setEnabled(!readOnly);
d->m_ui->renameButton->setEnabled(!readOnly);
d->m_ui->editor->setReadOnly(readOnly);
}
void ThemeSettingsWidget::confirmDeleteTheme()
{
const int index = d->m_ui->themeComboBox->currentIndex();
if (index == -1)
return;
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
if (entry.readOnly())
return;
QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
tr("Delete Theme"),
tr("Are you sure you want to delete the theme '%1' permanently?").arg(entry.name()),
QMessageBox::Discard | QMessageBox::Cancel,
d->m_ui->deleteButton->window());
// Change the text and role of the discard button
QPushButton *deleteButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
deleteButton->setText(tr("Delete"));
messageBox->addButton(deleteButton, QMessageBox::AcceptRole);
messageBox->setDefaultButton(deleteButton);
connect(deleteButton, &QAbstractButton::clicked, messageBox, &QDialog::accept);
connect(messageBox, &QDialog::accepted, this, &ThemeSettingsWidget::deleteTheme);
messageBox->setAttribute(Qt::WA_DeleteOnClose);
messageBox->open();
}
void ThemeSettingsWidget::deleteTheme()
{
const int index = d->m_ui->themeComboBox->currentIndex();
QTC_ASSERT(index != -1, return);
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
QTC_ASSERT(!entry.readOnly(), return);
if (QFile::remove(entry.fileName()))
d->m_themeListModel->removeTheme(index);
}
void ThemeSettingsWidget::copyTheme()
{
QInputDialog *dialog = new QInputDialog(d->m_ui->copyButton->window());
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setInputMode(QInputDialog::TextInput);
dialog->setWindowTitle(tr("Copy Theme"));
dialog->setLabelText(tr("Theme name:"));
//TODO
//dialog->setTextValue(tr("%1 (copy)").arg(d_ptr->m_value.colorScheme().displayName()));
connect(dialog, &QInputDialog::textValueSelected, this, &ThemeSettingsWidget::copyThemeByName);
dialog->open();
}
void ThemeSettingsWidget::maybeSaveTheme()
{
if (!d->m_ui->editor->model()->hasChanges())
return;
QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
tr("Theme Changed"),
tr("The theme \"%1\" was modified, do you want to save the changes?")
.arg(d->m_currentTheme.name()),
QMessageBox::Discard | QMessageBox::Save,
d->m_ui->themeComboBox->window());
// Change the text of the discard button
QPushButton *discardButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
discardButton->setText(tr("Discard"));
messageBox->addButton(discardButton, QMessageBox::DestructiveRole);
messageBox->setDefaultButton(QMessageBox::Save);
if (messageBox->exec() == QMessageBox::Save) {
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.writeSettings(d->m_currentTheme.fileName());
}
}
void ThemeSettingsWidget::renameTheme()
{
int index = d->m_ui->themeComboBox->currentIndex();
if (index == -1)
return;
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
maybeSaveTheme();
QInputDialog *dialog = new QInputDialog(d->m_ui->renameButton->window());
dialog->setInputMode(QInputDialog::TextInput);
dialog->setWindowTitle(tr("Rename Theme"));
dialog->setLabelText(tr("Theme name:"));
dialog->setTextValue(d->m_ui->editor->model()->m_name);
int ret = dialog->exec();
QString newName = dialog->textValue();
delete dialog;
if (ret != QDialog::Accepted || newName.isEmpty())
return;
// overwrite file with new name
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.setName(newName);
newTheme.writeSettings(entry.fileName());
refreshThemeList();
}
void ThemeSettingsWidget::copyThemeByName(const QString &name)
{
int index = d->m_ui->themeComboBox->currentIndex();
if (index == -1)
return;
const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
QString baseFileName = QFileInfo(entry.fileName()).completeBaseName();
baseFileName += QLatin1String("_copy%1.creatortheme");
QString fileName = createThemeFileName(baseFileName);
if (fileName.isEmpty())
return;
// Ask about saving any existing modifactions
maybeSaveTheme();
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.setName(name);
newTheme.writeSettings(fileName);
d->m_currentTheme = ThemeEntry(fileName, true);
refreshThemeList();
}
void ThemeSettingsWidget::apply()
{
{
d->m_ui->editor->model()->toTheme(creatorTheme());
if (creatorTheme()->flag(Theme::ApplyThemePaletteGlobally))
QApplication::setPalette(creatorTheme()->palette(QApplication::palette()));
foreach (QWidget *w, QApplication::topLevelWidgets())
w->update();
}
// save definition of theme
if (!d->m_currentTheme.readOnly()) {
Theme newTheme;
d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.writeSettings(d->m_currentTheme.fileName());
}
// save filename of selected theme in global config
QSettings *settings = Core::ICore::settings();
settings->setValue(QLatin1String(Core::Constants::SETTINGS_THEME), d->m_currentTheme.fileName());
}
} // namespace Internal
} // namespace Core

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef THEMESETTINGSWIDGET_H
#define THEMESETTINGSWIDGET_H
#include <QWidget>
namespace Core {
namespace Internal {
class ThemeSettingsPrivate;
class ThemeSettingsWidget : public QWidget
{
Q_OBJECT
public:
ThemeSettingsWidget(QWidget *parent = 0);
~ThemeSettingsWidget();
static QString defaultThemeFileName(const QString &fileName = QString());
void apply();
private slots:
void themeSelected(int index);
void copyTheme();
void renameTheme();
void copyThemeByName(const QString &);
void confirmDeleteTheme();
void deleteTheme();
void maybeSaveTheme();
private:
void refreshThemeList();
ThemeSettingsPrivate *d;
};
} // namespace Internal
} // namespace Core
#endif // THEMESETTINGSWIDGET_H

View File

@@ -567,6 +567,8 @@ bool VariableChooser::eventFilter(QObject *obj, QEvent *event)
return handleEscapePressed(ke, this);
} else if (event->type() == QEvent::Resize) {
d->updateButtonGeometry();
} else if (event->type() == QEvent::Hide) {
close();
}
return false;
}

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "CodePaster"

View File

@@ -1,5 +1,4 @@
import qbs 1.0
import QtcTool
QtcTool {
name: "cpaster"

View File

@@ -1365,9 +1365,8 @@ void CppCodeModelInspectorDialog::refresh()
if (editor) {
const QString editorFilePath = editor->document()->filePath();
editorDocument = cmmi->editorDocument(editorFilePath);
if (editorDocument) {
const CPlusPlus::Snapshot editorSnapshot
= BuiltinEditorDocumentParser::get(editorFilePath)->snapshot();
if (auto *builtinDocumentParser = BuiltinEditorDocumentParser::get(editorFilePath)) {
const CPlusPlus::Snapshot editorSnapshot = builtinDocumentParser->snapshot();
m_snapshotInfos->append(SnapshotInfo(editorSnapshot, SnapshotInfo::EditorSnapshot));
const QString editorSnapshotTitle
= QString::fromLatin1("Current Editor's Snapshot (%1 Documents)")

View File

@@ -1,8 +1,6 @@
import qbs 1.0
import qbs.FileInfo
import QtcPlugin
QtcPlugin {
name: "CppEditor"

View File

@@ -100,6 +100,9 @@ private slots:
void test_FollowSymbolUnderCursor_data();
void test_FollowSymbolUnderCursor();
void test_FollowSymbolUnderCursor_followCall_data();
void test_FollowSymbolUnderCursor_followCall();
void test_FollowSymbolUnderCursor_QObject_connect_data();
void test_FollowSymbolUnderCursor_QObject_connect();

View File

@@ -931,45 +931,6 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
"};\n"
);
QTest::newRow("matchFunctionSignature_FollowCall_1") << _(
"class Bar {};\n"
"void $foo(int) {}\n"
"void foo(const char *) {}\n"
"void foo(const Bar &) {}\n"
"void foo(char) {}\n"
"\n"
"void t()\n"
"{\n"
" @foo(5);\n"
"}\n"
);
QTest::newRow("matchFunctionSignature_FollowCall_2") << _(
"class Bar {};\n"
"void foo(int) {}\n"
"void $foo(const char *) {}\n"
"void foo(const Bar &) {}\n"
"void foo(char) {}\n"
"\n"
"void t()\n"
"{\n"
" @foo(\"hoo\");\n"
"}\n"
);
QTest::newRow("matchFunctionSignature_FollowCall_3") << _(
"class Bar {};\n"
"void foo(int) {}\n"
"void foo(const char *) {}\n"
"void foo(const Bar &) {}\n"
"void $foo(char) {}\n"
"\n"
"void t()\n"
"{\n"
" @foo('a');\n"
"}\n"
);
QTest::newRow("infiniteLoopLocalTypedef_QTCREATORBUG-11999") << _(
"template<class MyTree>\n"
"class TreeConstIterator\n"
@@ -993,6 +954,73 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor()
F2TestCase(F2TestCase::FollowSymbolUnderCursorAction, singleDocument(source));
}
void CppEditorPlugin::test_FollowSymbolUnderCursor_followCall_data()
{
QTest::addColumn<QByteArray>("variableDeclaration"); // without semicolon, can be ""
QTest::addColumn<QByteArray>("callArgument");
QTest::addColumn<QByteArray>("expectedSignature"); // you might need to add a function
// declaration with such a signature
QTest::newRow("intLiteral-to-int")
<< _("")
<< _("5")
<< _("int");
QTest::newRow("charLiteral-to-const-char-ptr")
<< _("")
<< _("\"hoo\"")
<< _("const char *");
QTest::newRow("charLiteral-to-int")
<< _("")
<< _("'a'")
<< _("char");
QTest::newRow("charPtr-to-constCharPtr")
<< _("char *var = \"var\"")
<< _("var")
<< _("const char *");
QTest::newRow("charPtr-to-constCharPtr")
<< _("char *var = \"var\"")
<< _("var")
<< _("const char *");
QTest::newRow("constCharPtr-to-constCharPtr")
<< _("const char *var = \"var\"")
<< _("var")
<< _("const char *");
QTest::newRow("Bar-to-constBarRef")
<< _("Bar var")
<< _("var")
<< _("const Bar &");
}
void CppEditorPlugin::test_FollowSymbolUnderCursor_followCall()
{
QFETCH(QByteArray, variableDeclaration);
QFETCH(QByteArray, callArgument);
QFETCH(QByteArray, expectedSignature);
const QByteArray templateSource =
"class Bar {};\n"
"void fun(int);\n"
"void fun(const char *);\n"
"void fun(const Bar &);\n"
"void fun(char);\n"
"void fun(double);\n"
"\n"
"void t()\n"
"{\n"
" " + variableDeclaration + ";\n"
" @fun(" + callArgument + ");\n"
"}\n";
const QByteArray matchText = " fun(" + expectedSignature + ")";
const QByteArray replaceText = " $fun(" + expectedSignature + ")";
QByteArray source = templateSource;
source.replace(matchText, replaceText);
QVERIFY(source != templateSource);
F2TestCase(F2TestCase::FollowSymbolUnderCursorAction, singleDocument(source));
}
void CppEditorPlugin::test_FollowSymbolUnderCursor_multipleDocuments_data()
{
QTest::addColumn<QList<TestDocumentPtr> >("documents");

View File

@@ -629,21 +629,9 @@ public:
, m_newSourceFiles(newProjectInfo.sourceFiles())
{}
bool definesChanged() const
{
return m_new.defines() != m_old.defines();
}
bool configurationChanged() const
{
return definesChanged()
|| m_new.headerPaths() != m_old.headerPaths();
}
bool nothingChanged() const
{
return !configurationChanged() && m_new.sourceFiles() == m_old.sourceFiles();
}
bool definesChanged() const { return m_new.definesChanged(m_old); }
bool configurationChanged() const { return m_new.configurationChanged(m_old); }
bool configurationOrFilesChanged() const { return m_new.configurationOrFilesChanged(m_old); }
QSet<QString> addedFiles() const
{
@@ -735,8 +723,12 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn
ProjectInfo oldProjectInfo = d->m_projectToProjectsInfo.value(project);
if (oldProjectInfo.isValid()) {
ProjectInfoComparer comparer(oldProjectInfo, newProjectInfo);
if (comparer.nothingChanged())
if (!comparer.configurationOrFilesChanged()) {
// Some other attached data might have changed
d->m_projectToProjectsInfo.insert(project, newProjectInfo);
return QFuture<void>();
}
// If the project configuration changed, do a full reindexing
if (comparer.configurationChanged()) {

View File

@@ -49,6 +49,7 @@ ProjectPart::ProjectPart()
, languageExtensions(NoExtensions)
, qtVersion(UnknownQt)
, warningFlags(ProjectExplorer::ToolChain::WarningsDefault)
, selectedForBuilding(true)
{
}
@@ -137,6 +138,36 @@ ProjectInfo::ProjectInfo(QPointer<ProjectExplorer::Project> project)
: m_project(project)
{}
bool ProjectInfo::operator ==(const ProjectInfo &other) const
{
return m_project == other.m_project
&& m_projectParts == other.m_projectParts
&& m_compilerCallData == other.m_compilerCallData
&& m_headerPaths == other.m_headerPaths
&& m_sourceFiles == other.m_sourceFiles
&& m_defines == other.m_defines;
}
bool ProjectInfo::operator !=(const ProjectInfo &other) const
{
return !operator ==(other);
}
bool ProjectInfo::definesChanged(const ProjectInfo &other) const
{
return m_defines != other.m_defines;
}
bool ProjectInfo::configurationChanged(const ProjectInfo &other) const
{
return definesChanged(other) || m_headerPaths != other.m_headerPaths;
}
bool ProjectInfo::configurationOrFilesChanged(const ProjectInfo &other) const
{
return configurationChanged(other) || m_sourceFiles != other.m_sourceFiles;
}
bool ProjectInfo::isValid() const
{
return !m_project.isNull();
@@ -193,6 +224,7 @@ void ProjectInfo::clearProjectParts()
m_headerPaths.clear();
m_sourceFiles.clear();
m_defines.clear();
m_compilerCallData.clear();
}
const ProjectPart::HeaderPaths ProjectInfo::headerPaths() const
@@ -210,6 +242,16 @@ const QByteArray ProjectInfo::defines() const
return m_defines;
}
void ProjectInfo::setCompilerCallData(const CompilerCallData &data)
{
m_compilerCallData = data;
}
ProjectInfo::CompilerCallData ProjectInfo::compilerCallData() const
{
return m_compilerCallData;
}
namespace {
class ProjectFileCategorizer
{

View File

@@ -129,6 +129,7 @@ public: // fields
LanguageExtensions languageExtensions;
QtVersion qtVersion;
ProjectExplorer::ToolChain::WarningFlags warningFlags;
bool selectedForBuilding;
};
inline uint qHash(const ProjectPart::HeaderPath &key, uint seed = 0)
@@ -142,6 +143,12 @@ public:
bool isValid() const;
bool operator ==(const ProjectInfo &other) const;
bool operator !=(const ProjectInfo &other) const;
bool definesChanged(const ProjectInfo &other) const;
bool configurationChanged(const ProjectInfo &other) const;
bool configurationOrFilesChanged(const ProjectInfo &other) const;
QPointer<ProjectExplorer::Project> project() const;
const QList<ProjectPart::Ptr> projectParts() const;
@@ -153,10 +160,16 @@ public:
const QSet<QString> sourceFiles() const;
const QByteArray defines() const;
// Source file --> List of compiler calls
typedef QHash<QString, QList<QStringList>> CompilerCallData;
void setCompilerCallData(const CompilerCallData &data);
CompilerCallData compilerCallData() const;
private:
QPointer<ProjectExplorer::Project> m_project;
QList<ProjectPart::Ptr> m_projectParts;
// The members below are (re)calculated from the project parts once a part is appended.
CompilerCallData m_compilerCallData;
// The members below are (re)calculated from the project parts with finish()
ProjectPart::HeaderPaths m_headerPaths;
QSet<QString> m_sourceFiles;
QByteArray m_defines;

View File

@@ -1,8 +1,6 @@
import qbs 1.0
import qbs.FileInfo
import QtcPlugin
QtcPlugin {
name: "CppTools"

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "CVS"

View File

@@ -190,7 +190,6 @@ static inline bool fileNameMatch(const QString &f1, const QString &f2)
static bool isSimilarTo(const BreakpointParameters &data, const BreakpointResponse &needle)
{
// Clear hit.
// Clear miss.
if (needle.type != UnknownBreakpointType && data.type != UnknownBreakpointType
&& data.type != needle.type)
@@ -200,6 +199,10 @@ static bool isSimilarTo(const BreakpointParameters &data, const BreakpointRespon
if (data.address && data.address == needle.address)
return true;
// Clear hit.
if (data == needle)
return true;
// At least at a position we were looking for.
// FIXME: breaks multiple breakpoints at the same location
if (!data.fileName.isEmpty()

View File

@@ -1,7 +1,5 @@
import qbs 1.0
import QtcPlugin
QtcPlugin {
name: "Debugger"

View File

@@ -1140,14 +1140,13 @@ public:
DebuggerEngine *m_currentEngine;
DebuggerSettings *m_debuggerSettings;
QStringList m_arguments;
DebuggerToolTipManager *m_toolTipManager;
DebuggerToolTipManager m_toolTipManager;
CommonOptionsPage *m_commonOptionsPage;
DummyEngine *m_dummyEngine;
const QSharedPointer<GlobalDebuggerOptions> m_globalDebuggerOptions;
};
DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
m_toolTipManager(new DebuggerToolTipManager(this)),
m_dummyEngine(0),
m_globalDebuggerOptions(new GlobalDebuggerOptions)
{
@@ -2036,7 +2035,7 @@ void DebuggerPluginPrivate::setInitialState()
setBusyCursor(false);
m_reverseDirectionAction->setChecked(false);
m_reverseDirectionAction->setEnabled(false);
m_toolTipManager->closeAllToolTips();
m_toolTipManager.closeAllToolTips();
m_startAndDebugApplicationAction->setEnabled(true);
m_attachToQmlPortAction->setEnabled(true);
@@ -2269,14 +2268,14 @@ void DebuggerPluginPrivate::onModeChanged(IMode *mode)
m_mainWindow->onModeChanged(mode);
if (mode->id() != Constants::MODE_DEBUG) {
m_toolTipManager->leavingDebugMode();
m_toolTipManager.leavingDebugMode();
return;
}
if (IEditor *editor = EditorManager::currentEditor())
editor->widget()->setFocus();
m_toolTipManager->debugModeEntered();
m_toolTipManager.debugModeEntered();
}
void DebuggerPluginPrivate::showSettingsDialog()
@@ -2334,7 +2333,7 @@ void DebuggerPluginPrivate::sessionLoaded()
void DebuggerPluginPrivate::aboutToUnloadSession()
{
m_toolTipManager->sessionAboutToChange();
m_toolTipManager.sessionAboutToChange();
}
void DebuggerPluginPrivate::aboutToSaveSession()

View File

@@ -65,31 +65,45 @@
using namespace Core;
using namespace TextEditor;
namespace Debugger {
namespace Internal {
class DebuggerToolTipWidget;
QList<QPointer<DebuggerToolTipWidget>> m_tooltips;
bool m_debugModeActive;
// Expire tooltips after n days on (no longer load them) in order
// to avoid them piling up.
enum { toolTipsExpiryDays = 6 };
static const char sessionSettingsKeyC[] = "DebuggerToolTips";
static const char sessionDocumentC[] = "DebuggerToolTips";
static const char sessionVersionAttributeC[] = "version";
static const char toolTipElementC[] = "DebuggerToolTip";
static const char toolTipClassAttributeC[] = "class";
static const char fileNameAttributeC[] = "name";
static const char functionAttributeC[] = "function";
static const char textPositionAttributeC[] = "position";
static const char textLineAttributeC[] = "line";
static const char textColumnAttributeC[] = "column";
static const char offsetXAttributeC[] = "offset_x";
static const char offsetYAttributeC[] = "offset_y";
static const char engineTypeAttributeC[] = "engine";
static const char dateAttributeC[] = "date";
static const char treeElementC[] = "tree";
static const char treeExpressionAttributeC[] = "expression";
static const char treeInameAttributeC[] = "iname";
static const char modelElementC[] = "model";
static const char modelColumnCountAttributeC[] = "columncount";
static const char modelRowElementC[] = "row";
static const char modelItemElementC[] = "item";
const char sessionSettingsKeyC[] = "DebuggerToolTips";
const char sessionDocumentC[] = "DebuggerToolTips";
const char sessionVersionAttributeC[] = "version";
const char toolTipElementC[] = "DebuggerToolTip";
const char toolTipClassAttributeC[] = "class";
const char fileNameAttributeC[] = "name";
const char functionAttributeC[] = "function";
const char textPositionAttributeC[] = "position";
const char textLineAttributeC[] = "line";
const char textColumnAttributeC[] = "column";
const char offsetXAttributeC[] = "offset_x";
const char offsetYAttributeC[] = "offset_y";
const char engineTypeAttributeC[] = "engine";
const char dateAttributeC[] = "date";
const char treeElementC[] = "tree";
const char treeExpressionAttributeC[] = "expression";
const char treeInameAttributeC[] = "iname";
const char modelElementC[] = "model";
const char modelColumnCountAttributeC[] = "columncount";
const char modelRowElementC[] = "row";
const char modelItemElementC[] = "item";
static void purgeClosedToolTips()
{
for (int i = m_tooltips.size(); --i >= 0; )
if (!m_tooltips.at(i))
m_tooltips.removeAt(i);
}
// Forward a stream reader across end elements looking for the
// next start element of a desired type.
@@ -112,19 +126,6 @@ static bool readStartElement(QXmlStreamReader &r, const char *name)
return true;
}
#if 0
static void debugMode(const QAbstractItemModel *model)
{
QDebug nospace = qDebug().nospace();
nospace << model << '\n';
for (int r = 0; r < model->rowCount(); r++)
nospace << '#' << r << ' ' << model->data(model->index(r, 0)).toString() << '\n';
}
#endif
namespace Debugger {
namespace Internal {
// A label that can be dragged to drag something else.
class DraggableLabel : public QLabel
@@ -472,27 +473,134 @@ private:
StandardItemTreeModelBuilder m_builder;
};
class DebuggerToolTipWidget;
/*!
\class Debugger::Internal::DebuggerToolTipTreeView
class DebuggerToolTipManagerData
\brief The DebuggerToolTipTreeView class is a treeview that adapts its size
to the model contents (also while expanding)
to be used within DebuggerTreeViewToolTipWidget.
*/
class DebuggerToolTipTreeView : public QTreeView
{
public:
DebuggerToolTipManagerData()
: m_debugModeActive(false)
{}
explicit DebuggerToolTipTreeView(QWidget *parent = 0);
void purgeClosedToolTips()
{
for (int i = m_tooltips.size(); --i >= 0; )
if (!m_tooltips.at(i))
m_tooltips.removeAt(i);
}
QSize sizeHint() const { return m_size; }
QList<QPointer<DebuggerToolTipWidget> > m_tooltips;
bool m_debugModeActive;
void computeSize();
private:
void expandNode(const QModelIndex &idx);
void collapseNode(const QModelIndex &idx);
int computeHeight(const QModelIndex &index) const;
QSize m_size;
};
static DebuggerToolTipManagerData *d = 0;
DebuggerToolTipTreeView::DebuggerToolTipTreeView(QWidget *parent) :
QTreeView(parent)
{
setHeaderHidden(true);
setEditTriggers(NoEditTriggers);
setUniformRowHeights(true);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
connect(this, &QTreeView::collapsed, this, &DebuggerToolTipTreeView::computeSize,
Qt::QueuedConnection);
connect(this, &QTreeView::expanded, this, &DebuggerToolTipTreeView::computeSize,
Qt::QueuedConnection);
connect(this, &QTreeView::expanded,
this, &DebuggerToolTipTreeView::expandNode);
connect(this, &QTreeView::collapsed,
this, &DebuggerToolTipTreeView::collapseNode);
}
void DebuggerToolTipTreeView::expandNode(const QModelIndex &idx)
{
model()->setData(idx, true, LocalsExpandedRole);
}
void DebuggerToolTipTreeView::collapseNode(const QModelIndex &idx)
{
model()->setData(idx, false, LocalsExpandedRole);
}
int DebuggerToolTipTreeView::computeHeight(const QModelIndex &index) const
{
int s = rowHeight(index);
const int rowCount = model()->rowCount(index);
for (int i = 0; i < rowCount; ++i)
s += computeHeight(model()->index(i, 0, index));
return s;
}
void DebuggerToolTipTreeView::computeSize()
{
int columns = 30; // Decoration
int rows = 0;
bool rootDecorated = false;
if (QAbstractItemModel *m = model()) {
WatchTreeView::reexpand(this, m->index(0, 0));
const int columnCount = m->columnCount();
rootDecorated = m->rowCount() > 0;
if (rootDecorated)
for (int i = 0; i < columnCount; ++i) {
resizeColumnToContents(i);
columns += sizeHintForColumn(i);
}
if (columns < 100)
columns = 100; // Prevent toolbar from shrinking when displaying 'Previous'
rows += computeHeight(QModelIndex());
// Fit tooltip to screen, showing/hiding scrollbars as needed.
// Add a bit of space to account for tooltip border, and not
// touch the border of the screen.
QPoint pos(x(), y());
QTC_ASSERT(QApplication::desktop(), return);
QRect desktopRect = QApplication::desktop()->availableGeometry(pos);
const int maxWidth = desktopRect.right() - pos.x() - 5 - 5;
const int maxHeight = desktopRect.bottom() - pos.y() - 5 - 5;
if (columns > maxWidth)
rows += horizontalScrollBar()->height();
if (rows > maxHeight) {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
rows = maxHeight;
columns += verticalScrollBar()->width();
} else {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
if (columns > maxWidth) {
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
columns = maxWidth;
} else {
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
}
m_size = QSize(columns + 5, rows + 5);
setMinimumSize(m_size);
setMaximumSize(m_size);
setRootIsDecorated(rootDecorated);
}
QString DebuggerToolTipManager::treeModelClipboardContents(const QAbstractItemModel *model)
{
QString rc;
QTC_ASSERT(model, return rc);
QTextStream str(&rc);
DumpTreeModelVisitor v(model, DumpTreeModelVisitor::ClipboardMode, str);
v.run();
return rc;
}
/////////////////////////////////////////////////////////////////////////
@@ -503,8 +611,6 @@ static DebuggerToolTipManagerData *d = 0;
class DebuggerToolTipWidget : public QWidget
{
Q_OBJECT
public:
DebuggerToolTipWidget(const DebuggerToolTipContext &context);
@@ -519,10 +625,13 @@ public:
void releaseEngine();
void saveSessionData(QXmlStreamWriter &w) const;
void setWatchModel(QAbstractItemModel *watchModel);
void setWatchModel(WatchModelBase *watchModel);
void handleStackFrameCompleted(const QString &frameFile, const QString &frameFunction);
public slots:
void copy();
void positionShow(const TextEditorWidget *editorWidget);
void pin();
void handleItemIsExpanded(const QModelIndex &sourceIdx)
{
QTC_ASSERT(m_filterModel.sourceModel() == sourceIdx.model(), return);
@@ -531,10 +640,6 @@ public slots:
m_treeView->expand(mappedIdx);
}
void copy();
void positionShow(const TextEditorWidget *editorWidget);
void pin();
public:
bool m_isPinned;
QToolButton *m_toolButton;
@@ -546,6 +651,13 @@ public:
QStandardItemModel m_defaultModel;
};
static void hideAllToolTips()
{
purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
tw->hide();
}
void DebuggerToolTipWidget::pin()
{
if (m_isPinned)
@@ -662,6 +774,7 @@ DebuggerToolTipWidget::DebuggerToolTipWidget(const DebuggerToolTipContext &conte
m_titleLabel = new DraggableLabel(this);
m_titleLabel->setText(msgReleasedText());
m_titleLabel->setMinimumWidth(40); // Ensure a draggable area even if text is empty.
m_titleLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
auto toolBar = new QToolBar(this);
toolBar->setProperty("_q_custom_style_disabled", QVariant(true));
@@ -669,8 +782,8 @@ DebuggerToolTipWidget::DebuggerToolTipWidget(const DebuggerToolTipContext &conte
if (!pinIconSizes.isEmpty())
toolBar->setIconSize(pinIconSizes.front());
toolBar->addWidget(m_toolButton);
toolBar->addWidget(m_titleLabel);
toolBar->addWidget(copyButton);
toolBar->addWidget(m_titleLabel);
m_treeView = new DebuggerToolTipTreeView(this);
m_treeView->setFocusPolicy(Qt::NoFocus);
@@ -691,14 +804,14 @@ DebuggerToolTipWidget::DebuggerToolTipWidget(const DebuggerToolTipContext &conte
connect(copyButton, &QAbstractButton::clicked, this, &DebuggerToolTipWidget::copy);
}
void DebuggerToolTipWidget::setWatchModel(QAbstractItemModel *watchModel)
void DebuggerToolTipWidget::setWatchModel(WatchModelBase *watchModel)
{
QTC_ASSERT(watchModel, return);
m_filterModel.setSourceModel(watchModel);
connect(watchModel, SIGNAL(itemIsExpanded(QModelIndex)),
this, SLOT(handleItemIsExpanded(QModelIndex)), Qt::UniqueConnection);
connect(watchModel, SIGNAL(columnAdjustmentRequested()),
m_treeView, SLOT(computeSize()), Qt::UniqueConnection);
connect(watchModel, &WatchModelBase::itemIsExpanded,
this, &DebuggerToolTipWidget::handleItemIsExpanded, Qt::UniqueConnection);
connect(watchModel, &WatchModelBase::columnAdjustmentRequested,
m_treeView, &DebuggerToolTipTreeView::computeSize, Qt::UniqueConnection);
}
void DebuggerToolTipWidget::handleStackFrameCompleted(const QString &frameFile, const QString &frameFunction)
@@ -780,7 +893,7 @@ void DebuggerToolTipWidget::positionShow(const TextEditorWidget *editorWidget)
static DebuggerToolTipWidget *findOrCreateWidget(const DebuggerToolTipContext &context)
{
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
if (tw && tw->m_context.isSame(context))
return tw;
@@ -789,7 +902,7 @@ static DebuggerToolTipWidget *findOrCreateWidget(const DebuggerToolTipContext &c
tw->setObjectName(QLatin1String("DebuggerTreeViewToolTipWidget: ") + QLatin1String(context.iname));
tw->m_context.creationDate = QDate::currentDate();
d->m_tooltips.push_back(tw);
m_tooltips.push_back(tw);
return tw;
}
@@ -839,7 +952,7 @@ static QDate dateFromString(const QString &date)
QDate();
}
static void loadSessionDataI(QXmlStreamReader &r)
static void loadSessionDataHelper(QXmlStreamReader &r)
{
if (!readStartElement(r, toolTipElementC))
return;
@@ -919,118 +1032,6 @@ void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const
w.writeEndElement();
}
/*!
\class Debugger::Internal::DebuggerToolTipTreeView
\brief The DebuggerToolTipTreeView class is a treeview that adapts its size
to the model contents (also while expanding)
to be used within DebuggerTreeViewToolTipWidget.
*/
DebuggerToolTipTreeView::DebuggerToolTipTreeView(QWidget *parent) :
QTreeView(parent)
{
setHeaderHidden(true);
setEditTriggers(NoEditTriggers);
setUniformRowHeights(true);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(computeSize()),
Qt::QueuedConnection);
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(computeSize()),
Qt::QueuedConnection);
connect(this, SIGNAL(expanded(QModelIndex)),
SLOT(expandNode(QModelIndex)));
connect(this, SIGNAL(collapsed(QModelIndex)),
SLOT(collapseNode(QModelIndex)));
}
void DebuggerToolTipTreeView::expandNode(const QModelIndex &idx)
{
model()->setData(idx, true, LocalsExpandedRole);
}
void DebuggerToolTipTreeView::collapseNode(const QModelIndex &idx)
{
model()->setData(idx, false, LocalsExpandedRole);
}
int DebuggerToolTipTreeView::computeHeight(const QModelIndex &index) const
{
int s = rowHeight(index);
const int rowCount = model()->rowCount(index);
for (int i = 0; i < rowCount; ++i)
s += computeHeight(model()->index(i, 0, index));
return s;
}
void DebuggerToolTipTreeView::computeSize()
{
int columns = 30; // Decoration
int rows = 0;
bool rootDecorated = false;
if (QAbstractItemModel *m = model()) {
WatchTreeView::reexpand(this, m->index(0, 0));
const int columnCount = m->columnCount();
rootDecorated = m->rowCount() > 0;
if (rootDecorated)
for (int i = 0; i < columnCount; ++i) {
resizeColumnToContents(i);
columns += sizeHintForColumn(i);
}
if (columns < 100)
columns = 100; // Prevent toolbar from shrinking when displaying 'Previous'
rows += computeHeight(QModelIndex());
// Fit tooltip to screen, showing/hiding scrollbars as needed.
// Add a bit of space to account for tooltip border, and not
// touch the border of the screen.
QPoint pos(x(), y());
QTC_ASSERT(QApplication::desktop(), return);
QRect desktopRect = QApplication::desktop()->availableGeometry(pos);
const int maxWidth = desktopRect.right() - pos.x() - 5 - 5;
const int maxHeight = desktopRect.bottom() - pos.y() - 5 - 5;
if (columns > maxWidth)
rows += horizontalScrollBar()->height();
if (rows > maxHeight) {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
rows = maxHeight;
columns += verticalScrollBar()->width();
} else {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
if (columns > maxWidth) {
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
columns = maxWidth;
} else {
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
}
m_size = QSize(columns + 5, rows + 5);
setMinimumSize(m_size);
setMaximumSize(m_size);
setRootIsDecorated(rootDecorated);
}
QString DebuggerToolTipManager::treeModelClipboardContents(const QAbstractItemModel *model)
{
QString rc;
QTC_ASSERT(model, return rc);
QTextStream str(&rc);
DumpTreeModelVisitor v(model, DumpTreeModelVisitor::ClipboardMode, str);
v.run();
return rc;
}
/*!
\class Debugger::Internal::DebuggerToolTipManager
@@ -1046,19 +1047,13 @@ QString DebuggerToolTipManager::treeModelClipboardContents(const QAbstractItemMo
(by file name and function) acquire the engine, others release.
*/
static DebuggerToolTipManager *m_instance = 0;
DebuggerToolTipManager::DebuggerToolTipManager(QObject *parent) :
QObject(parent)
DebuggerToolTipManager::DebuggerToolTipManager()
{
d = new DebuggerToolTipManagerData;
m_instance = this;
}
DebuggerToolTipManager::~DebuggerToolTipManager()
{
delete d;
m_instance = 0;
}
void DebuggerToolTipManager::registerEngine(DebuggerEngine *)
@@ -1066,11 +1061,42 @@ void DebuggerToolTipManager::registerEngine(DebuggerEngine *)
loadSessionData();
}
void DebuggerToolTipManager::slotUpdateVisibleToolTips()
{
purgeClosedToolTips();
if (m_tooltips.isEmpty())
return;
if (!m_debugModeActive) {
hideAllToolTips();
return;
}
BaseTextEditor *toolTipEditor = BaseTextEditor::currentTextEditor();
if (!toolTipEditor) {
hideAllToolTips();
return;
}
const QString fileName = toolTipEditor->textDocument()->filePath();
if (fileName.isEmpty()) {
hideAllToolTips();
return;
}
// Reposition and show all tooltips of that file.
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) {
if (tw->fileName() == fileName)
tw->positionShow(toolTipEditor->editorWidget());
else
tw->hide();
}
}
void DebuggerToolTipManager::updateEngine(DebuggerEngine *engine)
{
QTC_ASSERT(engine, return);
d->purgeClosedToolTips();
if (d->m_tooltips.isEmpty())
purgeClosedToolTips();
if (m_tooltips.isEmpty())
return;
// Stack frame changed: All tooltips of that file acquire the engine,
@@ -1085,7 +1111,7 @@ void DebuggerToolTipManager::updateEngine(DebuggerEngine *engine)
function = frame.function;
}
}
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
tw->handleStackFrameCompleted(fileName, function);
slotUpdateVisibleToolTips(); // Move out when stepping in same file.
}
@@ -1093,7 +1119,7 @@ void DebuggerToolTipManager::updateEngine(DebuggerEngine *engine)
void DebuggerToolTipManager::deregisterEngine(DebuggerEngine *engine)
{
QTC_ASSERT(engine, return);
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
if (tw && tw->m_context.engineType == engine->objectName())
tw->releaseEngine();
saveSessionData();
@@ -1101,7 +1127,7 @@ void DebuggerToolTipManager::deregisterEngine(DebuggerEngine *engine)
bool DebuggerToolTipManager::hasToolTips()
{
return !d->m_tooltips.isEmpty();
return !m_tooltips.isEmpty();
}
void DebuggerToolTipManager::showToolTip
@@ -1118,37 +1144,6 @@ void DebuggerToolTipManager::showToolTip
Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow());
}
bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e)
{
if (!hasToolTips())
return false;
switch (e->type()) {
case QEvent::Move: { // Move along with parent (toplevel)
const QMoveEvent *me = static_cast<const QMoveEvent *>(e);
const QPoint dist = me->pos() - me->oldPos();
d->purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
if (tw->isVisible())
tw->move(tw->pos() + dist);
}
break;
case QEvent::WindowStateChange: { // Hide/Show along with parent (toplevel)
const QWindowStateChangeEvent *se = static_cast<const QWindowStateChangeEvent *>(e);
const bool wasMinimized = se->oldState() & Qt::WindowMinimized;
const bool isMinimized = static_cast<const QWidget *>(o)->windowState() & Qt::WindowMinimized;
if (wasMinimized ^ isMinimized) {
d->purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
tw->setVisible(!isMinimized);
}
}
break;
default:
break;
}
return false;
}
void DebuggerToolTipManager::sessionAboutToChange()
{
closeAllToolTips();
@@ -1161,19 +1156,19 @@ void DebuggerToolTipManager::loadSessionData()
r.readNextStartElement();
if (r.tokenType() == QXmlStreamReader::StartElement && r.name() == QLatin1String(sessionDocumentC))
while (!r.atEnd())
loadSessionDataI(r);
loadSessionDataHelper(r);
}
void DebuggerToolTipManager::saveSessionData()
{
QString data;
d->purgeClosedToolTips();
purgeClosedToolTips();
QXmlStreamWriter w(&data);
w.writeStartDocument();
w.writeStartElement(QLatin1String(sessionDocumentC));
w.writeAttribute(QLatin1String(sessionVersionAttributeC), QLatin1String("1.0"));
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
if (tw->isPinned())
tw->saveSessionData(w);
w.writeEndDocument();
@@ -1183,119 +1178,13 @@ void DebuggerToolTipManager::saveSessionData()
void DebuggerToolTipManager::closeAllToolTips()
{
d->purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
tw->close();
d->m_tooltips.clear();
m_tooltips.clear();
}
void DebuggerToolTipManager::hide()
{
d->purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips)
tw->hide();
}
void DebuggerToolTipManager::slotUpdateVisibleToolTips()
{
d->purgeClosedToolTips();
if (d->m_tooltips.isEmpty())
return;
if (!d->m_debugModeActive) {
hide();
return;
}
BaseTextEditor *toolTipEditor = BaseTextEditor::currentTextEditor();
if (!toolTipEditor) {
hide();
return;
}
const QString fileName = toolTipEditor->textDocument()->filePath();
if (fileName.isEmpty()) {
hide();
return;
}
// Reposition and show all tooltips of that file.
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips) {
if (tw->fileName() == fileName)
tw->positionShow(toolTipEditor->editorWidget());
else
tw->hide();
}
}
void DebuggerToolTipManager::slotDebuggerStateChanged(DebuggerState state)
{
const QObject *engine = sender();
QTC_ASSERT(engine, return);
// Release at earliest possible convenience.
switch (state) {
case InferiorShutdownRequested:
case EngineShutdownRequested:
case DebuggerFinished:
case EngineShutdownOk: {
break;
}
default:
break;
}
}
void DebuggerToolTipManager::slotEditorOpened(IEditor *e)
{
// Move tooltip along when scrolled.
if (BaseTextEditor *textEditor = qobject_cast<BaseTextEditor *>(e)) {
TextEditorWidget *widget = textEditor->editorWidget();
connect(widget->verticalScrollBar(), &QScrollBar::valueChanged,
this, &DebuggerToolTipManager::slotUpdateVisibleToolTips);
connect(widget, &TextEditorWidget::tooltipOverrideRequested,
this, &DebuggerToolTipManager::slotTooltipOverrideRequested);
}
}
void DebuggerToolTipManager::debugModeEntered()
{
// Hook up all signals in debug mode.
if (!d->m_debugModeActive) {
d->m_debugModeActive = true;
QWidget *topLevel = ICore::mainWindow()->topLevelWidget();
topLevel->installEventFilter(this);
EditorManager *em = EditorManager::instance();
connect(em, &EditorManager::currentEditorChanged,
this, &DebuggerToolTipManager::slotUpdateVisibleToolTips);
connect(em, &EditorManager::editorOpened,
this, &DebuggerToolTipManager::slotEditorOpened);
foreach (IEditor *e, DocumentModel::editorsForOpenedDocuments())
slotEditorOpened(e);
// Position tooltips delayed once all the editor placeholder layouting is done.
if (!d->m_tooltips.isEmpty())
QTimer::singleShot(0, this, SLOT(slotUpdateVisibleToolTips()));
}
}
void DebuggerToolTipManager::leavingDebugMode()
{
// Remove all signals in debug mode.
if (d->m_debugModeActive) {
d->m_debugModeActive = false;
hide();
if (QWidget *topLevel = ICore::mainWindow()->topLevelWidget())
topLevel->removeEventFilter(this);
foreach (IEditor *e, DocumentModel::editorsForOpenedDocuments()) {
if (BaseTextEditor *toolTipEditor = qobject_cast<BaseTextEditor *>(e)) {
toolTipEditor->editorWidget()->verticalScrollBar()->disconnect(this);
toolTipEditor->disconnect(this);
}
}
EditorManager::instance()->disconnect(this);
}
}
void DebuggerToolTipManager::slotTooltipOverrideRequested
static void slotTooltipOverrideRequested
(TextEditorWidget *editorWidget, const QPoint &point, int pos, bool *handled)
{
QTC_ASSERT(handled, return);
@@ -1319,7 +1208,7 @@ void DebuggerToolTipManager::slotTooltipOverrideRequested
context.expression = fixCppExpression(raw);
if (context.expression.isEmpty()) {
const Utils::WidgetContent widgetContent(new QLabel(tr("No valid expression")), true);
const Utils::WidgetContent widgetContent(new QLabel(DebuggerToolTipManager::tr("No valid expression")), true);
Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow());
*handled = true;
return;
@@ -1331,7 +1220,7 @@ void DebuggerToolTipManager::slotTooltipOverrideRequested
if (context.expression.isEmpty())
context.expression = localVariable->name;
context.iname = localVariable->iname;
showToolTip(context, engine);
DebuggerToolTipManager::showToolTip(context, engine);
*handled = true;
return;
}
@@ -1345,18 +1234,97 @@ void DebuggerToolTipManager::slotTooltipOverrideRequested
}
static void slotEditorOpened(IEditor *e)
{
// Move tooltip along when scrolled.
if (BaseTextEditor *textEditor = qobject_cast<BaseTextEditor *>(e)) {
TextEditorWidget *widget = textEditor->editorWidget();
QObject::connect(widget->verticalScrollBar(), &QScrollBar::valueChanged,
&DebuggerToolTipManager::slotUpdateVisibleToolTips);
QObject::connect(widget, &TextEditorWidget::tooltipOverrideRequested,
slotTooltipOverrideRequested);
}
}
void DebuggerToolTipManager::debugModeEntered()
{
// Hook up all signals in debug mode.
if (!m_debugModeActive) {
m_debugModeActive = true;
QWidget *topLevel = ICore::mainWindow()->topLevelWidget();
topLevel->installEventFilter(this);
EditorManager *em = EditorManager::instance();
connect(em, &EditorManager::currentEditorChanged,
&DebuggerToolTipManager::slotUpdateVisibleToolTips);
connect(em, &EditorManager::editorOpened, slotEditorOpened);
foreach (IEditor *e, DocumentModel::editorsForOpenedDocuments())
slotEditorOpened(e);
// Position tooltips delayed once all the editor placeholder layouting is done.
if (!m_tooltips.isEmpty())
QTimer::singleShot(0, this, SLOT(slotUpdateVisibleToolTips()));
}
}
void DebuggerToolTipManager::leavingDebugMode()
{
// Remove all signals in debug mode.
if (m_debugModeActive) {
m_debugModeActive = false;
hideAllToolTips();
if (QWidget *topLevel = ICore::mainWindow()->topLevelWidget())
topLevel->removeEventFilter(this);
foreach (IEditor *e, DocumentModel::editorsForOpenedDocuments()) {
if (BaseTextEditor *toolTipEditor = qobject_cast<BaseTextEditor *>(e)) {
toolTipEditor->editorWidget()->verticalScrollBar()->disconnect(this);
toolTipEditor->disconnect(this);
}
}
EditorManager::instance()->disconnect(this);
}
}
DebuggerToolTipContexts DebuggerToolTipManager::treeWidgetExpressions
(DebuggerEngine *, const QString &fileName, const QString &function)
{
DebuggerToolTipContexts rc;
foreach (const QPointer<DebuggerToolTipWidget> &tw, d->m_tooltips) {
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) {
if (tw && tw->context().matchesFrame(fileName, function))
rc.push_back(tw->context());
}
return rc;
}
bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e)
{
if (m_tooltips.isEmpty())
return false;
switch (e->type()) {
case QEvent::Move: { // Move along with parent (toplevel)
const QMoveEvent *me = static_cast<const QMoveEvent *>(e);
const QPoint dist = me->pos() - me->oldPos();
purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
if (tw->isVisible())
tw->move(tw->pos() + dist);
}
break;
case QEvent::WindowStateChange: { // Hide/Show along with parent (toplevel)
const QWindowStateChangeEvent *se = static_cast<const QWindowStateChangeEvent *>(e);
const bool wasMinimized = se->oldState() & Qt::WindowMinimized;
const bool isMinimized = static_cast<const QWidget *>(o)->windowState() & Qt::WindowMinimized;
if (wasMinimized ^ isMinimized) {
purgeClosedToolTips();
foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips)
tw->setVisible(!isMinimized);
}
}
break;
default:
break;
}
return false;
}
} // namespace Internal
} // namespace Debugger
#include "debuggertooltipmanager.moc"

View File

@@ -33,18 +33,16 @@
#include "debuggerconstants.h"
#include <QCoreApplication>
#include <QDate>
#include <QPointer>
#include <QTreeView>
#include <QPoint>
QT_BEGIN_NAMESPACE
class QDebug;
class QAbstractItemModel;
QT_END_NAMESPACE
namespace Core { class IEditor; }
namespace TextEditor { class BaseTextEditor; class TextEditorWidget; }
namespace Debugger {
class DebuggerEngine;
namespace Internal {
@@ -72,36 +70,12 @@ public:
typedef QList<DebuggerToolTipContext> DebuggerToolTipContexts;
QDebug operator<<(QDebug, const DebuggerToolTipContext &);
class DebuggerToolTipTreeView : public QTreeView
{
Q_OBJECT
public:
explicit DebuggerToolTipTreeView(QWidget *parent = 0);
QAbstractItemModel *swapModel(QAbstractItemModel *model);
QSize sizeHint() const { return m_size; }
private slots:
void computeSize();
void expandNode(const QModelIndex &idx);
void collapseNode(const QModelIndex &idx);
private:
int computeHeight(const QModelIndex &index) const;
QSize m_size;
};
class DebuggerToolTipManager : public QObject
{
Q_OBJECT
public:
explicit DebuggerToolTipManager(QObject *parent = 0);
DebuggerToolTipManager();
~DebuggerToolTipManager();
static void registerEngine(DebuggerEngine *engine);
@@ -120,21 +94,15 @@ public:
static QString treeModelClipboardContents(const QAbstractItemModel *model);
public slots:
void debugModeEntered();
void leavingDebugMode();
void sessionAboutToChange();
static void loadSessionData();
static void saveSessionData();
static void closeAllToolTips();
static void hide();
private slots:
public slots:
static void slotUpdateVisibleToolTips();
void slotDebuggerStateChanged(Debugger::DebuggerState);
void slotEditorOpened(Core::IEditor *);
void slotTooltipOverrideRequested(TextEditor::TextEditorWidget *editorWidget,
const QPoint &point, int pos, bool *handled);
};
} // namespace Internal

Some files were not shown because too many files have changed in this diff Show More